Browse Source

Merge pull request #1457 from zhuangwei123/master

[bsp/ls1cdev]添加自引导特性,添加配置选项
Bernard Xiong 7 years ago
parent
commit
1ad1bd3c37

+ 28 - 15
bsp/ls1cdev/.config

@@ -228,20 +228,6 @@ CONFIG_LWIP_NETIF_LOOPBACK=0
 # RT-Thread online packages
 #
 
-#
-# system packages
-#
-
-#
-# RT-Thread GUI Engine
-#
-# CONFIG_PKG_USING_GUIENGINE is not set
-# CONFIG_PKG_USING_LVGL is not set
-# CONFIG_PKG_USING_LWEXT4 is not set
-# CONFIG_PKG_USING_PARTITION is not set
-# CONFIG_PKG_USING_SQLITE is not set
-# CONFIG_PKG_USING_RTI is not set
-
 #
 # IoT - internet of things
 #
@@ -271,6 +257,7 @@ CONFIG_LWIP_NETIF_LOOPBACK=0
 # CONFIG_PKG_USING_COAP is not set
 # CONFIG_PKG_USING_NOPOLL is not set
 # CONFIG_PKG_USING_NETUTILS is not set
+# CONFIG_PKG_USING_ONENET is not set
 
 #
 # security packages
@@ -289,6 +276,7 @@ CONFIG_LWIP_NETIF_LOOPBACK=0
 # multimedia packages
 #
 # CONFIG_PKG_USING_OPENMV is not set
+# CONFIG_PKG_USING_MUPDF is not set
 
 #
 # tools packages
@@ -299,6 +287,26 @@ CONFIG_LWIP_NETIF_LOOPBACK=0
 # CONFIG_PKG_USING_SYSTEMVIEW is not set
 # CONFIG_PKG_USING_IPERF is not set
 
+#
+# system packages
+#
+
+#
+# RT-Thread GUI Engine
+#
+# CONFIG_PKG_USING_GUIENGINE is not set
+# CONFIG_PKG_USING_LWEXT4 is not set
+# CONFIG_PKG_USING_PARTITION is not set
+# CONFIG_PKG_USING_SQLITE is not set
+# CONFIG_PKG_USING_RTI is not set
+# CONFIG_PKG_USING_LITTLEVGL2RTT is not set
+
+#
+# peripheral libraries and drivers
+#
+# CONFIG_PKG_USING_STM32F4_HAL is not set
+# CONFIG_PKG_USING_STM32F4_DRIVERS is not set
+
 #
 # miscellaneous packages
 #
@@ -306,13 +314,18 @@ CONFIG_LWIP_NETIF_LOOPBACK=0
 # CONFIG_PKG_USING_MINILZO is not set
 # CONFIG_PKG_USING_QUICKLZ is not set
 # CONFIG_PKG_USING_MULTIBUTTON is not set
-# CONFIG_PKG_USING_SAMPLES is not set
 # CONFIG_PKG_USING_CANFESTIVAL is not set
 
+#
+# sample package
+#
+# CONFIG_PKG_USING_SAMPLES is not set
+
 #
 # example package: hello
 #
 # CONFIG_PKG_USING_HELLO is not set
+# CONFIG_RT_USING_SELF_BOOT is not set
 CONFIG_RT_USING_UART2=y
 CONFIG_RT_UART_RX_BUFFER_SIZE=64
 CONFIG_RT_USING_GMAC_INT_MODE=y

+ 9 - 0
bsp/ls1cdev/SConstruct

@@ -12,6 +12,8 @@ from building import *
 
 TARGET = 'rtthread.' + rtconfig.TARGET_EXT
 
+rtconfig.AFLAGS += ' -I' + str(Dir('#'))
+
 env = Environment(tools = ['mingw'],
 	AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
 	CC = rtconfig.CC, CCFLAGS = rtconfig.CFLAGS,
@@ -24,6 +26,13 @@ Export('rtconfig')
 
 # prepare building environment
 objs = PrepareBuilding(env, RTT_ROOT)
+
+if GetDepend('RT_USING_SELF_BOOT'):
+    rtconfig.LFLAGS += " -Ttext 0x80010000"
+else:
+	rtconfig.LFLAGS += " -Ttext 0x80200000"    
+env.Replace(LINKFLAGS = rtconfig.LFLAGS)
+
     
 if GetDepend('RT_USING_RTGUI'):
     objs = objs + SConscript(RTT_ROOT + '/examples/gui/SConscript', variant_dir='build/examples/gui', duplicate=0)

+ 4 - 1
bsp/ls1cdev/drivers/board.c

@@ -100,6 +100,9 @@ void rt_hw_board_init(void)
 	/* init hardware interrupt */
 	rt_hw_interrupt_init();
 
+	/* clear bev */
+	write_c0_status(read_c0_status()&(~(1<<22)));
+
 	/* copy vector */
 	rt_memcpy((void *)A_K0BASE, tlb_refill_exception, 0x80);
 	rt_memcpy((void *)(A_K0BASE + 0x180), general_exception, 0x80);
@@ -109,7 +112,7 @@ void rt_hw_board_init(void)
 	invalidate_icache_all();
 	
 #ifdef RT_USING_HEAP
-		rt_system_heap_init((void*)&__bss_end, (void*)RT_HW_HEAP_END);
+	rt_system_heap_init((void*)&__bss_end, (void*)RT_HW_HEAP_END);
 #endif
 
 #ifdef RT_USING_SERIAL

+ 15 - 1
bsp/ls1cdev/drivers/net/synopGMAC.c

@@ -31,6 +31,8 @@
 #include "mii.c"
 #include "synopGMAC_debug.h"
 #include <ls1c.h>
+#include "ls1c_pin.h"
+
 #define RMII
 
 #define Gmac_base			0xbfe10000
@@ -865,10 +867,22 @@ int rt_hw_eth_init(void)
 	u64 base_addr = Gmac_base; 
 	struct synopGMACNetworkAdapter * synopGMACadapter;
 	static u8 mac_addr0[6] = DEFAULT_MAC_ADDRESS;
-
+	int index;
+	
 	rt_sem_init(&sem_ack, "tx_ack", 1, RT_IPC_FLAG_FIFO);
 	rt_sem_init(&sem_lock, "eth_lock", 1, RT_IPC_FLAG_FIFO);
 
+	for(index=21; index<=30;index++)
+	{
+		pin_set_purpose(index, PIN_PURPOSE_OTHER);
+		pin_set_remap(index, PIN_REMAP_DEFAULT);
+	}
+	pin_set_purpose(35, PIN_PURPOSE_OTHER);
+	pin_set_remap(35, PIN_REMAP_DEFAULT);
+	*((volatile unsigned int *)0xbfd00424) &= ~(7 << 28);
+	*((volatile unsigned int *)0xbfd00424) |= (1 << 30); //wl rmii
+
+
 
 	memset(&eth_dev, 0, sizeof(eth_dev));
 	synopGMACadapter = (struct synopGMACNetworkAdapter * )plat_alloc_memory(sizeof (struct synopGMACNetworkAdapter));

+ 4 - 0
bsp/ls1cdev/kconfig

@@ -19,6 +19,10 @@ config $PKGS_DIR
 source "$RTT_DIR/Kconfig"
 source "$PKGS_DIR/Kconfig"
 
+config RT_USING_SELF_BOOT
+    bool "Enable RT-Thread run without bootloader"
+    default n
+	
 if RT_USING_SERIAL
 config RT_USING_UART2
     bool "Using RT_USING_UART2"

+ 108 - 106
bsp/ls1cdev/libraries/ls1c_pin.c

@@ -1,4 +1,4 @@
-// 引脚功能(普通gpio,pwm,复用等)相关接口
+// 寮曡剼鍔熻兘(鏅�€歡pio锛宲wm锛屽�鐢ㄧ瓑)鐩稿叧鎺ュ彛
 
 
 #include "ls1c_public.h"
@@ -8,21 +8,21 @@
 
 
 /*
- * 把指定pin设置为指定用途(普通gpio,非gpio)
- * @gpio gpio引脚编号
- * @purpose 用途
+ * 鎶婃寚瀹歱in璁剧疆涓烘寚瀹氱敤閫�(鏅�€歡pio锛岄潪gpio)
+ * @gpio gpio寮曡剼缂栧彿
+ * @purpose 鐢ㄩ€�
  */
 void pin_set_purpose(unsigned int gpio, pin_purpose_t purpose)
 {
-    volatile unsigned int *gpio_cfgx;           // GPIO_CFGx寄存器
+    volatile unsigned int *gpio_cfgx;           // GPIO_CFGx瀵勫瓨鍣�
     unsigned int pin = GPIO_GET_PIN(gpio);
 
     gpio_cfgx = gpio_get_cfg_reg(gpio);
-    if (PIN_PURPOSE_GPIO == purpose)            // 引脚用作普通gpio
+    if (PIN_PURPOSE_GPIO == purpose)            // 寮曡剼鐢ㄤ綔鏅�€歡pio
     {
         reg_set_one_bit(gpio_cfgx, pin);
     }
-    else                                        // 引脚用作其它功能(非gpio)
+    else                                        // 寮曡剼鐢ㄤ綔鍏跺畠鍔熻兘(闈瀏pio)
     {
         reg_clr_one_bit(gpio_cfgx, pin);
     }
@@ -33,116 +33,118 @@ void pin_set_purpose(unsigned int gpio, pin_purpose_t purpose)
 
 
 /*
- * 设置指定pin为第n复用
- * @gpio gpio编号
- * @remap 第n复用
+ * 璁剧疆鎸囧畾pin涓虹�n澶嶇敤
+ * @gpio gpio缂栧彿
+ * @remap 绗琻澶嶇敤
  */
 void pin_set_remap(unsigned int gpio, pin_remap_t remap)
 {
-    volatile unsigned int *reg = NULL;          // 复用寄存器
+    volatile unsigned int *reg = NULL;          // 澶嶇敤瀵勫瓨鍣�
     unsigned int port = GPIO_GET_PORT(gpio);
     unsigned int pin  = GPIO_GET_PIN(gpio);
-	int i;
+    int i;
 
-	/*指定全部pin复用为0*/
-	for(i =0; i <=4; i++)
-	{
-		reg = (volatile unsigned int *)((LS1C_CBUS_FIRST0)+((port)*0x04)+((i)*0x10));
-		// 置0
-		reg_clr_one_bit(reg, pin);		
-	}		
+    /*鎸囧畾鍏ㄩ儴pin澶嶇敤涓�0*/
+    for (i = 0; i <= 4; i++)
+    {
+        reg = (volatile unsigned int *)((LS1C_CBUS_FIRST0) + ((port) * 0x04) + ((i) * 0x10));
+        // 缃�0
+        reg_clr_one_bit(reg, pin);
+    }
+
+    if (remap == PIN_REMAP_DEFAULT) return;
 
     switch (port)
     {
-        case 0:
-            switch (remap)
-            {
-                case PIN_REMAP_FIRST:
-                    reg = (volatile unsigned int *)LS1C_CBUS_FIRST0;
-                    break;
-                case PIN_REMAP_SECOND:
-                    reg = (volatile unsigned int *)LS1C_CBUS_SECOND0;
-                    break;
-                case PIN_REMAP_THIRD:
-                    reg = (volatile unsigned int *)LS1C_CBUS_THIRD0;
-                    break;
-                case PIN_REMAP_FOURTH:
-                    reg = (volatile unsigned int *)LS1C_CBUS_FOURTH0;
-                    break;
-                case PIN_REMAP_FIFTH:
-                    reg = (volatile unsigned int *)LS1C_CBUS_FIFTH0;
-                    break;
-            }
-            break;
-
-        case 1:
-            switch (remap)
-            {
-                case PIN_REMAP_FIRST:
-                    reg = (volatile unsigned int *)LS1C_CBUS_FIRST1;
-                    break;
-                case PIN_REMAP_SECOND:
-                    reg = (volatile unsigned int *)LS1C_CBUS_SECOND1;
-                    break;
-                case PIN_REMAP_THIRD:
-                    reg = (volatile unsigned int *)LS1C_CBUS_THIRD1;
-                    break;
-                case PIN_REMAP_FOURTH:
-                    reg = (volatile unsigned int *)LS1C_CBUS_FOURTH1;
-                    break;
-                case PIN_REMAP_FIFTH:
-                    reg = (volatile unsigned int *)LS1C_CBUS_FIFTH1;
-                    break;
-            }
-            break;
-
-        case 2:
-            switch (remap)
-            {
-                case PIN_REMAP_FIRST:
-                    reg = (volatile unsigned int *)LS1C_CBUS_FIRST2;
-                    break;
-                case PIN_REMAP_SECOND:
-                    reg = (volatile unsigned int *)LS1C_CBUS_SECOND2;
-                    break;
-                case PIN_REMAP_THIRD:
-                    reg = (volatile unsigned int *)LS1C_CBUS_THIRD2;
-                    break;
-                case PIN_REMAP_FOURTH:
-                    reg = (volatile unsigned int *)LS1C_CBUS_FOURTH2;
-                    break;
-                case PIN_REMAP_FIFTH:
-                    reg = (volatile unsigned int *)LS1C_CBUS_FIFTH2;
-                    break;
-            }
-            break;
-
-        case 3:
-            switch (remap)
-            {
-                case PIN_REMAP_FIRST:
-                    reg = (volatile unsigned int *)LS1C_CBUS_FIRST3;
-                    break;
-                case PIN_REMAP_SECOND:
-                    reg = (volatile unsigned int *)LS1C_CBUS_SECOND3;
-                    break;
-                case PIN_REMAP_THIRD:
-                    reg = (volatile unsigned int *)LS1C_CBUS_THIRD3;
-                    break;
-                case PIN_REMAP_FOURTH:
-                    reg = (volatile unsigned int *)LS1C_CBUS_FOURTH3;
-                    break;
-                case PIN_REMAP_FIFTH:
-                    reg = (volatile unsigned int *)LS1C_CBUS_FIFTH3;
-                    break;
-            }
-            break;
-
-        default:
-            return ;
+    case 0:
+        switch (remap)
+        {
+        case PIN_REMAP_FIRST:
+            reg = (volatile unsigned int *)LS1C_CBUS_FIRST0;
+            break;
+        case PIN_REMAP_SECOND:
+            reg = (volatile unsigned int *)LS1C_CBUS_SECOND0;
+            break;
+        case PIN_REMAP_THIRD:
+            reg = (volatile unsigned int *)LS1C_CBUS_THIRD0;
+            break;
+        case PIN_REMAP_FOURTH:
+            reg = (volatile unsigned int *)LS1C_CBUS_FOURTH0;
+            break;
+        case PIN_REMAP_FIFTH:
+            reg = (volatile unsigned int *)LS1C_CBUS_FIFTH0;
+            break;
+        }
+        break;
+
+    case 1:
+        switch (remap)
+        {
+        case PIN_REMAP_FIRST:
+            reg = (volatile unsigned int *)LS1C_CBUS_FIRST1;
+            break;
+        case PIN_REMAP_SECOND:
+            reg = (volatile unsigned int *)LS1C_CBUS_SECOND1;
+            break;
+        case PIN_REMAP_THIRD:
+            reg = (volatile unsigned int *)LS1C_CBUS_THIRD1;
+            break;
+        case PIN_REMAP_FOURTH:
+            reg = (volatile unsigned int *)LS1C_CBUS_FOURTH1;
+            break;
+        case PIN_REMAP_FIFTH:
+            reg = (volatile unsigned int *)LS1C_CBUS_FIFTH1;
+            break;
+        }
+        break;
+
+    case 2:
+        switch (remap)
+        {
+        case PIN_REMAP_FIRST:
+            reg = (volatile unsigned int *)LS1C_CBUS_FIRST2;
+            break;
+        case PIN_REMAP_SECOND:
+            reg = (volatile unsigned int *)LS1C_CBUS_SECOND2;
+            break;
+        case PIN_REMAP_THIRD:
+            reg = (volatile unsigned int *)LS1C_CBUS_THIRD2;
+            break;
+        case PIN_REMAP_FOURTH:
+            reg = (volatile unsigned int *)LS1C_CBUS_FOURTH2;
+            break;
+        case PIN_REMAP_FIFTH:
+            reg = (volatile unsigned int *)LS1C_CBUS_FIFTH2;
+            break;
+        }
+        break;
+
+    case 3:
+        switch (remap)
+        {
+        case PIN_REMAP_FIRST:
+            reg = (volatile unsigned int *)LS1C_CBUS_FIRST3;
+            break;
+        case PIN_REMAP_SECOND:
+            reg = (volatile unsigned int *)LS1C_CBUS_SECOND3;
+            break;
+        case PIN_REMAP_THIRD:
+            reg = (volatile unsigned int *)LS1C_CBUS_THIRD3;
+            break;
+        case PIN_REMAP_FOURTH:
+            reg = (volatile unsigned int *)LS1C_CBUS_FOURTH3;
+            break;
+        case PIN_REMAP_FIFTH:
+            reg = (volatile unsigned int *)LS1C_CBUS_FIFTH3;
+            break;
+        }
+        break;
+
+    default:
+        return ;
     }
 
-    // 1
+    // 缃�1
     reg_set_one_bit(reg, pin);
 
     return ;

+ 4 - 6
bsp/ls1cdev/ls1c_ram.lds

@@ -11,6 +11,7 @@
  * Date           Author       Notes
  * 2010-05-17     swkyer       first version
  * 2010-09-04     bernard      move the beginning entry to 0x80200000
+ * 2018-05-12     zhuangwei    use -Ttext
  */
 
 OUTPUT_ARCH(mips)
@@ -19,16 +20,13 @@ GROUP(-lgcc -lc)
 ENTRY(_start)
 SECTIONS
 {
-    . = 0x80200000 ;
-
-    .start :
-    {
-        *(.start);
-    }
+    . = 0x80000000 ;
 
     . = ALIGN(4);
     .text : 
     {
+		start = ABSOLUTE(.);
+		*(.start);
          *(.text)
          *(.text.*)
          *(.rodata)

+ 11 - 5
bsp/ls1cdev/rtconfig.h

@@ -156,11 +156,6 @@
 
 /* RT-Thread online packages */
 
-/* system packages */
-
-/* RT-Thread GUI Engine */
-
-
 /* IoT - internet of things */
 
 
@@ -184,9 +179,20 @@
 /* tools packages */
 
 
+/* system packages */
+
+/* RT-Thread GUI Engine */
+
+
+/* peripheral libraries and drivers */
+
+
 /* miscellaneous packages */
 
 
+/* sample package */
+
+
 /* example package: hello */
 
 #define RT_USING_UART2

+ 6 - 1
libcpu/mips/loongson_1c/cpuport.c

@@ -17,6 +17,8 @@
 #include <rtthread.h>
 #include "ls1c.h"
 
+register rt_uint32_t $GP __asm__ ("$28");
+
 /**
  * @addtogroup Loongson LS1B
  */
@@ -68,12 +70,15 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_ad
 {
 	rt_uint32_t *stk;
     static rt_uint32_t g_sr = 0;
+	static rt_uint32_t g_gp = 0;
 
     if (g_sr == 0)
     {
     	g_sr = cp0_get_status();
     	g_sr &= 0xfffffffe;
     	g_sr |= 0x8401;
+
+		g_gp = $GP;
     }
 
     /** Start at stack top */
@@ -87,7 +92,7 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter, rt_uint8_t *stack_ad
 	*(--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) g_gp;	        /* gp */
 	*(--stk) = (rt_uint32_t) 0x0000001b;	/* k1 */
 	*(--stk) = (rt_uint32_t) 0x0000001a;	/* k0 */
 	*(--stk) = (rt_uint32_t) 0x00000019;	/* t9 */

+ 85 - 0
libcpu/mips/loongson_1c/sdram_cfg.h

@@ -0,0 +1,85 @@
+
+#ifndef __OPENLOONGSON_SDRAM_CFG_H
+#define __OPENLOONGSON_SDRAM_CFG_H
+
+
+//#define	SD_FREQ	(6 * PLL_M) / (2 * SDRAM_PARAM_DIV_NUM)
+#define	SD_FREQ	(((APB_CLK / 4) * (PLL_MULT / CPU_DIV)) / SDRAM_PARAM_DIV_NUM)
+
+ 
+/* 颗粒行数 */
+#define	ROW_1K		0x7
+#define	ROW_2K		0x0
+#define	ROW_4K		0x1
+#define	ROW_8K		0x2
+#define	ROW_16K		0x3
+/* 颗粒列数 */
+#define	COL_256		0x7
+#define	COL_512		0x0
+#define	COL_1K		0x1
+#define	COL_2K		0x2
+#define	COL_4K		0x3
+/* 颗粒位宽 */
+#define	WIDTH_8		0x0
+#define	WIDTH_16	0x1
+#define	WIDTH_32	0x2
+
+#define	TRCD		3
+#define	TCL			3
+#define	TRP			3
+#define	TRFC		8
+#define	TRAS		6
+#define	TREF		0x818
+#define	TWR			2
+
+#define	DEF_SEL		0x1
+#define	DEF_SEL_N	0x0
+#define	HANG_UP		0x1
+#define	HANG_UP_N	0x0
+#define	CFG_VALID	0x1
+
+
+#if 0
+// 白菜板8MB
+/*
+    以型号为IS42S16400的SDRAM为例,
+    物理参数为,
+    容量:8MB
+    位宽:16位
+    列宽:8位,即2的8次方,即256
+    行宽:12位,即2的12次方,即4K
+
+    所以,
+    颗粒的位宽=WIDTH_16
+    颗粒的列数=COL_256
+    颗粒的行数=ROW_4K
+
+    再结合宏SD_PARA0和芯片手册中寄存器SD_CONFIG,相信一看就能明白
+    替换宏SD_PARA0中的行宽、列宽和位宽
+*/
+#define SDRAM_WIDTH         (WIDTH_16)
+#define SDRAM_COL           (COL_256)
+#define SDRAM_ROW           (ROW_4K)
+
+#else
+
+// 智龙32MByte
+#define SDRAM_WIDTH         (WIDTH_16)
+#define SDRAM_COL           (COL_512)
+#define SDRAM_ROW           (ROW_8K)
+
+#endif
+
+#define	SD_PARA0	(0x7f<<25 | \
+					(TRAS << 21) | \
+					(TRFC << 17) | (TRP << 14) | (TCL << 11) | \
+					(TRCD << 8) | (SDRAM_WIDTH << 6) | (SDRAM_COL << 3) | \
+					SDRAM_ROW)
+
+#define	SD_PARA1	((HANG_UP_N << 8) | (DEF_SEL_N << 7) | (TWR << 5) | (TREF >> 7))
+
+#define	SD_PARA1_EN	((CFG_VALID << 9) | (HANG_UP_N << 8) | \
+					(DEF_SEL_N << 7) | (TWR << 5) | (TREF >> 7))
+
+
+#endif

+ 392 - 0
libcpu/mips/loongson_1c/start_gcc.S

@@ -15,6 +15,34 @@
 
 #include "../common/mips.inc"
 #include "../common/stackframe.h"
+#include "sdram_cfg.h"
+#include "cache.h"
+#include "rtconfig.h"
+
+#define SR_BOOT_EXC_VEC		0x00400000
+
+
+/* config pll div for cpu and sdram */
+#define PLL_MULT            (0x54)  // 晶振为24Mhz时,PLL=504Mhz
+#define SDRAM_DIV           (0)     // SDRAM为CPU的2分频
+#define CPU_DIV             (2)     // CPU为PLL的2分频
+
+	// 配置内存大小
+#define MEM_SIZE    (0x02000000)        // 32MByte
+
+	/* Delay macro */
+#define	DELAY(count)	\
+		li v0, count;	\
+	99: 		\
+		bnez	v0, 99b;\
+		addiu	v0, -1
+
+
+#define msize		s2
+#define	output_en	s3
+
+
+
 
 	.section ".start", "ax"
 	.set noreorder
@@ -25,6 +53,8 @@ _start:
 	.set	noreorder
 	la	ra, _start
 
+#if !defined(RT_USING_SELF_BOOT)
+
 	/* disable interrupt */
 	mfc0	t0, CP0_STATUS
 	and 	t0, 0xfffffffe	# By default it will be disabled.
@@ -57,6 +87,46 @@ _clr_bss_loop:
 	/* restart, never die */
 	j	_start
 	nop
+	
+#else
+
+	mtc0	zero, CP0_STATUS	// 清零cp0 status寄存器
+	mtc0	zero, CP0_CAUSE		// 清零cp0 cause寄存器
+
+	/*
+	设置启动异常向量入口地址为ROM地址(0xbfc00000)
+	将寄存器cp0 status的BEV置1,使CPU采用ROM(kseg1)空间的异常入口点
+	*/
+	li	t0, SR_BOOT_EXC_VEC /* Exception to Boostrap Location */
+	mtc0	t0, CP0_STATUS
+
+	/* setup stack pointer */
+	li	sp, SYSTEM_STACK
+	la	gp, _gp
+		
+	/* initialize spi */
+	li	t0, 0xbfe80000		//地址0xbfe80000为SPI0的寄存器基地址
+	li	t1, 0x17			// div 4, fast_read + burst_en + memory_en double I/O 模式 部分SPI flash可能不支持
+	sb	t1, 0x4(t0) 		// 设置寄存器sfc_param
+	li	t1, 0x05
+	sb	t1, 0x6(t0) 		// 设置寄存器sfc_timing
+
+	/* 设置sdram cs1复用关系,开发板使用ejtag_sel gpio_0引脚(第五复用)作为第二片sdram的片选
+	  注意sw2拨码开关的设置,使用ejtag烧录pmon时需要调整拨码开关,烧录完再调整回来 */
+	li	a0, 0xbfd011c0
+	lw	a1, 0x40(a0)
+	ori a1, 0x01
+	sw	a1, 0x40(a0)
+
+
+	bal locate
+	nop
+
+	/* restart, never die */
+	j	_start
+	nop
+#endif
+
 	.set	reorder
 
 	.globl  cp0_get_cause
@@ -83,6 +153,328 @@ cp0_get_lo:
 	jr	ra
 	nop
 
+#if defined(RT_USING_SELF_BOOT)
+
+/****************************************LOCATE*********************************/
+
+/*
+ *  We get here from executing a bal to get the PC value of the current execute
+ *  location into ra. Check to see if we run from ROM or if this is ramloaded.
+ *  寄存器ra内保持着函数的返回地址,根据ra的值来判断当前是从ROM冷启动,还是从RAM热复位的
+ *  ROM冷启动由通电引起,RAM热复位为各种异常引起,比如看门狗引起的复位等,
+ *  也就是RAM热复位之前CPU已经开始运行了
+ *  如果是从ROM冷启动,则寄存器ra的值为指令"bal	locate"所在位置加8字节,大概在0xBFC00000附近
+ *  如果是从RAM热复位,则集成器ra的值为0x80xxxxxx
+ */
+locate:
+//	la		s0, uncached
+//	subu	s0, ra, s0
+    /*
+     * start.s的这段汇编程序在ROM(入口点为0xBFC00000)中运行
+     * 而编译链接时指定的起始地址是0x80100000,所以需要修正一下地址
+     * s0中保存着ra与start的差值,在后续的代码中可以起到修正地址的作用
+     * 在看看文件开始的时候,对寄存器s0用途的描述是“         link versus load offset, used to relocate absolute adresses”
+     * 除了修正地址外,还通过s0的值来判断是从ROM冷启动,还是从RAM热启动
+     */
+		
+	la		s0, _start           // s0 = _start, 其中start的地址为编译链接时,指定的0x80010000
+	subu	s0, ra, s0          // s0 = ra - s0,其中ra的值在ROM入口地址0xBFC00000附近
+	and	s0, 0xffff0000          // s0 = s0 & 0xffff0000
+
+    /*
+     * 初始化cp0的status寄存器和cause寄存器
+     * 在异常引起的(从RAM)热复位后,需要重新初始化cp0的status和cause,
+     * 如果是从ROM冷启动的,那么前面已经初始化了,这里是再次重复初始化,没有影响的
+     */
+	li		t0, SR_BOOT_EXC_VEC
+	mtc0	t0, CP0_CONFIG        // 重新初始化cp0的status寄存器
+	mtc0	zero, CP0_CAUSE       // 重新清零cp0的cause寄存器
+	.set	noreorder
+    
+	li	t0, 0xbfe78030          // 地址0xbfe78030为PLL/SDRAM频率配置寄存器的地址
+	/* 设置PLL倍频 及SDRAM分频 */
+	li	t2, (0x80000008 | (PLL_MULT << 8) | (0x3 << 2) | SDRAM_DIV)
+	/* 设置CPU分频 */
+	li	t3, (0x00008003 | (CPU_DIV << 8))
+	/* 注意:首先需要把分频使能位清零 */
+	li	t1, 0x2
+	sw	t1, 0x4(t0)         // 清零CPU_DIV_VALID,即disable
+	sw	t2, 0x0(t0)         // 写寄存器START_FREQ
+	sw	t3, 0x4(t0)         // 写寄存器CLK_DIV_PARAM
+	DELAY(2000)
+
+	/* 芯片上电默认使用gpio(输入模式)但大多时候是使用模块的功能,如lcd i2c spi ac97等
+	   所以这里把gpio都关闭,方便使用模块功能。如果上电后需要gpio输出一个确定电平,
+	   如继电器、LDE等,可以修改这里的代码。*/
+	/* disable all gpio */
+	li a0,0xbfd00000
+	sw zero,0x10c0(a0)	/* disable gpio 0-31 */
+	sw zero,0x10c4(a0)	/* disable gpio 32-63 */
+	sw zero,0x10c8(a0)	/* disable gpio 64-95 */
+	sw zero,0x10cc(a0)
+
+	li t0, 0xffffffff
+	sw t0, 0x10d0(a0)
+	sw t0, 0x10d4(a0)
+	sw t0, 0x10d8(a0)
+	sw t0, 0x10dc(a0)
+
+	sw t0, 0x10f0(a0)
+	sw t0, 0x10f4(a0)
+	sw t0, 0x10f8(a0)
+	sw t0, 0x10fc(a0)
+
+
+	/* lcd soft_reset and panel config & timing */
+#ifdef DC_FB0
+/*	li a0, 0xbc301240
+	li a1, 0x00100103
+	sw a1, 0x0(a0)
+	li a1, 0x00000103
+	sw a1, 0x0(a0)		//soft_reset
+	li a1, 0x00100103
+	sw a1, 0x0(a0)
+
+	li a1, 0x80001111
+	sw a1, 0x180(a0)	//panel config
+	li a1, 0x33333333
+	sw a1, 0x1a0(a0)*/
+#endif
+
+	li output_en, 0x1
+#ifdef FAST_STARTUP
+	li a1, 0x03000000
+	sw a1, 0x10c4(a0)
+	sw a1, 0x10d4(a0)
+	lw a2, 0x10e4(a0)
+	and a2, a1
+	beq a2, a1, get_pin_val_finish
+	nop
+	li output_en, 0x1
+
+get_pin_val_finish:
+
+#endif
+
+	/* Initializing. Standby... */
+    /*
+     *  根据s0的值判断是否为ROM冷启动
+     *  如果s0不等于0,则是ROM冷启动;如果等于0,则是RAM热复位
+     *  冷启动,则需要初始化内存,cache,加载代码到内存等
+     */
+	bnez s0, 1f     // 如果寄存器s0不等于0,则说明是ROM冷启动,则跳转到下一个标号1处进行彻底初始化
+	nop
+	li a0, 128
+
+	jal rtthread_startup    // 热复位,则直接跳转到函数main
+	nop
+1:
+
+/* use only 8wins */
+#define CPU_WIN_BASE 0xbfd00000
+#define CPU_WIN_MASK 0xbfd00040
+#define CPU_WIN_MMAP 0xbfd00080
+
+#define set_cpu_window(id, base, mask, mmap) \
+        li      t0, CPU_WIN_BASE          ;  \
+        sw      $0, 0x80+id*8(t0)         ;  \
+        li      t1, base                  ;  \
+        sw      t1, 0x00+id*8(t0)         ;  \
+        sw      $0, 0x04+id*8(t0)         ;  \
+        li      t1, mask                  ;  \
+        sw      t1, 0x40+id*8(t0)         ;  \
+        sw      $0, 0x44+id*8(t0)         ;  \
+        li      t1, mmap                  ;  \
+        sw      t1, 0x80+id*8(t0)         ;  \
+        sw      $0, 0x84+id*8(t0)
+
+/* fixup cpu window */
+cpu_win_fixup:
+	//
+	// hit         = (paddr & mask) == (mmap & mask)
+	// mapped_addr =  paddr &~mask | mmap & mask
+	//
+	// mmap[7] -> enable
+	// mmap[5] -> block trans enable
+	// mmap[4] -> cachable
+	// mmap[1:0] -> destination
+	//
+	// NOTE: the address windows has priority, win0 > win1 > ... > win7
+
+/*	set_cpu_window(0, 0x1c280000, 0xfff80000, 0x1c280083) // camera 512K
+	set_cpu_window(1, 0x1c300000, 0xfff00000, 0x1c300081) // dc 1M
+	set_cpu_window(2, 0x1fe10000, 0xffffe000, 0x1fe10082) // gmac0	8K
+	set_cpu_window(3, 0x1fe10000, 0xffff0000, 0x1fe100d0) // gmac0	64K
+	set_cpu_window(4, 0x1f000000, 0xff000000, 0x1f000082) // AXIMUX   16M
+	set_cpu_window(5, 0x00000000, 0x00000000, 0x000000f0) // ddr 0
+	set_cpu_window(6, 0x00000000, 0x00000000, 0x000000f0) // ddr 0
+	set_cpu_window(7, 0x00000000, 0x00000000, 0x000000f0) // ddr 0*/
+
+/*	set_cpu_window(0, 0x1c280000, 0xfff80000, 0x1c2800d3) // camera
+//	set_cpu_window(1, 0x1fc00000, 0xfff00000, 0x1fc000f2) //
+	set_cpu_window(2, 0x1c300000, 0xfff00000, 0x1c3000d1) // dc 1M
+//	set_cpu_window(3, 0x1f000000, 0xff000000, 0x1f0000d2) //
+	set_cpu_window(4, 0x00000000, 0x00000000, 0x000000f0)
+	set_cpu_window(5, 0x00000000, 0x00000000, 0x000000f0)
+	set_cpu_window(6, 0x00000000, 0x00000000, 0x000000f0) // ddr 0
+	set_cpu_window(7, 0x00000000, 0x00000000, 0x000000f0) // ddr 0*/
+
+	// after this fixup, the kernel code should be compiled with
+	// uncached instruction fetch patch
+
+	/* 配置内存 */
+	li msize, MEM_SIZE    
+#if !defined(NAND_BOOT_EN)
+
+    /* 
+       手册建议,先写寄存器SD_CONFIG[31:0],然后再写寄存器的SD_CONFIG[63:32],
+       即先写低32位,再写高32位。
+       写三次寄存器,最后一次将最高位置一,即使能
+    */
+
+    // 写第一次
+	li  	t1, 0xbfd00410      // 寄存器SD_CONFIG[31:0]的地址为0xbfd00410
+	li		a1, SD_PARA0        // 宏SD_PARA0在sdram_cfg.S中定义的
+	sw		a1, 0x0(t1)         // 将宏SD_PARA0的值写入寄存器SD_CONFIG[31:0]
+	li		a1, SD_PARA1
+	sw		a1, 0x4(t1)         // 同理,将宏SD_PARA1的值写入寄存器SD_CONFIG[63:32]
+
+	// 写第二次
+	li		a1, SD_PARA0
+	sw		a1, 0x0(t1)
+	li		a1, SD_PARA1
+	sw		a1, 0x4(t1)
+
+    // 写第三次	
+	li		a1, SD_PARA0
+	sw		a1, 0x0(t1)
+	li		a1, SD_PARA1_EN     // 使能
+	sw		a1, 0x4(t1)
+//	DELAY(100)
+#endif
+
+	/**************************************CACHE*****************************/
+	
+#define CF_7_SE         (1 << 3)        /* Secondary cache enable */
+#define CF_7_SC         (1 << 31)       /* Secondary cache not present */
+#define CF_7_TE         (1 << 12)       /* Tertiary cache enable */
+#define CF_7_TC         (1 << 17)       /* Tertiary cache not present */
+#define CF_7_TS         (3 << 20)       /* Tertiary cache size */
+#define CF_7_TS_AL      20              /* Shift to align */
+#define NOP8 nop;nop;nop;nop;nop;nop;nop;nop
+	
+do_caches:
+	/* Init caches... */
+	li	s7, 0					/* no L2 cache */
+	li	s8, 0					/* no L3 cache */
+
+	bal 	cache_init			// 调用汇编函数cache_init
+	nop
+
+	mfc0   a0, CP0_CONFIG 		// 将协处理器0的config寄存器的值加载到寄存器a0
+	and    a0, a0, ~((1<<12) | 7)	// a0 = a0 & ~((1<<12) | 7)
+	or	   a0, a0, 2				// a0 |= 2
+	mtc0   a0, CP0_CONFIG 		// 将寄存器a0的值写入协处理器0的config寄存器
+
+/***********************MEMORY DEBUGGING AND COPY SELF TO RAM***********************/
+//#include "newtest.32/mydebug.S"
+bootnow:
+	/* copy program to sdram to make copy fast */
+	/* 先将执行拷贝pmon到内存任务的代码,拷贝到内存0xa0000000 */
+	
+	/* 先确定需要拷贝的代码段为标号121到标号122之间的代码
+	 * 由于链接时指定的起始地址是0x80010000,
+	 * 而目前正在ROM(SPI NOR FLASH,起始地址为0xBFC00000)运行
+	 * 所以需要用寄存器s0来修正一下地址
+	 */
+	la		t0, 121f			// 将下一个标号121所在地址,加载到寄存器t0
+	addu	t0, s0				// 使用寄存器s0修正t0中的(标号121的)地址
+	la		t1, 122f			// 将下一个标号122所在地址,加载到寄存器t1
+	addu	t1, s0				// 使用寄存器s0修正t1中的(标号122的)地址
+	
+	li		t2, 0xa0000000		// 将立即数0xa0000000(起始地址)加载到寄存器t2
+1:
+	lw		v0, (t0)			// 将寄存器t0所指的内存地址开始4字节的数据加载到寄存器v0
+	sw		v0, (t2)			// 将寄存器v0的内容保存到寄存器t2所指的内存中
+	addu	t0, 4				// 寄存器t0向后移4字节
+	addu	t2, 4				// 寄存器t2向后移4字节
+	ble t0, t1, 1b				// 如果t0 <= t1,则跳转到上一个标号1处,继续拷贝后面的4字节
+	nop
+
+	li		t0, 0xa0000000		// 将立即数0xa0000000加载到寄存器t0
+	jr		t0					// 跳转到起始地址0xa0000000处开始执行(拷贝任务)
+	nop 	
+
+121: 
+	/* Copy PMON to execute location... */
+	/* 将固件拷贝到起始地址为0xa0010000的内存空间
+	   由于kseg0(0x8000 0000 - 0x9FFF FFFF)和kseg1(0xA000 0000 - 0xBFFF FFFF)是映射到物理内存的相同区域
+	   即拷贝到0xA000 0000开始的kseg1,就相当于拷贝到0x8000 0000开始的kseg0
+	   这就是为什么链接时,指定的地址是0x8001 0000,而拷贝的目标起始地址是0xA001 0000
+	*/
+	la		a0, _start			// 加载符号start所在地址0x80010000加载到寄存器a0中
+	addu	a1, a0, s0			// 使用寄存器s0修正寄存器a0中的地址,a1=0xBFC00000
+	la		a2, __bss_start			// 加载_edata(链接脚本中的一个符号)到寄存器a2
+	or		a0, 0xa0000000		// a0 = a0 | 0xa0000000 = 0xa0010000
+	or		a2, 0xa0000000		// a2 = a2 | 0xa0000000,修正地址_edata
+	subu	t1, a2, a0			// t1 = a2 - a0,即计算从start到_edata之间的长度(字节数)
+	srl t1, t1, 2				// t1 >>= 2,即t1除以4。(和前面类似,每次拷贝4字节,所以除以4)
+								// 似乎t1计算结果没有被使用,马上就被后面的覆盖了
+
+	move	t0, a0				// t0 = a0 = 0xa0010000 (目标起始地址)
+	move	t1, a1				// t1 = a1 = 0xBFC00000 (start在ROM中的地址,源起始地址)
+	move	t2, a2				// t2 = a2 (_edata在ROM中的地址,源结束地址)
+
+	/* copy text section */
+1:	and t3, t0, 0x0000ffff		// t3 = t0 & 0x0000ffff,取低16位
+	bnez	t3, 2f				// 如果t3不等于0,则跳转到下一个标号2处继续执行,t3的计算结果似乎没被使用,就被后面的覆盖了
+	nop
+2:	lw		t3, 0(t1)			// 从源地址t1处加载4字节到寄存器t3中
+	nop
+	sw		t3, 0(t0)			// 将寄存器t3中的4字节数据保存到目标地址t0处
+	addu	t0, 4				// 目标地址t0后移4字节
+	addu	t1, 4				// 源地址t1	  后移4字节
+	bne t2, t0, 1b				// 如果t2不等于t0,则跳到上一个标号1处继续拷贝,总的来说就是判断拷贝是否结束
+	nop
+	/* copy text section done. */
+	
+	/* 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
+
+	/* 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
+
+	/* jump to RT-Thread RTOS */
+	jal	rtthread_startup
+	nop
+
+	/* restart, never die */
+	j	_start
+	nop
+	
+
+122:
+
+stuck:
+	b	stuck
+	nop
+#endif
+
 	.extern tlb_refill_handler
 	.extern cache_error_handler