├── boot-helper.S
├── splash.h
├── boot.h
├── isr.c
├── linker.ld
├── splash.c
├── README
├── cvt.c
├── crt0.S
├── core_portme.h
├── core_portme.mak
├── core_portme.c
├── boot.c
└── ee_printf.c
/boot-helper.S:
--------------------------------------------------------------------------------
1 | .section .text, "ax", @progbits
2 | .global boot_helper
3 | boot_helper:
4 | /* Invalidate instruction cache */
5 | wcsr ICC, r0
6 | nop
7 | nop
8 | nop
9 | nop
10 | call r5
11 |
--------------------------------------------------------------------------------
/splash.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Milkymist SoC (Software)
3 | * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3 of the License.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #ifndef __SPLASH_H
19 | #define __SPLASH_H
20 |
21 | void splash_display();
22 |
23 | #endif /* __SPLASH_H */
24 |
--------------------------------------------------------------------------------
/boot.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Milkymist SoC (Software)
3 | * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3 of the License.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #ifndef __BOOT_H
19 | #define __BOOT_H
20 |
21 | void serialboot();
22 | void netboot();
23 | void fsboot(int devnr);
24 | void flashboot();
25 |
26 | #endif /* __BOOT_H */
27 |
--------------------------------------------------------------------------------
/isr.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Milkymist SoC (Software)
3 | * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3 of the License.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | #include
24 | #include
25 |
26 | void isr()
27 | {
28 | unsigned int irqs;
29 |
30 | irqs = irq_pending() & irq_getmask();
31 |
32 | if(irqs & IRQ_UART)
33 | uart_isr();
34 |
35 | if(irqs & IRQ_TMU)
36 | tmu_isr();
37 |
38 | if(irqs & IRQ_TIMER0)
39 | time_isr();
40 |
41 | if(irqs & IRQ_USB)
42 | usb_isr();
43 | }
44 |
--------------------------------------------------------------------------------
/linker.ld:
--------------------------------------------------------------------------------
1 | OUTPUT_FORMAT("elf32-lm32")
2 | /* ENTRY(_mystart) */
3 | STARTUP(coremark_lm32/crt0.o)
4 |
5 | __DYNAMIC = 0;
6 |
7 | MEMORY {
8 | sdram : ORIGIN = 0x40000000, LENGTH = 0x4000000 /* upper 64M of SDRAM */
9 | }
10 |
11 | SECTIONS
12 | {
13 | .text :
14 | {
15 | _ftext = .;
16 | *(.text .stub .text.* .gnu.linkonce.t.*)
17 | _etext = .;
18 | } > sdram
19 |
20 | .rodata :
21 | {
22 | . = ALIGN(4);
23 | _frodata = .;
24 | *(.rodata .rodata.* .gnu.linkonce.r.*)
25 | *(.rodata1)
26 | /* we use _erodata for copying .data section to sdram. */
27 | . = ALIGN(4);
28 | _erodata = .;
29 | } > sdram
30 |
31 | .data :
32 | {
33 | . = ALIGN(4);
34 | _fdata = .;
35 | *(.data .data.* .gnu.linkonce.d.*)
36 | *(.data1)
37 | _gp = ALIGN(16);
38 | *(.sdata .sdata.* .gnu.linkonce.s.*)
39 | _edata = .;
40 | } > sdram
41 |
42 | .bss :
43 | {
44 | . = ALIGN(4);
45 | _fbss = .;
46 | *(.dynsbss)
47 | *(.sbss .sbss.* .gnu.linkonce.sb.*)
48 | *(.scommon)
49 | *(.dynbss)
50 | *(.bss .bss.* .gnu.linkonce.b.*)
51 | *(COMMON)
52 | . = ALIGN(4);
53 | _ebss = .;
54 | _end = .;
55 | PROVIDE (end = .);
56 | } > sdram
57 | }
58 |
59 | PROVIDE(_fstack = ORIGIN(sdram) + LENGTH(sdram) - 4);
60 |
--------------------------------------------------------------------------------
/splash.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Milkymist SoC (Software)
3 | * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3 of the License.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #include
19 | #include
20 | #include
21 |
22 | #include "splash.h"
23 |
24 | extern int rescue;
25 |
26 | void splash_display()
27 | {
28 | int i;
29 | unsigned short *splash_src = rescue ? (unsigned short *)FLASH_OFFSET_RESCUE_SPLASH : (unsigned short *)FLASH_OFFSET_REGULAR_SPLASH;
30 |
31 | printf("I: Displaying splash screen...");
32 |
33 | for(i=0;i
37 | Remote debugging using /dev/pts/5
38 | 0x00860650 in ?? ()
39 | (gdb) load
40 | (gdb) set $PC=_mystart
41 | (gdb) c
42 |
43 |
44 | To run on QEMU simulator:
45 | # qemu-system-lm32 -M milkymist -kernel coremark.bin -nographic
46 |
--------------------------------------------------------------------------------
/cvt.c:
--------------------------------------------------------------------------------
1 | #include
2 | #define CVTBUFSIZE 80
3 | static char CVTBUF[CVTBUFSIZE];
4 |
5 | static char *cvt(double arg, int ndigits, int *decpt, int *sign, char *buf, int eflag)
6 | {
7 | int r2;
8 | double fi, fj;
9 | char *p, *p1;
10 |
11 | if (ndigits < 0) ndigits = 0;
12 | if (ndigits >= CVTBUFSIZE - 1) ndigits = CVTBUFSIZE - 2;
13 | r2 = 0;
14 | *sign = 0;
15 | p = &buf[0];
16 | if (arg < 0)
17 | {
18 | *sign = 1;
19 | arg = -arg;
20 | }
21 | arg = modf(arg, &fi);
22 | p1 = &buf[CVTBUFSIZE];
23 |
24 | if (fi != 0)
25 | {
26 | p1 = &buf[CVTBUFSIZE];
27 | while (fi != 0)
28 | {
29 | fj = modf(fi / 10, &fi);
30 | *--p1 = (int)((fj + .03) * 10) + '0';
31 | r2++;
32 | }
33 | while (p1 < &buf[CVTBUFSIZE]) *p++ = *p1++;
34 | }
35 | else if (arg > 0)
36 | {
37 | while ((fj = arg * 10) < 1)
38 | {
39 | arg = fj;
40 | r2--;
41 | }
42 | }
43 | p1 = &buf[ndigits];
44 | if (eflag == 0) p1 += r2;
45 | *decpt = r2;
46 | if (p1 < &buf[0])
47 | {
48 | buf[0] = '\0';
49 | return buf;
50 | }
51 | while (p <= p1 && p < &buf[CVTBUFSIZE])
52 | {
53 | arg *= 10;
54 | arg = modf(arg, &fj);
55 | *p++ = (int) fj + '0';
56 | }
57 | if (p1 >= &buf[CVTBUFSIZE])
58 | {
59 | buf[CVTBUFSIZE - 1] = '\0';
60 | return buf;
61 | }
62 | p = p1;
63 | *p1 += 5;
64 | while (*p1 > '9')
65 | {
66 | *p1 = '0';
67 | if (p1 > buf)
68 | ++*--p1;
69 | else
70 | {
71 | *p1 = '1';
72 | (*decpt)++;
73 | if (eflag == 0)
74 | {
75 | if (p > buf) *p = '0';
76 | p++;
77 | }
78 | }
79 | }
80 | *p = '\0';
81 | return buf;
82 | }
83 |
84 | char *ecvt(double arg, int ndigits, int *decpt, int *sign)
85 | {
86 | return cvt(arg, ndigits, decpt, sign, CVTBUF, 1);
87 | }
88 |
89 | char *ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf)
90 | {
91 | return cvt(arg, ndigits, decpt, sign, buf, 1);
92 | }
93 |
94 | char *fcvt(double arg, int ndigits, int *decpt, int *sign)
95 | {
96 | return cvt(arg, ndigits, decpt, sign, CVTBUF, 0);
97 | }
98 |
99 | char *fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf)
100 | {
101 | return cvt(arg, ndigits, decpt, sign, buf, 0);
102 | }
103 |
--------------------------------------------------------------------------------
/crt0.S:
--------------------------------------------------------------------------------
1 | /*
2 | * LatticeMico32 C startup code.
3 | *
4 | * Redistribution and use in source and binary forms, with or without
5 | * modification, are permitted provided that the following conditions
6 | * are met:
7 | * 1. Redistributions of source code must retain the above copyright
8 | * notice, this list of conditions and the following disclaimer.
9 | * 2. Redistributions in binary form must reproduce the above copyright
10 | * notice, this list of conditions and the following disclaimer in the
11 | * documentation and/or other materials provided with the distribution.
12 | *
13 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 | * SUCH DAMAGE.
24 | */
25 |
26 | /* Exception handlers - Must be 32 bytes long. */
27 | .section .text, "ax", @progbits
28 | .global _mystart
29 | _mystart:
30 | _reset_handler:
31 | xor r0, r0, r0
32 | wcsr IE, r0
33 | mvhi r1, hi(_reset_handler)
34 | ori r1, r1, lo(_reset_handler)
35 | wcsr EBA, r1
36 | /* calli _sdram_init - we'll assume memory should not be reinitialized. */
37 | nop
38 | xor r2, r2, r2
39 | bi _crt0
40 |
41 | _breakpoint_handler:
42 | bi _breakpoint_handler
43 | nop
44 | nop
45 | nop
46 | nop
47 | nop
48 | nop
49 | nop
50 |
51 | _instruction_bus_error_handler:
52 | bi _instruction_bus_error_handler
53 | nop
54 | nop
55 | nop
56 | nop
57 | nop
58 | nop
59 | nop
60 |
61 | _watchpoint_hander:
62 | bi _watchpoint_hander
63 | nop
64 | nop
65 | nop
66 | nop
67 | nop
68 | nop
69 | nop
70 |
71 | _data_bus_error_handler:
72 | bi _data_bus_error_handler
73 | nop
74 | nop
75 | nop
76 | nop
77 | nop
78 | nop
79 | nop
80 |
81 | _divide_by_zero_handler:
82 | bi _divide_by_zero_handler
83 | nop
84 | nop
85 | nop
86 | nop
87 | nop
88 | nop
89 | nop
90 |
91 | _interrupt_handler:
92 | sw (sp+0), ra
93 | calli .save_all
94 | calli isr
95 | bi .restore_all_and_eret
96 | nop
97 | nop
98 | nop
99 | nop
100 |
101 | macaddress:
102 | .byte 0x10
103 | .byte 0xe2
104 | .byte 0xd5
105 | .byte 0x00
106 | .byte 0x00
107 | .byte 0x00
108 |
109 | /* padding to align to a 32-bit boundary */
110 | .byte 0x00
111 | .byte 0x00
112 |
113 | _crt0:
114 | /* Setup stack and global pointer */
115 | mvhi sp, hi(_fstack)
116 | ori sp, sp, lo(_fstack)
117 | mvhi gp, hi(_gp)
118 | ori gp, gp, lo(_gp)
119 |
120 | /* Clear BSS */
121 | mvhi r1, hi(_fbss)
122 | ori r1, r1, lo(_fbss)
123 | mvhi r3, hi(_ebss)
124 | ori r3, r3, lo(_ebss)
125 | .clearBSS:
126 | be r1, r3, .callMain
127 | sw (r1+0), r0
128 | addi r1, r1, 4
129 | bi .clearBSS
130 |
131 | .callMain:
132 | mv r1, r2
133 | mvi r2, 0
134 | mvi r3, 0
135 | calli port_main
136 | .end:
137 | bi .end
138 |
139 | .save_all:
140 | addi sp, sp, -56
141 | sw (sp+4), r1
142 | sw (sp+8), r2
143 | sw (sp+12), r3
144 | sw (sp+16), r4
145 | sw (sp+20), r5
146 | sw (sp+24), r6
147 | sw (sp+28), r7
148 | sw (sp+32), r8
149 | sw (sp+36), r9
150 | sw (sp+40), r10
151 | sw (sp+48), ea
152 | sw (sp+52), ba
153 | /* ra needs to be moved from initial stack location */
154 | lw r1, (sp+56)
155 | sw (sp+44), r1
156 | ret
157 |
158 | .restore_all_and_eret:
159 | lw r1, (sp+4)
160 | lw r2, (sp+8)
161 | lw r3, (sp+12)
162 | lw r4, (sp+16)
163 | lw r5, (sp+20)
164 | lw r6, (sp+24)
165 | lw r7, (sp+28)
166 | lw r8, (sp+32)
167 | lw r9, (sp+36)
168 | lw r10, (sp+40)
169 | lw ra, (sp+44)
170 | lw ea, (sp+48)
171 | lw ba, (sp+52)
172 | addi sp, sp, 56
173 | eret
174 |
--------------------------------------------------------------------------------
/core_portme.h:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | /* File : core_portme.h */
4 |
5 | /*
6 | Author : Shay Gal-On, EEMBC
7 | Legal : TODO!
8 | */
9 | /* Topic : Description
10 | This file contains configuration constants required to execute on different platforms
11 | */
12 | #ifndef CORE_PORTME_H
13 | #define CORE_PORTME_H
14 | /************************/
15 | /* Data types and settings */
16 | /************************/
17 | /* Configuration : HAS_FLOAT
18 | Define to 1 if the platform supports floating point.
19 | */
20 | #ifndef HAS_FLOAT
21 | #define HAS_FLOAT 1
22 | #endif
23 | /* Configuration : HAS_TIME_H
24 | Define to 1 if platform has the time.h header file,
25 | and implementation of functions thereof.
26 | */
27 | #ifndef HAS_TIME_H
28 | #define HAS_TIME_H 1
29 | #endif
30 | /* Configuration : USE_CLOCK
31 | Define to 1 if platform has the time.h header file,
32 | and implementation of functions thereof.
33 | */
34 | #ifndef USE_CLOCK
35 | #define USE_CLOCK 1
36 | #endif
37 | /* Configuration : HAS_STDIO
38 | Define to 1 if the platform has stdio.h.
39 | */
40 | #ifndef HAS_STDIO
41 | #define HAS_STDIO 0
42 | #endif
43 | /* Configuration : HAS_PRINTF
44 | Define to 1 if the platform has stdio.h and implements the printf function.
45 | */
46 | #ifndef HAS_PRINTF
47 | #define HAS_PRINTF 0
48 | #endif
49 |
50 |
51 | /* Definitions : COMPILER_VERSION, COMPILER_FLAGS, MEM_LOCATION
52 | Initialize these strings per platform
53 | */
54 | #ifndef COMPILER_VERSION
55 | #ifdef __GNUC__
56 | #define COMPILER_VERSION "GCC"__VERSION__
57 | #else
58 | #define COMPILER_VERSION "Clang"__VERSION__
59 | #endif
60 | #endif
61 | #ifndef COMPILER_FLAGS
62 | #define COMPILER_FLAGS FLAGS_STR /* "Please put compiler flags here (e.g. -o3)" */
63 | #endif
64 | #ifndef MEM_LOCATION
65 | #define MEM_LOCATION "STACK"
66 | #endif
67 |
68 | /* Data Types :
69 | To avoid compiler issues, define the data types that need ot be used for 8b, 16b and 32b in .
70 |
71 | *Imprtant* :
72 | ee_ptr_int needs to be the data type used to hold pointers, otherwise coremark may fail!!!
73 | */
74 | typedef signed short ee_s16;
75 | typedef unsigned short ee_u16;
76 | typedef signed int ee_s32;
77 | typedef float ee_f32;
78 | typedef unsigned char ee_u8;
79 | typedef unsigned int ee_u32;
80 | typedef ee_u32 ee_ptr_int;
81 | typedef size_t ee_size_t;
82 | /* #define NULL ((void *)0) */
83 | /* align_mem :
84 | This macro is used to align an offset to point to a 32b value. It is used in the Matrix algorithm to initialize the input memory blocks.
85 | */
86 | #define align_mem(x) (void *)(4 + (((ee_ptr_int)(x) - 1) & ~3))
87 |
88 | /* Configuration : CORE_TICKS
89 | Define type of return from the timing functions.
90 | */
91 | #define CORETIMETYPE ee_u32
92 | typedef ee_u32 CORE_TICKS;
93 |
94 | /* Configuration : SEED_METHOD
95 | Defines method to get seed values that cannot be computed at compile time.
96 |
97 | Valid values :
98 | SEED_ARG - from command line.
99 | SEED_FUNC - from a system function.
100 | SEED_VOLATILE - from volatile variables.
101 | */
102 | #ifndef SEED_METHOD
103 | #define SEED_METHOD SEED_VOLATILE
104 | #endif
105 |
106 | /* Configuration : MEM_METHOD
107 | Defines method to get a block of memry.
108 |
109 | Valid values :
110 | MEM_MALLOC - for platforms that implement malloc and have malloc.h.
111 | MEM_STATIC - to use a static memory array.
112 | MEM_STACK - to allocate the data block on the stack (NYI).
113 | */
114 | #ifndef MEM_METHOD
115 | #define MEM_METHOD MEM_STATIC
116 | #endif
117 |
118 | /* Configuration : MULTITHREAD
119 | Define for parallel execution
120 |
121 | Valid values :
122 | 1 - only one context (default).
123 | N>1 - will execute N copies in parallel.
124 |
125 | Note :
126 | If this flag is defined to more then 1, an implementation for launching parallel contexts must be defined.
127 |
128 | Two sample implementations are provided. Use or to enable them.
129 |
130 | It is valid to have a different implementation of and in ,
131 | to fit a particular architecture.
132 | */
133 | #ifndef MULTITHREAD
134 | #define MULTITHREAD 1
135 | #define USE_PTHREAD 0
136 | #define USE_FORK 0
137 | #define USE_SOCKET 0
138 | #endif
139 |
140 | /* Configuration : MAIN_HAS_NOARGC
141 | Needed if platform does not support getting arguments to main.
142 |
143 | Valid values :
144 | 0 - argc/argv to main is supported
145 | 1 - argc/argv to main is not supported
146 |
147 | Note :
148 | This flag only matters if MULTITHREAD has been defined to a value greater then 1.
149 | */
150 | #define MAIN_HAS_NOARGC 1
151 |
152 | /* Configuration : MAIN_HAS_NORETURN
153 | Needed if platform does not support returning a value from main.
154 |
155 | Valid values :
156 | 0 - main returns an int, and return value will be 0.
157 | 1 - platform does not support returning a value from main
158 | Clang requires main to return an int.
159 | */
160 | #ifndef MAIN_HAS_NORETURN
161 | #define MAIN_HAS_NORETURN 0
162 | #endif
163 |
164 | /* Variable : default_num_contexts
165 | Not used for this simple port, must cintain the value 1.
166 | */
167 | extern ee_u32 default_num_contexts;
168 |
169 | typedef struct CORE_PORTABLE_S {
170 | ee_u8 portable_id;
171 | } core_portable;
172 |
173 | /* target specific init/fini */
174 | void portable_init(core_portable *p, int *argc, char *argv[]);
175 | void portable_fini(core_portable *p);
176 |
177 | #if !defined(PROFILE_RUN) && !defined(PERFORMANCE_RUN) && !defined(VALIDATION_RUN)
178 | #if (TOTAL_DATA_SIZE==1200)
179 | #define PROFILE_RUN 1
180 | #elif (TOTAL_DATA_SIZE==2000)
181 | #define PERFORMANCE_RUN 1
182 | #else
183 | #define VALIDATION_RUN 1
184 | #endif
185 | #endif
186 |
187 | int ee_printf(const char *fmt, ...);
188 |
189 | #define CLOCKS_PER_SEC 1000
190 |
191 | #endif /* CORE_PORTME_H */
192 |
--------------------------------------------------------------------------------
/core_portme.mak:
--------------------------------------------------------------------------------
1 | #File : core_portme.mak
2 | # Command line:
3 | # make XCFLAGS="-DTOTAL_DATA_SIZE=6000 -DMAIN_HAS_NOARGC=1" PORT_DIR=coremark_lm32 clean
4 |
5 | # We utilize the Milkymist bios for I/O and timer.
6 | MMDIR = /home/jpbonn/Documents/mico32/milkymist
7 | MMDIR = /opt/milkymist/milkymist/
8 | #############################################################################
9 | # Mico32 toolchain
10 | #
11 | COMPILERRT_DIR=/home/jp/Documents/baseline/compiler-rt-lm32/lm32/emb
12 | # try out the gcc compiled lm32-elf newlib instead of our clang compiled one
13 | NEWLIB_DIR=/home/jpbonn/Documents/mico32/lm32-gcc/install/lm32-elf
14 | # use the clang compiled newlib
15 | NEWLIB_DIR=/home/jp/Documents/baseline/newlib/build/install/lm32-elf
16 | LIBGLOSS_DIR=/home/jp/Documents/baseline/newlib/build-libgloss/install/lib/
17 |
18 | # Toolchain options
19 | #
20 | #INCLUDES_NOLIBC ?= -nostdinc -I$(MMDIR)/software/include/base ASFD
21 | INCLUDES_NOLIBC ?= -I$(MMDIR)/software/include/base
22 | INCLUDES = $(INCLUDES_NOLIBC) -I$(MMDIR)/software/include -I$(MMDIR)/tools -I$(NEWLIB_DIR)/include
23 | #ASFLAGS = $(INCLUDES) -nostdinc
24 | ASFLAGS = $(INCLUDES)
25 | # later: -Wmissing-prototypes
26 | PORT_CFLAGS = -g -O9 -Wall -Wstrict-prototypes -Wold-style-definition -Wshadow \
27 | -mbarrel-shift-enabled -mmultiply-enabled -mdivide-enabled \
28 | -msign-extend-enabled -fno-builtin -fsigned-char \
29 | -fsingle-precision-constant $(INCLUDES)
30 | #LDFLAGS = -nostdlib -nodefaultlibs
31 |
32 | ############################################################################
33 |
34 | # Flag : OUTFLAG
35 | # Use this flag to define how to to get an executable (e.g -o)
36 | OUTFLAG= -o
37 | CC=clang -march=lm32 -ccc-host-triple lm32 -ccc-gcc-name lm32-rtems4.11-gcc
38 | LD = lm32-rtems4.11-ld
39 | AS = lm32-rtems4.11-as
40 | OBJCOPY = lm32-rtems4.11-objcopy
41 | # Flag : CFLAGS
42 | # Use this flag to define compiler options. Note, you can add compiler options from the command line using XCFLAGS="other flags"
43 | #PORT_CFLAGS = -O0 -g -march=lm32 -ccc-host-triple lm32 -ccc-gcc-name lm32-rtems4.11-gcc
44 | FLAGS_STR = "$(PORT_CFLAGS) $(XCFLAGS) $(XLFLAGS) $(LFLAGS_END)"
45 | CFLAGS = $(PORT_CFLAGS) -I$(PORT_DIR) -I. -DFLAGS_STR=\"$(FLAGS_STR)\"
46 | #Flag : LFLAGS_END
47 | # Define any libraries needed for linking or other flags that should come at the end of the link line (e.g. linker scripts).
48 | # Note : On certain platforms, the default clock_gettime implementation is supported but requires linking of librt.
49 | SEPARATE_COMPILE=1
50 | # Flag : SEPARATE_COMPILE
51 | # You must also define below how to create an object file, and how to link.
52 | OBJOUT = -o
53 | LFLAGS = -nostdlib -nodefaultlibs -T $(PORT_DIR)/linker.ld -N --start-group
54 | ASFLAGS =
55 | OFLAG = -o
56 | COUT = -c
57 |
58 | #LFLAGS_END = --end-group -L$(MMDIR)/software/libhpdmc -L$(MMDIR)/software/libbase -L$(MMDIR)/software/libhal -L$(MMDIR)/software/libnet -L$(NEWLIB_DIR)/lib --start-group -lbase-light -lhal -lc -lm --end-group -L$(COMPILERRT_DIR) -lcompiler_rt
59 | LFLAGS_END = --end-group -L$(MMDIR)/software/libhpdmc -L$(MMDIR)/software/libbase -L$(MMDIR)/software/libhal -L$(MMDIR)/software/libnet -L$(NEWLIB_DIR)/lib --start-group -lbase-light -lhal -lc -lm --end-group -L$(COMPILERRT_DIR) -lcompiler_rt -L$(LIBGLOSS_DIR) -lnosys
60 | #LFLAGS_END = --end-group -L$(MMDIR)/software/libhpdmc -L$(MMDIR)/software/libbase -L$(MMDIR)/software/libhal -L$(MMDIR)/software/libnet -L$(NEWLIB_DIR)/lib --start-group -lbase-light -lhal -lc -lm --end-group -L$(COMPILERRT_DIR) -lcompiler_rt
61 |
62 | # Flag : PORT_SRCS
63 | # Port specific source files can be added here
64 | # You may also need cvt.c if the fcvt functions are not provided as intrinsics by your compiler!
65 | PORT_SRCS = $(PORT_DIR)/core_portme.c $(PORT_DIR)/ee_printf.c
66 | vpath %.c $(PORT_DIR)
67 | vpath %.s $(PORT_DIR)
68 |
69 | # Flag: PORT_OBJS
70 | # Port specific object files can be added here
71 | #PORT_OBJS = $(PORT_DIR)/crt0.o $(PORT_DIR)/core_portme.o $(PORT_DIR)/ee_printf.o $(PORT_DIR)/isr.o
72 | PORT_OBJS = $(PORT_DIR)/core_portme.o $(PORT_DIR)/ee_printf.o $(PORT_DIR)/isr.o
73 | PORT_CLEAN = $(PORT_DIR)/*.o *.bin *.out *.fbi *.o
74 |
75 |
76 | # Flag : LOAD
77 | # For a simple port, we assume self hosted compile and run, no load needed.
78 |
79 | # Flag : RUN
80 | # For a simple port, we assume self hosted compile and run, simple invocation of the executable
81 |
82 | LOAD = echo "Please set LOAD to the process of loading the executable to the flash"
83 | RUN = echo "Please set LOAD to the process of running the executable (e.g. via jtag, or board reset)"
84 | RUN = qemu-system-lm32 -M milkymist -nographic -kernel
85 |
86 | OEXT = .o
87 | EXE = .out
88 |
89 | $(OPATH)$(PORT_DIR)/%$(OEXT) : %.c
90 | $(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
91 |
92 | $(OPATH)%$(OEXT) : %.c
93 | $(CC) $(CFLAGS) $(XCFLAGS) $(COUT) $< $(OBJOUT) $@
94 |
95 | $(OPATH)$(PORT_DIR)/%$(OEXT) : %.S
96 | $(AS) $(ASFLAGS) $< $(OBJOUT) $@
97 |
98 | $(OPATH)$(PORT_DIR)/%$(OEXT) : %.s
99 | $(AS) $(ASFLAGS) $< $(OBJOUT) $@
100 |
101 | # Target: port_postbuild
102 | # Generate boot images for Milkymist One
103 | .PHONY: port_postbuild
104 | port_postbuild: $(OUTNAME)
105 | echo "Doing postbuild on $(OUTNAME)"
106 | $(OBJCOPY) -O binary $(OUTNAME) coremark.bin
107 | mkmmimg coremark.bin write coremark.fbi
108 |
109 | # Target: port_prebuild
110 | # Build crt0.o separately. It was getting linked in twice if
111 | # it was added to PORT_OBJS since the linker STARTUP directive
112 | # included it too.
113 | .PHONY: port_prebuild
114 | port_prebuild:
115 | echo "*******Doing prebuild "
116 | make $(PORT_DIR)/crt0.o
117 |
118 | # Target : port_pre% and port_post%
119 | # For the purpose of this simple port, no pre or post steps needed.
120 | .PHONY : port_prebuild port_prerun port_postrun port_preload port_postload
121 | port_pre% port_post% :
122 |
123 | # FLAG : OPATH
124 | # Path to the output folder. Default - current folder.
125 | OPATH = ./
126 | MKDIR = mkdir -p
127 |
128 |
--------------------------------------------------------------------------------
/core_portme.c:
--------------------------------------------------------------------------------
1 | /*
2 | File : core_portme.c
3 | */
4 | /*
5 | Author : Shay Gal-On, EEMBC
6 | Legal : TODO!
7 | */
8 | #include "coremark.h"
9 | #include "core_portme.h"
10 |
11 | #include
12 |
13 | #if VALIDATION_RUN
14 | volatile ee_s32 seed1_volatile=0x3415;
15 | volatile ee_s32 seed2_volatile=0x3415;
16 | volatile ee_s32 seed3_volatile=0x66;
17 | #endif
18 | #if PERFORMANCE_RUN
19 | volatile ee_s32 seed1_volatile=0x0;
20 | volatile ee_s32 seed2_volatile=0x0;
21 | volatile ee_s32 seed3_volatile=0x66;
22 | #endif
23 | #if PROFILE_RUN
24 | volatile ee_s32 seed1_volatile=0x8;
25 | volatile ee_s32 seed2_volatile=0x8;
26 | volatile ee_s32 seed3_volatile=0x8;
27 | #endif
28 | volatile ee_s32 seed4_volatile=ITERATIONS;
29 | volatile ee_s32 seed5_volatile=0;
30 | /* Porting : Timing functions
31 | How to capture time and convert to seconds must be ported to whatever is supported by the platform.
32 | e.g. Read value from on board RTC, read value from cpu clock cycles performance counter etc.
33 | Sample implementation for standard time.h and windows.h definitions included.
34 |
35 | We're returning milliseconds.
36 | */
37 | static unsigned int time = 0;
38 | CORETIMETYPE barebones_clock() {
39 |
40 | struct timestamp dest;
41 | time_get(&dest);
42 | return dest.sec*1000 + dest.usec/1000;
43 |
44 | return time;
45 | }
46 | /* Define : TIMER_RES_DIVIDER
47 | Divider to trade off timer resolution and total time that can be measured.
48 |
49 | Use lower values to increase resolution, but make sure that overflow does not occur.
50 | If there are issues with the return value overflowing, increase this value.
51 | */
52 | #define GETMYTIME(_t) (*_t=barebones_clock())
53 | #define MYTIMEDIFF(fin,ini) ((fin)-(ini))
54 | #define TIMER_RES_DIVIDER 1
55 | #define SAMPLE_TIME_IMPLEMENTATION 1
56 | #define EE_TICKS_PER_SEC (CLOCKS_PER_SEC / TIMER_RES_DIVIDER)
57 |
58 | /** Define Host specific (POSIX), or target specific global time variables. */
59 | static CORETIMETYPE start_time_val, stop_time_val;
60 |
61 | /* Function : start_time
62 | This function will be called right before starting the timed portion of the benchmark.
63 |
64 | Implementation may be capturing a system timer (as implemented in the example code)
65 | or zeroing some system parameters - e.g. setting the cpu clocks cycles to 0.
66 |
67 | */
68 | void start_time(void) {
69 | GETMYTIME(&start_time_val );
70 | }
71 | /* Function : stop_time
72 | This function will be called right after ending the timed portion of the benchmark.
73 |
74 | Implementation may be capturing a system timer (as implemented in the example code)
75 | or other system parameters - e.g. reading the current value of cpu cycles counter.
76 | */
77 | void stop_time(void) {
78 | GETMYTIME(&stop_time_val );
79 | }
80 | /* Function : get_time
81 | Return an abstract "ticks" number that signifies time on the system.
82 |
83 | Actual value returned may be cpu cycles, milliseconds or any other value,
84 | as long as it can be converted to seconds by .
85 | This methodology is taken to accomodate any hardware or simulated platform.
86 | The sample implementation returns millisecs by default,
87 | and the resolution is controlled by
88 | */
89 | CORE_TICKS get_time(void) {
90 | CORE_TICKS elapsed=(CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val));
91 | return elapsed;
92 | }
93 | /* Function : time_in_secs
94 | Convert the value returned by get_time to seconds.
95 |
96 | The type is used to accomodate systems with no support for floating point.
97 | Default implementation implemented by the EE_TICKS_PER_SEC macro above.
98 | */
99 | secs_ret time_in_secs(CORE_TICKS ticks) {
100 | secs_ret retval=((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC;
101 | return retval;
102 | }
103 |
104 | ee_u32 default_num_contexts=1;
105 |
106 | extern int main(void);
107 |
108 | /* External Milkymist functions: */
109 | void splash_display();
110 |
111 | #include
112 | #include
113 | #include
114 | #include
115 | #include
116 | #include
117 | #include
118 | /* #include */
119 | #include
120 | #include
121 | #include
122 | #include
123 | #include
124 | #include
125 | #include
126 | #include
127 | #include
128 | #include
129 |
130 | #include
131 | #include
132 | #include
133 | #include
134 | #include
135 |
136 | static const char banner[] =
137 | "\nMILKYMIST(tm) v"VERSION" BIOS http://www.milkymist.org\n"
138 | "(c) Copyright 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq\n\n"
139 | "This program is free software: you can redistribute it and/or modify\n"
140 | "it under the terms of the GNU General Public License as published by\n"
141 | "the Free Software Foundation, version 3 of the License.\n\n";
142 |
143 | void
144 | time_tick(void)
145 | {
146 | return;
147 | }
148 |
149 | int rescue;
150 |
151 | /* main is from Milkymist bios. */
152 | int port_main(int i, char **c)
153 | {
154 | /* lock gdbstub ROM */
155 | CSR_DBG_CTRL = DBG_CTRL_GDB_ROM_LOCK;
156 |
157 | /* enable bus errors */
158 | CSR_DBG_CTRL = DBG_CTRL_BUS_ERR_EN;
159 |
160 | CSR_GPIO_OUT = GPIO_LED1;
161 | rescue = !((unsigned int)main > FLASH_OFFSET_REGULAR_BIOS);
162 |
163 | irq_setmask(0);
164 | irq_enable(1);
165 | time_init();
166 | uart_init();
167 | // vga_init(!(rescue || (CSR_GPIO_IN & GPIO_BTN2)));
168 | putsnonl(banner);
169 | // crcbios();
170 | // brd_init();
171 | // tmu_init(); /* < for hardware-accelerated scrolling */
172 | // usb_init();
173 | // ukb_init();
174 |
175 | if(rescue)
176 | printf("I: Booting in rescue mode\n");
177 |
178 | // splash_display();
179 | // ethreset(); /* < that pesky ethernet PHY needs two resets at times... */
180 | // print_mac();
181 | // boot_sequence();
182 | // vga_unblank();
183 | // vga_set_console(1);
184 | uart_force_sync(1);
185 | while (1) {
186 | putsnonl("\e[1mStarting CoreMark\e[0m\n");
187 | main();
188 | putsnonl("\e[1mCoreMark ended.\e[0m \n\n");
189 | }
190 | return 0;
191 | }
192 |
193 |
194 | /* Function : portable_init
195 | Target specific initialization code
196 | Test for some common mistakes.
197 | */
198 | void portable_init(core_portable *p, int *argc, char *argv[])
199 | {
200 | if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) {
201 | ee_printf("ERROR! Please define ee_ptr_int to a type that holds a pointer!\n");
202 | }
203 | if (sizeof(ee_u32) != 4) {
204 | ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n");
205 | }
206 | p->portable_id=1;
207 | }
208 | /* Function : portable_fini
209 | Target specific final code
210 | */
211 | void portable_fini(core_portable *p)
212 | {
213 | p->portable_id=0;
214 | }
215 |
216 |
217 |
--------------------------------------------------------------------------------
/boot.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Milkymist SoC (Software)
3 | * Copyright (C) 2007, 2008, 2009, 2010, 2011 Sebastien Bourdeauducq
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU General Public License as published by
7 | * the Free Software Foundation, version 3 of the License.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with this program. If not, see .
16 | */
17 |
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include
31 | #include
32 |
33 | #include
34 | #include
35 |
36 | #include
37 | #include
38 |
39 | /*
40 | #include "unlzma.h"
41 | */
42 | #include "boot.h"
43 |
44 | extern const struct board_desc *brd_desc;
45 | extern int rescue;
46 |
47 | extern void boot_helper(unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int addr);
48 |
49 | static void __attribute__((noreturn)) boot(unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4, unsigned int addr)
50 | {
51 | vga_blank();
52 | uart_force_sync(1);
53 | irq_setmask(0);
54 | irq_enable(0);
55 | boot_helper(r1, r2, r3, r4, addr);
56 | while(1);
57 | }
58 |
59 | /* Note that we do not use the hw timer so that this function works
60 | * even if the system controller does not.
61 | */
62 | static int check_ack()
63 | {
64 | int timeout;
65 | int recognized;
66 | static const char str[SFL_MAGIC_LEN] = SFL_MAGIC_ACK;
67 |
68 | timeout = 2000000;
69 | recognized = 0;
70 | while(timeout > 0) {
71 | if(uart_read_nonblock()) {
72 | char c;
73 | c = uart_read();
74 | if(c == str[recognized]) {
75 | recognized++;
76 | if(recognized == SFL_MAGIC_LEN)
77 | return 1;
78 | } else {
79 | if(c == str[0])
80 | recognized = 1;
81 | else
82 | recognized = 0;
83 | }
84 | }
85 | timeout--;
86 | }
87 | return 0;
88 | }
89 |
90 | #define MAX_FAILED 5
91 |
92 | void serialboot()
93 | {
94 | struct sfl_frame frame;
95 | int failed;
96 | unsigned int cmdline_adr, initrdstart_adr, initrdend_adr;
97 | static const char str[SFL_MAGIC_LEN] = SFL_MAGIC_REQ;
98 | const char *c;
99 |
100 | printf("I: Attempting serial firmware loading\n");
101 |
102 | usb_debug_enable(0);
103 |
104 | c = str;
105 | while(*c) {
106 | uart_write(*c);
107 | c++;
108 | }
109 | if(!check_ack()) {
110 | printf("E: Timeout\n");
111 | usb_debug_enable(1);
112 | return;
113 | }
114 |
115 | failed = 0;
116 | cmdline_adr = initrdstart_adr = initrdend_adr = 0;
117 | while(1) {
118 | int i;
119 | int actualcrc;
120 | int goodcrc;
121 |
122 | /* Grab one frame */
123 | frame.length = uart_read();
124 | frame.crc[0] = uart_read();
125 | frame.crc[1] = uart_read();
126 | frame.cmd = uart_read();
127 | for(i=0;i 0)
229 | printf("I: Successfully downloaded %d bytes from %s over TFTP\n", r, filename);
230 | else
231 | printf("I: Unable to download %s over TFTP\n", filename);
232 | return r;
233 | }
234 |
235 | void netboot()
236 | {
237 | int size;
238 | unsigned int cmdline_adr, initrdstart_adr, initrdend_adr;
239 | unsigned int ip;
240 | unsigned char *macadr = (unsigned char *)FLASH_OFFSET_MAC_ADDRESS;
241 |
242 | printf("I: Booting from network...\n");
243 | printf("I: MAC : %02x:%02x:%02x:%02x:%02x:%02x\n", macadr[0], macadr[1], macadr[2], macadr[3], macadr[4], macadr[5]);
244 | printf("I: Local IP : %d.%d.%d.%d\n", LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4);
245 | printf("I: Remote IP: %d.%d.%d.%d\n", REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
246 |
247 | ip = IPTOINT(REMOTEIP1, REMOTEIP2, REMOTEIP3, REMOTEIP4);
248 |
249 | microudp_start(macadr, IPTOINT(LOCALIP1, LOCALIP2, LOCALIP3, LOCALIP4));
250 |
251 | if(tftp_get_v(ip, "boot.bin", (void *)SDRAM_BASE) <= 0) {
252 | printf("E: Network boot failed\n");
253 | return;
254 | }
255 |
256 | cmdline_adr = SDRAM_BASE+0x1000000;
257 | size = tftp_get_v(ip, "cmdline.txt", (void *)cmdline_adr);
258 | if(size <= 0) {
259 | printf("I: No command line parameters found\n");
260 | cmdline_adr = 0;
261 | } else
262 | *((char *)(cmdline_adr+size)) = 0x00;
263 |
264 | initrdstart_adr = SDRAM_BASE+0x1002000;
265 | size = tftp_get_v(ip, "initrd.bin", (void *)initrdstart_adr);
266 | if(size <= 0) {
267 | printf("I: No initial ramdisk found\n");
268 | initrdstart_adr = 0;
269 | initrdend_adr = 0;
270 | } else
271 | initrdend_adr = initrdstart_adr + size;
272 |
273 | printf("I: Booting...\n");
274 | boot(cmdline_adr, initrdstart_adr, initrdend_adr, rescue, SDRAM_BASE);
275 | }
276 |
277 | static int tryload(char *filename, unsigned int address)
278 | {
279 | int devsize, realsize;
280 |
281 | devsize = fatfs_load(filename, (char *)address, 16*1024*1024, &realsize);
282 | if(devsize <= 0)
283 | return -1;
284 | if(realsize > devsize) {
285 | printf("E: File size larger than the blocks read (corrupted FS or IO error ?)\n");
286 | return -1;
287 | }
288 | printf("I: Read a %d byte image from %s\n", realsize, filename);
289 |
290 | return realsize;
291 | }
292 |
293 | void fsboot(int devnr)
294 | {
295 | int size;
296 | unsigned int cmdline_adr, initrdstart_adr, initrdend_adr;
297 |
298 | printf("I: Booting from filesystem...\n");
299 | if(!fatfs_init(devnr)) {
300 | printf("E: Unable to initialize filesystem\n");
301 | return;
302 | }
303 |
304 | if(tryload("BOOT.BIN", SDRAM_BASE) <= 0) {
305 | printf("E: Firmware image not found\n");
306 | fatfs_done();
307 | return;
308 | }
309 |
310 | cmdline_adr = SDRAM_BASE+0x1000000;
311 | size = tryload("CMDLINE.TXT", cmdline_adr);
312 | if(size <= 0) {
313 | printf("I: No command line parameters found (CMDLINE.TXT)\n");
314 | cmdline_adr = 0;
315 | } else
316 | *((char *)(cmdline_adr+size)) = 0x00;
317 |
318 | initrdstart_adr = SDRAM_BASE+0x1002000;
319 | size = tryload("INITRD.BIN", initrdstart_adr);
320 | if(size <= 0) {
321 | printf("I: No initial ramdisk found (INITRD.BIN)\n");
322 | initrdstart_adr = 0;
323 | initrdend_adr = 0;
324 | } else
325 | initrdend_adr = initrdstart_adr + size;
326 |
327 | fatfs_done();
328 | printf("I: Booting...\n");
329 | boot(cmdline_adr, initrdstart_adr, initrdend_adr, rescue, SDRAM_BASE);
330 | }
331 |
332 | /*
333 | static void lzma_error(char *x)
334 | {
335 | printf("LZMA error: %s\n", x);
336 | }
337 | */
338 |
339 | void flashboot()
340 | {
341 | unsigned int *flashbase;
342 | unsigned int length;
343 | unsigned int crc;
344 | unsigned int got_crc;
345 | int lzma;
346 |
347 | printf("I: Booting from flash...\n");
348 | if(rescue)
349 | flashbase = (unsigned int *)FLASH_OFFSET_RESCUE_APP;
350 | else
351 | flashbase = (unsigned int *)FLASH_OFFSET_REGULAR_APP;
352 | length = *flashbase++;
353 | if(length & 0x80000000) {
354 | length &= 0x7fffffff;
355 | lzma = 1;
356 | } else
357 | lzma = 0;
358 | crc = *flashbase++;
359 | if((length < 32) || (length > 4*1024*1024)) {
360 | printf("E: Invalid flash boot image length\n");
361 | return;
362 | }
363 | if(lzma) {
364 | printf("UNSUPPORTED: I: Decompressing %d bytes from flash...\n", length);
365 | /*
366 | int r;
367 | got_crc = crc32((unsigned char *)flashbase, length);
368 | if(crc != got_crc) {
369 | printf("E: CRC failed (expected %08x, got %08x)\n", crc, got_crc);
370 | return;
371 | }
372 | r = unlzma((unsigned char *)flashbase, length, NULL, NULL, (void *)SDRAM_BASE, NULL, lzma_error);
373 | if(r < 0)
374 | return;
375 | */
376 | } else {
377 | printf("I: Loading %d bytes from flash...\n", length);
378 | memcpy((void *)SDRAM_BASE, flashbase, length);
379 | got_crc = crc32((unsigned char *)SDRAM_BASE, length);
380 | if(crc != got_crc) {
381 | printf("E: CRC failed (expected %08x, got %08x)\n", crc, got_crc);
382 | return;
383 | }
384 | }
385 | printf("I: Booting...\n");
386 | boot(0, 0, 0, rescue, SDRAM_BASE);
387 | }
388 |
--------------------------------------------------------------------------------
/ee_printf.c:
--------------------------------------------------------------------------------
1 | /* File : barebones/ee_printf.c
2 | This file contains an implementation of ee_printf that only requires a method to output a char to a UART without pulling in library code.
3 |
4 | This code is based on a file that contains the following:
5 | Copyright (C) 2002 Michael Ringgaard. All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without
8 | modification, are permitted provided that the following conditions
9 | are met:
10 |
11 | 1. Redistributions of source code must retain the above copyright
12 | notice, this list of conditions and the following disclaimer.
13 | 2. Redistributions in binary form must reproduce the above copyright
14 | notice, this list of conditions and the following disclaimer in the
15 | documentation and/or other materials provided with the distribution.
16 | 3. Neither the name of the project nor the names of its contributors
17 | may be used to endorse or promote products derived from this software
18 | without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 | SUCH DAMAGE.
31 |
32 | */
33 |
34 | #include
35 | #include
36 |
37 | #define ZEROPAD (1<<0) /* Pad with zero */
38 | #define SIGN (1<<1) /* Unsigned/signed long */
39 | #define PLUS (1<<2) /* Show plus */
40 | #define SPACE (1<<3) /* Spacer */
41 | #define LEFT (1<<4) /* Left justified */
42 | #define HEX_PREP (1<<5) /* 0x */
43 | #define UPPERCASE (1<<6) /* 'ABCDEF' */
44 |
45 | #define is_digit(c) ((c) >= '0' && (c) <= '9')
46 |
47 | static char *lower_digits = "0123456789abcdefghijklmnopqrstuvwxyz";
48 | static char *upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
49 | static size_t strnlen(const char *s, size_t count);
50 |
51 | static size_t strnlen(const char *s, size_t count)
52 | {
53 | const char *sc;
54 | for (sc = s; *sc != '\0' && count--; ++sc);
55 | return sc - s;
56 | }
57 |
58 | static int ee_skip_atoi(const char **s)
59 | {
60 | int i = 0;
61 | while (is_digit(**s)) i = i*10 + *((*s)++) - '0';
62 | return i;
63 | }
64 |
65 | static char *ee_number(char *str, long num, int base, int size, int precision, int type)
66 | {
67 | char c, sign, tmp[66];
68 | char *dig = lower_digits;
69 | int i;
70 |
71 | if (type & UPPERCASE) dig = upper_digits;
72 | if (type & LEFT) type &= ~ZEROPAD;
73 | if (base < 2 || base > 36) return 0;
74 |
75 | c = (type & ZEROPAD) ? '0' : ' ';
76 | sign = 0;
77 | if (type & SIGN)
78 | {
79 | if (num < 0)
80 | {
81 | sign = '-';
82 | num = -num;
83 | size--;
84 | }
85 | else if (type & PLUS)
86 | {
87 | sign = '+';
88 | size--;
89 | }
90 | else if (type & SPACE)
91 | {
92 | sign = ' ';
93 | size--;
94 | }
95 | }
96 |
97 | if (type & HEX_PREP)
98 | {
99 | if (base == 16)
100 | size -= 2;
101 | else if (base == 8)
102 | size--;
103 | }
104 |
105 | i = 0;
106 |
107 | if (num == 0)
108 | tmp[i++] = '0';
109 | else
110 | {
111 | while (num != 0)
112 | {
113 | tmp[i++] = dig[((unsigned long) num) % (unsigned) base];
114 | num = ((unsigned long) num) / (unsigned) base;
115 | }
116 | }
117 |
118 | if (i > precision) precision = i;
119 | size -= precision;
120 | if (!(type & (ZEROPAD | LEFT))) while (size-- > 0) *str++ = ' ';
121 | if (sign) *str++ = sign;
122 |
123 | if (type & HEX_PREP)
124 | {
125 | if (base == 8)
126 | *str++ = '0';
127 | else if (base == 16)
128 | {
129 | *str++ = '0';
130 | *str++ = lower_digits[33];
131 | }
132 | }
133 |
134 | if (!(type & LEFT)) while (size-- > 0) *str++ = c;
135 | while (i < precision--) *str++ = '0';
136 | while (i-- > 0) *str++ = tmp[i];
137 | while (size-- > 0) *str++ = ' ';
138 |
139 | return str;
140 | }
141 |
142 | static char *eaddr(char *str, unsigned char *addr, int size, int precision, int type)
143 | {
144 | char tmp[24];
145 | char *dig = lower_digits;
146 | int i, len;
147 |
148 | if (type & UPPERCASE) dig = upper_digits;
149 | len = 0;
150 | for (i = 0; i < 6; i++)
151 | {
152 | if (i != 0) tmp[len++] = ':';
153 | tmp[len++] = dig[addr[i] >> 4];
154 | tmp[len++] = dig[addr[i] & 0x0F];
155 | }
156 |
157 | if (!(type & LEFT)) while (len < size--) *str++ = ' ';
158 | for (i = 0; i < len; ++i) *str++ = tmp[i];
159 | while (len < size--) *str++ = ' ';
160 |
161 | return str;
162 | }
163 |
164 | static char *iaddr(char *str, unsigned char *addr, int size, int precision, int type)
165 | {
166 | char tmp[24];
167 | int i, n, len;
168 |
169 | len = 0;
170 | for (i = 0; i < 4; i++)
171 | {
172 | if (i != 0) tmp[len++] = '.';
173 | n = addr[i];
174 |
175 | if (n == 0)
176 | tmp[len++] = lower_digits[0];
177 | else
178 | {
179 | if (n >= 100)
180 | {
181 | tmp[len++] = lower_digits[n / 100];
182 | n = n % 100;
183 | tmp[len++] = lower_digits[n / 10];
184 | n = n % 10;
185 | }
186 | else if (n >= 10)
187 | {
188 | tmp[len++] = lower_digits[n / 10];
189 | n = n % 10;
190 | }
191 |
192 | tmp[len++] = lower_digits[n];
193 | }
194 | }
195 |
196 | if (!(type & LEFT)) while (len < size--) *str++ = ' ';
197 | for (i = 0; i < len; ++i) *str++ = tmp[i];
198 | while (len < size--) *str++ = ' ';
199 |
200 | return str;
201 | }
202 |
203 | #ifdef HAS_FLOAT
204 |
205 | char *ecvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
206 | char *fcvtbuf(double arg, int ndigits, int *decpt, int *sign, char *buf);
207 | static void ee_bufcpy(char *d, char *s, int count);
208 |
209 | void ee_bufcpy(char *pd, char *ps, int count) {
210 | char *pe=ps+count;
211 | while (ps!=pe)
212 | *pd++=*ps++;
213 | }
214 |
215 | static void parse_float(double value, char *buffer, char fmt, int precision)
216 | {
217 | int decpt, sign, exp, pos;
218 | char *fdigits = NULL;
219 | char cvtbuf[80];
220 | int capexp = 0;
221 | int magnitude;
222 |
223 | if (fmt == 'G' || fmt == 'E')
224 | {
225 | capexp = 1;
226 | fmt += 'a' - 'A';
227 | }
228 |
229 | if (fmt == 'g')
230 | {
231 | fdigits = ecvtbuf(value, precision, &decpt, &sign, cvtbuf);
232 | magnitude = decpt - 1;
233 | if (magnitude < -4 || magnitude > precision - 1)
234 | {
235 | fmt = 'e';
236 | precision -= 1;
237 | }
238 | else
239 | {
240 | fmt = 'f';
241 | precision -= decpt;
242 | }
243 | }
244 |
245 | if (fmt == 'e')
246 | {
247 | fdigits = ecvtbuf(value, precision + 1, &decpt, &sign, cvtbuf);
248 |
249 | if (sign) *buffer++ = '-';
250 | *buffer++ = *fdigits;
251 | if (precision > 0) *buffer++ = '.';
252 | ee_bufcpy(buffer, fdigits + 1, precision);
253 | buffer += precision;
254 | *buffer++ = capexp ? 'E' : 'e';
255 |
256 | if (decpt == 0)
257 | {
258 | if (value == 0.0)
259 | exp = 0;
260 | else
261 | exp = -1;
262 | }
263 | else
264 | exp = decpt - 1;
265 |
266 | if (exp < 0)
267 | {
268 | *buffer++ = '-';
269 | exp = -exp;
270 | }
271 | else
272 | *buffer++ = '+';
273 |
274 | buffer[2] = (exp % 10) + '0';
275 | exp = exp / 10;
276 | buffer[1] = (exp % 10) + '0';
277 | exp = exp / 10;
278 | buffer[0] = (exp % 10) + '0';
279 | buffer += 3;
280 | }
281 | else if (fmt == 'f')
282 | {
283 | fdigits = fcvtbuf(value, precision, &decpt, &sign, cvtbuf);
284 | if (sign) *buffer++ = '-';
285 | if (*fdigits)
286 | {
287 | if (decpt <= 0)
288 | {
289 | *buffer++ = '0';
290 | *buffer++ = '.';
291 | for (pos = 0; pos < -decpt; pos++) *buffer++ = '0';
292 | while (*fdigits) *buffer++ = *fdigits++;
293 | }
294 | else
295 | {
296 | pos = 0;
297 | while (*fdigits)
298 | {
299 | if (pos++ == decpt) *buffer++ = '.';
300 | *buffer++ = *fdigits++;
301 | }
302 | }
303 | }
304 | else
305 | {
306 | *buffer++ = '0';
307 | if (precision > 0)
308 | {
309 | *buffer++ = '.';
310 | for (pos = 0; pos < precision; pos++) *buffer++ = '0';
311 | }
312 | }
313 | }
314 |
315 | *buffer = '\0';
316 | }
317 |
318 | static void decimal_point(char *buffer)
319 | {
320 | while (*buffer)
321 | {
322 | if (*buffer == '.') return;
323 | if (*buffer == 'e' || *buffer == 'E') break;
324 | buffer++;
325 | }
326 |
327 | if (*buffer)
328 | {
329 | int n = strnlen(buffer,256);
330 | while (n > 0)
331 | {
332 | buffer[n + 1] = buffer[n];
333 | n--;
334 | }
335 |
336 | *buffer = '.';
337 | }
338 | else
339 | {
340 | *buffer++ = '.';
341 | *buffer = '\0';
342 | }
343 | }
344 |
345 | static void cropzeros(char *buffer)
346 | {
347 | char *stop;
348 |
349 | while (*buffer && *buffer != '.') buffer++;
350 | if (*buffer++)
351 | {
352 | while (*buffer && *buffer != 'e' && *buffer != 'E') buffer++;
353 | stop = buffer--;
354 | while (*buffer == '0') buffer--;
355 | if (*buffer == '.') buffer--;
356 | while (buffer!=stop)
357 | *++buffer=0;
358 | }
359 | }
360 |
361 | static char *flt(char *str, double num, int size, int precision, char fmt, int flags)
362 | {
363 | char tmp[80];
364 | char c, sign;
365 | int n, i;
366 |
367 | // Left align means no zero padding
368 | if (flags & LEFT) flags &= ~ZEROPAD;
369 |
370 | // Determine padding and sign char
371 | c = (flags & ZEROPAD) ? '0' : ' ';
372 | sign = 0;
373 | if (flags & SIGN)
374 | {
375 | if (num < 0.0)
376 | {
377 | sign = '-';
378 | num = -num;
379 | size--;
380 | }
381 | else if (flags & PLUS)
382 | {
383 | sign = '+';
384 | size--;
385 | }
386 | else if (flags & SPACE)
387 | {
388 | sign = ' ';
389 | size--;
390 | }
391 | }
392 |
393 | // Compute the precision value
394 | if (precision < 0)
395 | precision = 6; // Default precision: 6
396 |
397 | // Convert floating point number to text
398 | parse_float(num, tmp, fmt, precision);
399 |
400 | if ((flags & HEX_PREP) && precision == 0) decimal_point(tmp);
401 | if (fmt == 'g' && !(flags & HEX_PREP)) cropzeros(tmp);
402 |
403 | n = strnlen(tmp,256);
404 |
405 | // Output number with alignment and padding
406 | size -= n;
407 | if (!(flags & (ZEROPAD | LEFT))) while (size-- > 0) *str++ = ' ';
408 | if (sign) *str++ = sign;
409 | if (!(flags & LEFT)) while (size-- > 0) *str++ = c;
410 | for (i = 0; i < n; i++) *str++ = tmp[i];
411 | while (size-- > 0) *str++ = ' ';
412 |
413 | return str;
414 | }
415 |
416 | #endif
417 |
418 | static int ee_vsprintf(char *buf, const char *fmt, va_list args)
419 | {
420 | int len;
421 | unsigned long num;
422 | int i, base;
423 | char *str;
424 | char *s;
425 |
426 | int flags; // Flags to number()
427 |
428 | int field_width; // Width of output field
429 | int precision; // Min. # of digits for integers; max number of chars for from string
430 | int qualifier; // 'h', 'l', or 'L' for integer fields
431 |
432 | for (str = buf; *fmt; fmt++)
433 | {
434 | if (*fmt != '%')
435 | {
436 | *str++ = *fmt;
437 | continue;
438 | }
439 |
440 | // Process flags
441 | flags = 0;
442 | repeat:
443 | fmt++; // This also skips first '%'
444 | switch (*fmt)
445 | {
446 | case '-': flags |= LEFT; goto repeat;
447 | case '+': flags |= PLUS; goto repeat;
448 | case ' ': flags |= SPACE; goto repeat;
449 | case '#': flags |= HEX_PREP; goto repeat;
450 | case '0': flags |= ZEROPAD; goto repeat;
451 | }
452 |
453 | // Get field width
454 | field_width = -1;
455 | if (is_digit(*fmt))
456 | field_width = ee_skip_atoi(&fmt);
457 | else if (*fmt == '*')
458 | {
459 | fmt++;
460 | field_width = va_arg(args, int);
461 | if (field_width < 0)
462 | {
463 | field_width = -field_width;
464 | flags |= LEFT;
465 | }
466 | }
467 |
468 | // Get the precision
469 | precision = -1;
470 | if (*fmt == '.')
471 | {
472 | ++fmt;
473 | if (is_digit(*fmt))
474 | precision = ee_skip_atoi(&fmt);
475 | else if (*fmt == '*')
476 | {
477 | ++fmt;
478 | precision = va_arg(args, int);
479 | }
480 | if (precision < 0) precision = 0;
481 | }
482 |
483 | // Get the conversion qualifier
484 | qualifier = -1;
485 | if (*fmt == 'l' || *fmt == 'L')
486 | {
487 | qualifier = *fmt;
488 | fmt++;
489 | }
490 |
491 | // Default base
492 | base = 10;
493 |
494 | switch (*fmt)
495 | {
496 | case 'c':
497 | if (!(flags & LEFT)) while (--field_width > 0) *str++ = ' ';
498 | *str++ = (unsigned char) va_arg(args, int);
499 | while (--field_width > 0) *str++ = ' ';
500 | continue;
501 |
502 | case 's':
503 | s = va_arg(args, char *);
504 | if (!s) s = "";
505 | len = strnlen(s, precision);
506 | if (!(flags & LEFT)) while (len < field_width--) *str++ = ' ';
507 | for (i = 0; i < len; ++i) *str++ = *s++;
508 | while (len < field_width--) *str++ = ' ';
509 | continue;
510 |
511 | case 'p':
512 | if (field_width == -1)
513 | {
514 | field_width = 2 * sizeof(void *);
515 | flags |= ZEROPAD;
516 | }
517 | str = ee_number(str, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags);
518 | continue;
519 |
520 | case 'A':
521 | flags |= UPPERCASE;
522 |
523 | case 'a':
524 | if (qualifier == 'l')
525 | str = eaddr(str, va_arg(args, unsigned char *), field_width, precision, flags);
526 | else
527 | str = iaddr(str, va_arg(args, unsigned char *), field_width, precision, flags);
528 | continue;
529 |
530 | // Integer number formats - set up the flags and "break"
531 | case 'o':
532 | base = 8;
533 | break;
534 |
535 | case 'X':
536 | flags |= UPPERCASE;
537 |
538 | case 'x':
539 | base = 16;
540 | break;
541 |
542 | case 'd':
543 | case 'i':
544 | flags |= SIGN;
545 |
546 | case 'u':
547 | break;
548 |
549 | #ifdef HAS_FLOAT
550 |
551 | case 'f':
552 | str = flt(str, va_arg(args, double), field_width, precision, *fmt, flags | SIGN);
553 | continue;
554 |
555 | #endif
556 |
557 | default:
558 | if (*fmt != '%') *str++ = '%';
559 | if (*fmt)
560 | *str++ = *fmt;
561 | else
562 | --fmt;
563 | continue;
564 | }
565 |
566 | if (qualifier == 'l')
567 | num = va_arg(args, unsigned long);
568 | else if (flags & SIGN)
569 | num = va_arg(args, int);
570 | else
571 | num = va_arg(args, unsigned int);
572 |
573 | str = ee_number(str, num, base, field_width, precision, flags);
574 | }
575 |
576 | *str = '\0';
577 | return str - buf;
578 | }
579 |
580 | void uart_send_char(char c) {
581 | char str[2];
582 | str[0] = c;
583 | str[1] = '\0';
584 | putsnonl(str);
585 | }
586 |
587 | int ee_printf(const char *fmt, ...)
588 | {
589 | char buf[15*80],*p;
590 | va_list args;
591 | int n=0;
592 |
593 | va_start(args, fmt);
594 | ee_vsprintf(buf, fmt, args);
595 | va_end(args);
596 | p=buf;
597 | while (*p) {
598 | uart_send_char(*p);
599 | n++;
600 | p++;
601 | }
602 |
603 | return n;
604 | }
605 |
606 |
--------------------------------------------------------------------------------