Procházet zdrojové kódy

fw: replace libc _start with a much simpler one

The libc _start not only gets bss clearing wrong, but pulls in a bunch
of code we don't need. Replace it with a much simpler version. This
saves over 2K.

Move the IRQ vector back to 0x10.
H. Peter Anvin před 3 roky
rodič
revize
54f6bd3fd6
10 změnil soubory, kde provedl 5435 přidání a 5414 odebrání
  1. 1 1
      fpga/max80.sv
  2. binární
      fpga/output_files/max80.jbc
  3. binární
      fpga/output_files/max80.jic
  4. binární
      fpga/output_files/max80.pof
  5. binární
      fpga/output_files/max80.sof
  6. 5373 5373
      fw/boot.mif
  7. 44 7
      fw/head.S
  8. 7 30
      fw/hello.c
  9. 9 2
      fw/max80.ld
  10. 1 1
      fw/sys.h

+ 1 - 1
fpga/max80.sv

@@ -461,7 +461,7 @@ module max80
 	.trap ( cpu_trap ),
 
 	.progaddr_reset ( 32'h0000_0000 ),
-	.progaddr_irq   ( 32'h0000_0020 ),
+	.progaddr_irq   ( 32'h0000_0010 ),
 
 	.mem_instr ( cpu_mem_instr ),
 	.mem_ready ( cpu_mem_ready ),

binární
fpga/output_files/max80.jbc


binární
fpga/output_files/max80.jic


binární
fpga/output_files/max80.pof


binární
fpga/output_files/max80.sof


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 5373 - 5373
fw/boot.mif


+ 44 - 7
fw/head.S

@@ -1,27 +1,64 @@
 #include "sys.h"
 #include "picorv32.h"
 
+#define GP_IS_ZERO 1
+
+	// The code in this file is sensitive to alignment, so
+	// don't use compressed instructions (there are very few anyway)
+	.option norvc
+	
 	// The linker ensures that section .init is first
 	.section ".init.reset","ax"
 	.globl _reset
 _reset:
-	rdtime t0		// Record timer at reset
+	rdtime s0		// Record timer at reset
 	li sp,STACK_TOP		// Cheaper than using la sp,___stack_top
+	j __start
+	.type _reset, @function
+	.size _reset, . - _reset
+
+	.section ".init","ax"
+	.globl __start
+__start:
+	not t0,zero
+	maskirq zero,t0,zero
+#if !GP_IS_ZERO
 	.option push
 	.option norelax		// Can't make gp references to set up gp...
 	la gp, __global_pointer$
 	.option pop
+#else
+	// Zero gp (linker will usually replace with the zero reg)
+	li gp,0
+#endif
 	addqxi gp,gp,0		// Set gp for interrupt code too
-	sw t0, time_zero, t1
-	j _start
-	.type _reset, @function
-	.size _reset, . - _reset
 
-	.pushsection ".sdata","a"
+	// Clear bss
+	la a0,__BSS_START__
+	la a1,__BSS_END__
+
+.L_clear_bss_loop:
+	sw zero,(a0)
+	sw zero,4(a0)
+	sw zero,8(a0)
+	sw zero,12(a0)
+	sw zero,16(a0)
+	sw zero,20(a0)
+	sw zero,24(a0)
+	sw zero,28(a0)
+	addi a0,a0,32
+	bltu a0,a1,.L_clear_bss_loop
+
+	sw s0, time_zero, t0
+	j main
+	.type __start, @function
+	.size __start, . - __start
+
+	.pushsection ".sbss","a"
 	.balign 4
 	.globl time_zero
 time_zero:
-	.long 0
+	.space 4
 	.type time_zero, @object
 	.size time_zero, . - time_zero
 	.popsection

+ 7 - 30
fw/hello.c

@@ -194,12 +194,12 @@ static void init(void)
 	"\n*** Hello, World! ***\n"
 	"Firmware compiled on: " __DATE__ " " __TIME__ "\n\n";
 
-    init_abc_memmap();
-
     set_led(0);
-
+    con_set_baudrate(115200);
     con_puts(hello);
 
+    init_abc_memmap();
+
     timer_irq_count = 0;
     timer_irq_start = rdtime();
     unmask_irq(SYSCLOCK_IRQ);
@@ -233,26 +233,6 @@ IRQHANDLER(romcopy)
     }
 }
 
-/*
- * Faster than memset() because it is less generic
- * newlib gets the bss clearing wrong for some reason...
- */
-static void clear_bss(void)
-{
-    extern uint32_t __bss_start[], __BSS_END__[];
-
-    for (uint32_t *p = __bss_start; p < __BSS_END__; p += 8) {
-	p[0] = 0;
-	p[1] = 0;
-	p[2] = 0;
-	p[3] = 0;
-	p[4] = 0;
-	p[5] = 0;
-	p[6] = 0;
-	p[7] = 0;
-    }
-}
-
 void main(void)
 {
     /* The data section is not reinitialized on reset */
@@ -261,16 +241,13 @@ void main(void)
     uint32_t irq_count;
     uint32_t abc_status;
     uint32_t done;
-    uint32_t bss_clear_time;
+    uint32_t time_to_main;
 
-    clear_bss();
-    bss_clear_time = rdtime() - time_zero;
+    time_to_main = rdtime() - time_zero;
 
     romcopy_state = 0;
     unmask_irq(ROMCOPY_IRQ);
 
-    con_set_baudrate(115200);
-
     init();
 
     con_printf("This is loop: %u\n", loops++);
@@ -283,8 +260,8 @@ void main(void)
 	con_puts("No ABC-bus host detected\n");
     }
 
-    con_printf("Clearing .bss took %u us\n",
-	       bss_clear_time/(CPU_HZ/1000000));
+    con_printf("Bootup code/clearing .bss took %u us\n",
+	       time_to_main/(CPU_HZ/1000000));
 
     while (!(irqmask() & (1 << ROMCOPY_IRQ)))
 	pause();

+ 9 - 2
fw/max80.ld

@@ -39,6 +39,7 @@ SECTIONS
 		*(.gnu_extab*)
 		*(.exception_ranges*)
 		*crtbegin.o(*)
+		*crt0.o(*)
 	}
 
 	PROVIDE (__executable_start = _PC_RESET);
@@ -69,7 +70,8 @@ SECTIONS
 	}
 
 	. = ALIGN(32);
-	__bss_start = .;
+	__BSS_START__ = .;
+	PROVIDE (__bss_start = .);
 	.sbss : ALIGN(4) {
 		*(.dynsbss)
 		*(.sbss .sbss.* .gnu.linkonce.sb.*)
@@ -79,13 +81,18 @@ SECTIONS
 
 	HIDDEN($assert_zero_page = ASSERT((. <= 2048), "zero page overflow"));
 
-	.bss  : {
+	.bss : {
 		*(.dynbss)
 		*(.bss .bss.* .gnu.linkonce.b.*)
 		*(COMMON)
 	}
 	. = ALIGN(32);
 	__BSS_END__ = .;
+	__BSS_LEN__ = __BSS_END__ - __BSS_START__;
+
+	. = ALIGN(4);
+	__BSS_END__ = .;
+	__BSS_LEN__ = __BSS_END__ - __BSS_START__;
 
 	__global_pointer$ = 0;
 

+ 1 - 1
fw/sys.h

@@ -26,6 +26,6 @@
 
 /* This need to match the corresponding Verilog constants */
 #define _PC_RESET	0
-#define _PC_IRQ		0x20
+#define _PC_IRQ		0x10
 
 #endif /* SYS_H */

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů