├── 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 | --------------------------------------------------------------------------------