├── README.md ├── dual-bootloader ├── ATmegaBOOT_168.c ├── Makefile ├── NameBoardSketch │ └── NameBoardSketch.pde ├── README ├── avrdude ├── avrdude.conf ├── eeprom │ └── EEPROM_firm.hex ├── firms │ ├── .DS_Store │ ├── BOX0168.hex │ ├── BOX01682.hex │ ├── BOX0328.hex │ └── README.txt ├── mmc_fat.c ├── mmc_fat.h ├── prog_flash.c ├── prog_flash.h ├── stk500v1.c └── stk500v1.h └── eth-bootloader ├── bootloader client ├── Recv.java └── Send.java ├── eboot.xcodeproj └── project.pbxproj └── firmware ├── Makefile ├── Readme.txt ├── Test list.txt ├── announce.c ├── app.c ├── bigapp.c ├── debug.c ├── debug.h ├── main.c ├── main.h ├── net.c ├── net.h ├── neteeprom.h ├── settings.c ├── tftp.c ├── tftp.h ├── validate.c ├── validate.h └── w5100_reg.h /README.md: -------------------------------------------------------------------------------- 1 | Ethernet Bootloader 2 | ================== 3 | 4 | Dual bootloader 5 | =============== 6 | This bootloader was written originally by https://github.com/thseiler and adapted for Arduino Ethernet by David Cuartielles 7 | 8 | 9 | 10 | Arduino Ethernet board and TFTP Bootloader 11 | ========================================== 12 | 13 | The Arduino Ethernet board is built by merging a regular Arduino board with the Arduino Ethernet Shield. Therefore, codewise, anything that works on your Arduino plus Ethernet Shield works on this board. 14 | 15 | There are some small hardware improvements from the Ethernet shield, namely we have replaced the resistors used to adapt the 3.3v parts to 5v coming from the processor with new high speed buffer. This will allow faster transfer rate when accessing the SD Card. 16 | 17 | How to get code into your board: The boards that you have received don't have any bootloader installed on it, they have run a small test program in the factory. In order to upload code to the board you will need either an ISP programmer or an Arduino 2009 running the AVR ISP sketch (Arduino Uno's have some issues with the ISP sketch due to new bootloader) 18 | 19 | If you burn the normal Arduino bootloader on this board you can hook up an usb-serial converter (or an unchipped Arduino) to pins 0,1,GND and Reset to program it like any 2009 board. 20 | 21 | We have been developing an ethernet bootloader that will allow you to upload code to the board using a TFTP client. It's currently alpha quality code and we would immensely appreciate if you could help us test it and debug it. 22 | 23 | The boards that you have received should be fitted with a Power-Over-Ethernet (PoE) module, this allows you to power your board through its ethernet cable. 24 | These modules are compliant with current PoE standards and require a proper PoE enabled hub delivering 48 Volts. 25 | 26 | BE CAREFUL, when the Arduino Ethernet is connected to a PoE enabled hub, the bottom of the board has pins connected to 48V, be very very careful not to place the board on metallic surfaces. We recommend you place your Arduino in a plastic enclosure. 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /dual-bootloader/ATmegaBOOT_168.c: -------------------------------------------------------------------------------- 1 | /* $Id$ */ 2 | 3 | /* some includes */ 4 | #include 5 | #include 6 | #include "stk500v1.h" 7 | #include "mmc_fat.h" 8 | 9 | /* function prototypes */ 10 | void main (void) __attribute__ ((naked,section (".init9"))); 11 | static inline char bootloader_skip_condition(); 12 | 13 | /* some variables */ 14 | const void (*app_start)(void) = 0x0000; 15 | uint8_t reset_reason = 0; 16 | 17 | /* main program starts here */ 18 | void main(void) 19 | { 20 | /* here we learn how we were reset */ 21 | reset_reason = MCUSR; 22 | MCUSR = 0; 23 | 24 | /* stop watchdog */ 25 | WDTCSR |= _BV(WDCE) | _BV(WDE); 26 | WDTCSR = 0; 27 | 28 | /* start app right ahead if this was watchdog */ 29 | if ((reset_reason & _BV(WDRF))) app_start(); 30 | 31 | /* this is needed because of the __attribute__ naked, section .init 9 */ 32 | /* from now, we can call functions :-) */ 33 | asm volatile ( "clr __zero_reg__" ); 34 | SP=RAMEND; 35 | 36 | /* test if we should skip to the app immediately... */ 37 | if (bootloader_skip_condition()) app_start(); 38 | 39 | /* warning: this means that the rest of the bootloader only runs, */ 40 | /* if the bootloader_skip_condition returnd false !!! */ 41 | 42 | #ifndef DISABLE_MMC 43 | /* lets first try the mmc */ 44 | mmc_updater(); 45 | #endif 46 | 47 | #ifndef DISABLE_SERIAL 48 | /* the fall back to serial */ 49 | stk500v1(); 50 | #endif 51 | 52 | /* we reset via watchdog */ 53 | /* in order to re-enable the RWW section (see prog_flash.c...) */ 54 | WDTCSR = _BV(WDE); 55 | while (1); // 16 ms 56 | } 57 | 58 | /* here is a collection of conditions as to when to enter bootloader */ 59 | 60 | #ifdef CONDITION_FTTH_HEAD_VOLTAGE 61 | 62 | static char bootloader_skip_condition() { 63 | unsigned char high, low; 64 | unsigned short voltage; 65 | 66 | // enable adc 67 | ADMUX = _BV(REFS0) | _BV(REFS1) | 0x06; 68 | ADCSRA |= _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADSC); // 1/64 69 | loop_until_bit_is_clear(ADCSRA, ADSC); 70 | 71 | low = ADCL; 72 | high = ADCH; 73 | voltage = ((unsigned short)high << 8) | low; 74 | 75 | return (voltage < 292); 76 | } 77 | 78 | #elif defined(CONDITION_FTTH_CONT_BUTTONS) 79 | 80 | static char inline bootloader_skip_condition() { 81 | // quickstart-test, see if up/down buttons are pressed 82 | DDRD &= ~_BV(PIND5); /* input */ 83 | DDRD &= ~_BV(PIND6); 84 | PORTD |= _BV(PIND5); /* pullup */ 85 | PORTD |= _BV(PIND6); 86 | 87 | uint8_t i; 88 | for(i = 0;i<255;i++) { i = i; } // quick delay... 89 | 90 | // continue only to bootloader, if BEND and UNBEND is pressed together 91 | return (bit_is_set(PIND, PIND5) || bit_is_set(PIND,PIND6)); 92 | } 93 | 94 | #else 95 | 96 | /* this is the default condition */ 97 | /* we only continue into the bootloader on an external reset */ 98 | 99 | static char inline bootloader_skip_condition() { 100 | return ! (reset_reason & _BV(EXTRF)); 101 | } 102 | 103 | #endif 104 | 105 | /* end of file ATmegaBOOT.c */ 106 | 107 | -------------------------------------------------------------------------------- /dual-bootloader/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for ATmegaBOOT 2 | # E.Lins, 18.7.2005 3 | # $Id$ 4 | # 5 | # Instructions 6 | # 7 | # To make bootloader .hex file: 8 | # make diecimila 9 | # make lilypad 10 | # make ng 11 | # etc... 12 | # 13 | # To burn bootloader .hex file: 14 | # make diecimila_isp 15 | # make lilypad_isp 16 | # make ng_isp 17 | # etc... 18 | # 19 | # 20110318 - D. Cuartielles for Arduino 20 | # modified files to compile for boards using the Arduino Ethernet Shield as the SD reader 21 | # 22 | # this works fine for the Arduino Diecimila with the dual booting, for doing the compilation on Linux, use 23 | # make clean; make diecimila; sudo make diecimila_isp 24 | # 25 | # also adds the keyword "BOX" at the end of the EEPROM for the bootloader to distinguish the name of the 26 | # new versions of the firmware 27 | # 28 | # TODO: make this work for boards with atmega328, also make sure it works with Arduino Uno boards 29 | # 30 | 31 | .SECONDARY: 32 | 33 | # program name should not be changed... 34 | PROGRAM = ATmegaBOOT_168 35 | 36 | # enter the parameters for the avrdude isp tool 37 | ISPTOOL = avrispmkII 38 | ISPPORT = usb 39 | ISPSPEED = -b 115200 40 | 41 | MCU_TARGET = atmega168 42 | LDSECTION = --section-start=.text=0x3800 43 | 44 | # the efuse should really be 0xf8; since, however, only the lower 45 | # three bits of that byte are used on the atmega168, avrdude gets 46 | # confused if you specify 1's for the higher bits, see: 47 | # http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/ 48 | # 49 | # similarly, the lock bits should be 0xff instead of 0x3f (to 50 | # unlock the bootloader section) and 0xcf instead of 0x0f (to 51 | # lock it), but since the high two bits of the lock byte are 52 | # unused, avrdude would get confused. 53 | 54 | ISPFUSES = ./avrdude -C avrdude.conf -c $(ISPTOOL) -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \ 55 | -e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m 56 | ISPFLASH = ./avrdude -C avrdude.conf -c $(ISPTOOL) -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \ 57 | -U flash:w:$(PROGRAM)_$(TARGET).hex -U lock:w:0x0f:m 58 | ISPEEPROM = ./avrdude -C avrdude.conf -c $(ISPTOOL) -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \ 59 | -U eeprom:w:EEPROM_firm.hex:i 60 | 61 | # to read the EEPROM you need to use the following, essentially there is just three bytes in it saying BOX 62 | # that BOX is the name that the new firmware files should have, you can call them BOX000.hex, BOX001.hex, etc 63 | #./avrdude -C avrdude.conf -c mkii -p atmega168 -P usb 115200 -U eeprom:r:EEPROM_firm.hex:i 64 | # 65 | # get the pre-recorder EEPROM 66 | 67 | STK500 = "C:\Program Files\Atmel\AVR Tools\STK500\Stk500.exe" 68 | STK500-1 = $(STK500) -e -d$(MCU_TARGET) -pf -vf -if$(PROGRAM)_$(TARGET).hex \ 69 | -lFF -LFF -f$(HFUSE)$(LFUSE) -EF8 -ms -q -cUSB -I200kHz -s -wt 70 | STK500-2 = $(STK500) -d$(MCU_TARGET) -ms -q -lCF -LCF -cUSB -I200kHz -s -wt 71 | 72 | 73 | SRC = $(PROGRAM).c mmc_fat.c stk500v1.c prog_flash.c 74 | OPTIMIZE = -Os -funsigned-char -fno-split-wide-types -fno-inline-small-functions -mcall-prologues -ffunction-sections -fdata-sections -ffreestanding -combine -fwhole-program -fno-jump-tables 75 | 76 | DEFS = 77 | LIBS = 78 | 79 | CC = avr-gcc 80 | 81 | # Override is only needed by avr-lib build system. 82 | 83 | override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(AVR_FREQ) $(DEFS) 84 | override LDFLAGS = -Wl,$(LDSECTION) -Wl,--relax -nostartfiles -Wl,-gc-sections 85 | #override LDFLAGS = -Wl,-Map,$(PROGRAM).map,$(LDSECTION) 86 | 87 | OBJCOPY = avr-objcopy 88 | OBJDUMP = avr-objdump 89 | 90 | all: 91 | 92 | lilypad: TARGET = lilypad 93 | lilypad: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>1' '-DNUM_LED_FLASHES=3' 94 | lilypad: AVR_FREQ = 8000000L 95 | lilypad: $(PROGRAM)_lilypad.hex 96 | 97 | lilypad_isp: lilypad 98 | lilypad_isp: TARGET = lilypad 99 | lilypad_isp: HFUSE = DD 100 | lilypad_isp: LFUSE = E2 101 | lilypad_isp: EFUSE = 00 102 | lilypad_isp: isp 103 | 104 | lilypad_resonator: TARGET = lilypad_resonator 105 | lilypad_resonator: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=3' 106 | lilypad_resonator: AVR_FREQ = 8000000L 107 | lilypad_resonator: $(PROGRAM)_lilypad_resonator.hex 108 | 109 | lilypad_resonator_isp: lilypad_resonator 110 | lilypad_resonator_isp: TARGET = lilypad_resonator 111 | lilypad_resonator_isp: HFUSE = DD 112 | lilypad_resonator_isp: LFUSE = C6 113 | lilypad_resonator_isp: EFUSE = 00 114 | lilypad_resonator_isp: isp 115 | 116 | pro8: TARGET = pro_8MHz 117 | pro8: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS' 118 | pro8: AVR_FREQ = 8000000L 119 | pro8: $(PROGRAM)_pro_8MHz.hex 120 | 121 | pro8_isp: pro8 122 | pro8_isp: TARGET = pro_8MHz 123 | pro8_isp: HFUSE = DD 124 | pro8_isp: LFUSE = C6 125 | pro8_isp: EFUSE = 00 126 | pro8_isp: isp 127 | 128 | pro16: TARGET = pro_16MHz 129 | pro16: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS' 130 | pro16: AVR_FREQ = 16000000L 131 | pro16: $(PROGRAM)_pro_16MHz.hex 132 | 133 | pro16_isp: pro16 134 | pro16_isp: TARGET = pro_16MHz 135 | pro16_isp: HFUSE = DD 136 | pro16_isp: LFUSE = C6 137 | pro16_isp: EFUSE = 00 138 | pro16_isp: isp 139 | 140 | pro20: TARGET = pro_20mhz 141 | pro20: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' '-DWATCHDOG_MODS' 142 | pro20: AVR_FREQ = 20000000L 143 | pro20: $(PROGRAM)_pro_20mhz.hex 144 | 145 | pro20_isp: pro20 146 | pro20_isp: TARGET = pro_20mhz 147 | pro20_isp: HFUSE = DD 148 | pro20_isp: LFUSE = C6 149 | pro20_isp: EFUSE = 00 150 | pro20_isp: isp 151 | 152 | diecimila: TARGET = diecimila 153 | diecimila: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' 154 | diecimila: AVR_FREQ = 16000000L 155 | diecimila: $(PROGRAM)_diecimila.hex 156 | 157 | diecimila_isp: diecimila 158 | diecimila_isp: TARGET = diecimila 159 | diecimila_isp: HFUSE = DD 160 | diecimila_isp: LFUSE = FF 161 | diecimila_isp: EFUSE = 00 162 | diecimila_isp: isp 163 | 164 | ng: TARGET = ng 165 | ng: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>1' '-DNUM_LED_FLASHES=3' 166 | ng: AVR_FREQ = 16000000L 167 | ng: $(PROGRAM)_ng.hex 168 | 169 | ng_isp: ng 170 | ng_isp: TARGET = ng 171 | ng_isp: HFUSE = DD 172 | ng_isp: LFUSE = FF 173 | ng_isp: EFUSE = 00 174 | ng_isp: isp_uno 175 | 176 | atmega328: TARGET = atmega328 177 | atmega328: MCU_TARGET = atmega328p 178 | atmega328: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 179 | atmega328: AVR_FREQ = 16000000L 180 | atmega328: LDSECTION = --section-start=.text=0x7800 181 | atmega328: $(PROGRAM)_atmega328.hex 182 | 183 | atmega328_isp: atmega328 184 | atmega328_isp: TARGET = atmega328 185 | atmega328_isp: MCU_TARGET = atmega328p 186 | atmega328_isp: HFUSE = DA 187 | atmega328_isp: LFUSE = FF 188 | atmega328_isp: EFUSE = 05 189 | atmega328_isp: isp 190 | 191 | atmega328_pro8: TARGET = atmega328_pro_8MHz 192 | atmega328_pro8: MCU_TARGET = atmega328p 193 | atmega328_pro8: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>3' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -DDOUBLE_SPEED 194 | atmega328_pro8: AVR_FREQ = 8000000L 195 | atmega328_pro8: LDSECTION = --section-start=.text=0x7800 196 | atmega328_pro8: $(PROGRAM)_atmega328_pro_8MHz.hex $(PROGRAM)_atmega328_pro_8MHz.lst 197 | 198 | atmega328_pro8_isp: atmega328_pro8 199 | atmega328_pro8_isp: TARGET = atmega328_pro_8MHz 200 | atmega328_pro8_isp: MCU_TARGET = atmega328p 201 | atmega328_pro8_isp: HFUSE = D2 202 | atmega328_pro8_isp: LFUSE = FF 203 | atmega328_pro8_isp: EFUSE = 05 204 | atmega328_pro8_isp: isp 205 | 206 | mega: TARGET = atmega1280 207 | mega: MCU_TARGET = atmega1280 208 | mega: CFLAGS += '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=0' -DBAUD_RATE=57600 209 | mega: AVR_FREQ = 16000000L 210 | mega: LDSECTION = --section-start=.text=0x1F000 211 | mega: $(PROGRAM)_atmega1280.hex 212 | 213 | mega_isp: mega 214 | mega_isp: TARGET = atmega1280 215 | mega_isp: MCU_TARGET = atmega1280 216 | mega_isp: HFUSE = DA 217 | mega_isp: LFUSE = FF 218 | mega_isp: EFUSE = F5 219 | mega_isp: isp 220 | 221 | isp: $(TARGET) 222 | $(ISPFUSES) 223 | sleep 2 224 | $(ISPFLASH) 225 | sleep 2 226 | $(ISPEEPROM) 227 | 228 | isp-stk500: $(PROGRAM)_$(TARGET).hex 229 | $(STK500-1) 230 | $(STK500-2) 231 | 232 | %.elf: $(SRC) 233 | $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS) 234 | 235 | clean: 236 | rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex 237 | 238 | %.lst: %.elf 239 | $(OBJDUMP) -h -S $< > $@ 240 | 241 | %.hex: %.elf 242 | $(OBJCOPY) -j .text -j .data -O ihex $< $@ 243 | 244 | %.srec: %.elf 245 | $(OBJCOPY) -j .text -j .data -O srec $< $@ 246 | 247 | %.bin: %.elf 248 | $(OBJCOPY) -j .text -j .data -O binary $< $@ 249 | 250 | -------------------------------------------------------------------------------- /dual-bootloader/NameBoardSketch/NameBoardSketch.pde: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | void setup() { 5 | int i = 0; 6 | 7 | /* debug */ 8 | Serial.begin(9600); 9 | 10 | /* this is the name you give to the board */ 11 | char name[] = "BOX"; 12 | 13 | /* copy name to eeprom in the inverse */ 14 | /* order that is expected by the bootloader */ 15 | while (name[i] && i<8) { 16 | EEPROM.write(E2END - i, name[i]); 17 | i++; 18 | } 19 | 20 | /* mark end */ 21 | EEPROM.write(E2END - i, 0xFF); 22 | 23 | delay(2000); 24 | 25 | Serial.print("The board was given the name '"); 26 | Serial.print(name); 27 | Serial.print("'."); 28 | Serial.println(); 29 | } 30 | 31 | void loop() { 32 | /* do nothing */ 33 | } 34 | -------------------------------------------------------------------------------- /dual-bootloader/README: -------------------------------------------------------------------------------- 1 | # Code Originally from https://github.com/thseiler 2 | # 20110318 - D. Cuartielles for Arduino 3 | # modified files to compile for boards using the Arduino Ethernet Shield as the SD reader 4 | # 5 | # this works fine for the Arduino Diecimila with the dual booting, for doing the compilation on Linux, use 6 | # make clean; cp eeprom/EEPROM_firm.hex .; make diecimila; sudo make diecimila_isp 7 | # 8 | # also adds the keyword "BOX" at the end of the EEPROM for the bootloader to distinguish the name of the 9 | # new versions of the firmware 10 | # 11 | # TODO: make this work for boards with atmega328, also make sure it works with Arduino Uno boards 12 | # 13 | # ATTENTION!!! remember the step of copying the EEPROM file to the right folder 14 | 15 | 2boots by https://github.com/thseiler 16 | ------ 17 | 18 | This is a dual bootloader for Atmel AVR atmega chips. It combines 19 | a serial bootloader and a mmc/sd card based one in the same 2kb of flash 20 | memory that is normally used by the arduino serial loader alone. 21 | 22 | You might ask Why? Well, I have quite a few arduino "in the field". 23 | I can simply drag a .hex file to an SD card, insert it in an SD shield, 24 | and field-upgrade my boards without additional hardware. At the same time, 25 | I can connect the serial port and start developping with the normal Arduino 26 | IDE. 27 | 28 | Features: 29 | * Uses just 2kb of flash, so it fits into the normal boot block of most atmegas 30 | * Serial bootloader is arduino compatible (avrdude / stk500v1) 31 | * MMC bootloader can read directly a *.hex file 32 | * Supported are FAT16 formatted cards up to 1GB in size 33 | * All of ladyada's fixes to the original bootloader are included 34 | 35 | 36 | How to build 37 | ------------ 38 | simply install avr-gcc and lib-avr and run on of: 39 | 40 | (for atmega168:) 41 | # make lilypad (8Mhz) 42 | # make lilypad_resonator (8Mhz) 43 | # make pro8 (8Mhz) 44 | # make pro16 (16Mhz) 45 | # make pro20 (20Mhz) 46 | # make diecimila (16Mhz) 47 | # make ng (16Mhz) 48 | 49 | (for atmega328:) 50 | # make atmega328 (16Mhz) 51 | # make atmega328_pro8 (8Mhz) 52 | 53 | there is currently no support for atmega1280 54 | 55 | How to flash 56 | ------------ 57 | Connect your board to your ISP programmer of choice, 58 | Adapt the setting for avrdude in the Makefile (ISPTOOL, ISPPORT, ISPSPEED) 59 | and append '_isp' to your make command. 60 | 61 | I.E. 62 | 63 | # make atmega328 <= compile 64 | # make atmega328_isp <= flash 65 | 66 | 67 | How does the MMC/SD stuff work? 68 | ------------------------------- 69 | 70 | The SD bootloader is disabled by default. If you want to enable it, 71 | you will have to name your board. For this, simply load the included 72 | Sketch "NameBoardSketch.pde", change the name you want to assign to 73 | the board and the run the sketch. 74 | 75 | The Sketch simply writes that name to the end of the EEPROM. 76 | 77 | If the bootloader finds a name in the EERPOM, it will init the SPI hardware, 78 | search for an MMC / SD card and then look for a file that starts with 79 | board name, and ends in HEX. 80 | 81 | If your board is named "SAMPLE", then a file SAMPLE000.hex would work, as 82 | would SAMPLE001.hex etc... 83 | 84 | If no file was found, the bootloader will revert to the serial method. 85 | 86 | This allows you to have different firmware for different board on the same 87 | SD card. It also means that the bootloader will only use the SPI lines 88 | on boards that are named. 89 | 90 | Where can I find the .hex file in the Arduino IDE ? 91 | --------------------------------------------------- 92 | 93 | It used to be in the applet folder. This changed with arduino-0018 94 | Have a look at this thread: 95 | http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1268011960 96 | 97 | 98 | -------------------------------------------------------------------------------- /dual-bootloader/avrdude: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/ethernet-bootloader/176a7671e8a1a048072dd15ebb9ef343e71280a1/dual-bootloader/avrdude -------------------------------------------------------------------------------- /dual-bootloader/eeprom/EEPROM_firm.hex: -------------------------------------------------------------------------------- 1 | :20000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 2 | :20002000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 3 | :20004000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 4 | :20006000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0 5 | :20008000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80 6 | :2000A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60 7 | :2000C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40 8 | :2000E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20 9 | :20010000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 10 | :20012000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF 11 | :20014000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF 12 | :20016000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F 13 | :20018000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F 14 | :2001A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F 15 | :2001C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F 16 | :2001E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF584F4233 17 | :20020000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE 18 | :20022000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE 19 | :20024000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE 20 | :20026000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E 21 | :20028000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E 22 | :2002A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E 23 | :2002C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E 24 | :2002E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E 25 | :20030000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD 26 | :20032000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDD 27 | :20034000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD 28 | :20036000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D 29 | :20038000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D 30 | :2003A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D 31 | :2003C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3D 32 | :2003E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF554E4F015D398E 33 | :00000001FF 34 | -------------------------------------------------------------------------------- /dual-bootloader/firms/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/ethernet-bootloader/176a7671e8a1a048072dd15ebb9ef343e71280a1/dual-bootloader/firms/.DS_Store -------------------------------------------------------------------------------- /dual-bootloader/firms/BOX0168.hex: -------------------------------------------------------------------------------- 1 | :100000000C9461000C947E000C947E000C947E0095 2 | :100010000C947E000C947E000C947E000C947E0068 3 | :100020000C947E000C947E000C947E000C947E0058 4 | :100030000C947E000C947E000C947E000C947E0048 5 | :100040000C9428010C947E000C947E000C947E008D 6 | :100050000C947E000C947E000C947E000C947E0028 7 | :100060000C947E000C947E00000000002400270009 8 | :100070002A0000000000250028002B0000000000DE 9 | :1000800023002600290004040404040404040202DA 10 | :100090000202020203030303030301020408102007 11 | :1000A0004080010204081020010204081020000012 12 | :1000B0000007000201000003040600000000000029 13 | :1000C000000011241FBECFEFD4E0DEBFCDBF11E092 14 | :1000D000A0E0B1E0EAE1F4E002C005900D92A030AA 15 | :1000E000B107D9F711E0A0E0B1E001C01D92A9303D 16 | :1000F000B107E1F70E9404020C940B020C9400007B 17 | :100100008DE061E00E94D40068EC70E080E090E057 18 | :100110000E9470018DE060E00E94D40068EC70E005 19 | :1001200080E090E00E9470018DE061E00E94D400C8 20 | :1001300068EC70E080E090E00E9470018DE060E08B 21 | :100140000E94D40068EE73E080E090E00E947001AD 22 | :1001500008958DE061E00E94AE000895482F50E0C0 23 | :10016000CA0186569F4FFC0124914A575F4FFA01FE 24 | :1001700084918823C1F0E82FF0E0EE0FFF1FE859CB 25 | :10018000FF4FA591B491662341F49FB7F8948C91E9 26 | :10019000209582238C939FBF08959FB7F8948C91EC 27 | :1001A000822B8C939FBF0895482F50E0CA0182553F 28 | :1001B0009F4FFC012491CA0186569F4FFC01349148 29 | :1001C0004A575F4FFA019491992309F440C02223C2 30 | :1001D00031F1233021F4809180008F7705C02430E5 31 | :1001E00031F4809180008F7D8093800018C0213091 32 | :1001F00019F484B58F7704C0223021F484B58F7D43 33 | :1002000084BD0DC0263021F48091B0008F7705C0E9 34 | :10021000273029F48091B0008F7D8093B000E92FC2 35 | :10022000F0E0EE0FFF1FEE58FF4FA591B49166234B 36 | :1002300041F49FB7F8948C91309583238C939FBFA2 37 | :1002400008959FB7F8948C91832B8C939FBF08954A 38 | :100250001F920F920FB60F9211242F933F938F93FB 39 | :100260009F93AF93BF938091040190910501A0915A 40 | :100270000601B0910701309108010196A11DB11D41 41 | :10028000232F2D5F2D3720F02D570196A11DB11D75 42 | :10029000209308018093040190930501A093060127 43 | :1002A000B09307018091000190910101A09102019A 44 | :1002B000B09103010196A11DB11D8093000190939F 45 | :1002C0000101A0930201B0930301BF91AF919F91EF 46 | :1002D0008F913F912F910F900FBE0F901F90189507 47 | :1002E0009B01AC017FB7F8948091000190910101CE 48 | :1002F000A0910201B091030166B5A89B05C06F3FB4 49 | :1003000019F00196A11DB11D7FBFBA2FA92F982FFB 50 | :100310008827860F911DA11DB11D62E0880F991FCE 51 | :10032000AA1FBB1F6A95D1F7BC012DC0FFB7F89477 52 | :100330008091000190910101A0910201B09103010F 53 | :10034000E6B5A89B05C0EF3F19F00196A11DB11DB0 54 | :10035000FFBFBA2FA92F982F88278E0F911DA11D9F 55 | :10036000B11DE2E0880F991FAA1FBB1FEA95D1F7C4 56 | :10037000861B970B885E9340C8F221503040404066 57 | :10038000504068517C4F211531054105510571F6EA 58 | :100390000895789484B5826084BD84B5816084BDFD 59 | :1003A00085B5826085BD85B5816085BDEEE6F0E0EE 60 | :1003B000808181608083E1E8F0E01082808182604A 61 | :1003C0008083808181608083E0E8F0E080818160CB 62 | :1003D0008083E1EBF0E0808184608083E0EBF0E0FB 63 | :1003E000808181608083EAE7F0E08081846080839F 64 | :1003F0008081826080838081816080838081806849 65 | :1004000080831092C10008950E94C9010E94A90032 66 | :0A0410000E948000FDCFF894FFCF9A 67 | :00000001FF 68 | -------------------------------------------------------------------------------- /dual-bootloader/firms/BOX01682.hex: -------------------------------------------------------------------------------- 1 | :100000000C9461000C947E000C947E000C947E0095 2 | :100010000C947E000C947E000C947E000C947E0068 3 | :100020000C947E000C947E000C947E000C947E0058 4 | :100030000C947E000C947E000C947E000C947E0048 5 | :100040000C9450010C947E000C947E000C947E0065 6 | :100050000C947E000C947E000C947E000C947E0028 7 | :100060000C947E000C947E00000000002400270009 8 | :100070002A0000000000250028002B0000000000DE 9 | :1000800023002600290004040404040404040202DA 10 | :100090000202020203030303030301020408102007 11 | :1000A0004080010204081020010204081020000012 12 | :1000B0000007000201000003040600000000000029 13 | :1000C000000011241FBECFEFD4E0DEBFCDBF11E092 14 | :1000D000A0E0B1E0EAE6F4E002C005900D92A030A5 15 | :1000E000B107D9F711E0A0E0B1E001C01D92A9303D 16 | :1000F000B107E1F70E942C020C9433020C9400002B 17 | :100100008DE061E00E94FC0068EC70E080E090E02F 18 | :100110000E9498018DE060E00E94FC0068EC70E0B5 19 | :1001200080E090E00E9498018DE061E00E94FC0078 20 | :1001300068EC70E080E090E00E9498018DE060E063 21 | :100140000E94FC0068EC70E080E090E00E94980162 22 | :100150008DE061E00E94FC0068EC70E080E090E0DF 23 | :100160000E9498018DE060E00E94FC0068EC70E065 24 | :1001700080E090E00E9498018DE061E00E94FC0028 25 | :1001800068EC70E080E090E00E9498018DE060E013 26 | :100190000E94FC0068EE73E080E090E00E9498010D 27 | :1001A00008958DE061E00E94D6000895482F50E048 28 | :1001B000CA0186569F4FFC0124914A575F4FFA01AE 29 | :1001C00084918823C1F0E82FF0E0EE0FFF1FE8597B 30 | :1001D000FF4FA591B491662341F49FB7F8948C9199 31 | :1001E000209582238C939FBF08959FB7F8948C919C 32 | :1001F000822B8C939FBF0895482F50E0CA018255EF 33 | :100200009F4FFC012491CA0186569F4FFC013491F7 34 | :100210004A575F4FFA019491992309F440C0222371 35 | :1002200031F1233021F4809180008F7705C0243094 36 | :1002300031F4809180008F7D8093800018C0213040 37 | :1002400019F484B58F7704C0223021F484B58F7DF2 38 | :1002500084BD0DC0263021F48091B0008F7705C099 39 | :10026000273029F48091B0008F7D8093B000E92F72 40 | :10027000F0E0EE0FFF1FEE58FF4FA591B4916623FB 41 | :1002800041F49FB7F8948C91309583238C939FBF52 42 | :1002900008959FB7F8948C91832B8C939FBF0895FA 43 | :1002A0001F920F920FB60F9211242F933F938F93AB 44 | :1002B0009F93AF93BF938091040190910501A0910A 45 | :1002C0000601B0910701309108010196A11DB11DF1 46 | :1002D000232F2D5F2D3720F02D570196A11DB11D25 47 | :1002E000209308018093040190930501A0930601D7 48 | :1002F000B09307018091000190910101A09102014A 49 | :10030000B09103010196A11DB11D8093000190934E 50 | :100310000101A0930201B0930301BF91AF919F919E 51 | :100320008F913F912F910F900FBE0F901F901895B6 52 | :100330009B01AC017FB7F89480910001909101017D 53 | :10034000A0910201B091030166B5A89B05C06F3F63 54 | :1003500019F00196A11DB11D7FBFBA2FA92F982FAB 55 | :100360008827860F911DA11DB11D62E0880F991F7E 56 | :10037000AA1FBB1F6A95D1F7BC012DC0FFB7F89427 57 | :100380008091000190910101A0910201B0910301BF 58 | :10039000E6B5A89B05C0EF3F19F00196A11DB11D60 59 | :1003A000FFBFBA2FA92F982F88278E0F911DA11D4F 60 | :1003B000B11DE2E0880F991FAA1FBB1FEA95D1F774 61 | :1003C000861B970B885E9340C8F221503040404016 62 | :1003D000504068517C4F211531054105510571F69A 63 | :1003E0000895789484B5826084BD84B5816084BDAD 64 | :1003F00085B5826085BD85B5816085BDEEE6F0E09E 65 | :10040000808181608083E1E8F0E0108280818260F9 66 | :100410008083808181608083E0E8F0E0808181607A 67 | :100420008083E1EBF0E0808184608083E0EBF0E0AA 68 | :10043000808181608083EAE7F0E08081846080834E 69 | :1004400080818260808380818160808380818068F8 70 | :1004500080831092C10008950E94F1010E94D10092 71 | :0A0460000E948000FDCFF894FFCF4A 72 | :00000001FF 73 | -------------------------------------------------------------------------------- /dual-bootloader/firms/BOX0328.hex: -------------------------------------------------------------------------------- 1 | :100000000C9461000C947E000C947E000C947E0095 2 | :100010000C947E000C947E000C947E000C947E0068 3 | :100020000C947E000C947E000C947E000C947E0058 4 | :100030000C947E000C947E000C947E000C947E0048 5 | :100040000C9414010C947E000C947E000C947E00A1 6 | :100050000C947E000C947E000C947E000C947E0028 7 | :100060000C947E000C947E00000000002400270009 8 | :100070002A0000000000250028002B0000000000DE 9 | :1000800023002600290004040404040404040202DA 10 | :100090000202020203030303030301020408102007 11 | :1000A0004080010204081020010204081020000012 12 | :1000B0000007000201000003040600000000000029 13 | :1000C000000011241FBECFEFD8E0DEBFCDBF11E08E 14 | :1000D000A0E0B1E0E2EFF3E002C005900D92A030A5 15 | :1000E000B107D9F711E0A0E0B1E001C01D92A9303D 16 | :1000F000B107E1F70E94F0010C94F7010C940000A5 17 | :100100008DE061E00E94C00068EC70E080E090E06B 18 | :100110000E945C018DE060E00E94C00068EC70E02D 19 | :1001200080E090E00E945C0108958DE061E00E9413 20 | :100130009A000895482F50E0CA0186569F4FFC014F 21 | :1001400024914A575F4FFA0184918823C1F0E82F28 22 | :10015000F0E0EE0FFF1FE859FF4FA591B491662321 23 | :1001600041F49FB7F8948C91209582238C939FBF84 24 | :1001700008959FB7F8948C91822B8C939FBF08951C 25 | :10018000482F50E0CA0182559F4FFC012491CA01BB 26 | :1001900086569F4FFC0134914A575F4FFA01949164 27 | :1001A000992309F440C0222331F1233021F48091B6 28 | :1001B00080008F7705C0243031F4809180008F7DDE 29 | :1001C0008093800018C0213019F484B58F7704C063 30 | :1001D000223021F484B58F7D84BD0DC0263021F4FA 31 | :1001E0008091B0008F7705C0273029F48091B0004E 32 | :1001F0008F7D8093B000E92FF0E0EE0FFF1FEE58E7 33 | :10020000FF4FA591B491662341F49FB7F8948C9168 34 | :10021000309583238C939FBF08959FB7F8948C915A 35 | :10022000832B8C939FBF08951F920F920FB60F924E 36 | :1002300011242F933F938F939F93AF93BF938091FC 37 | :10024000040190910501A0910601B0910701309140 38 | :1002500008010196A11DB11D232F2D5F2D3720F020 39 | :100260002D570196A11DB11D209308018093040113 40 | :1002700090930501A0930601B093070180910001BE 41 | :1002800090910101A0910201B09103010196A11D7D 42 | :10029000B11D8093000190930101A0930201B093DE 43 | :1002A0000301BF91AF919F918F913F912F910F903B 44 | :1002B0000FBE0F901F9018959B01AC017FB7F8946B 45 | :1002C0008091000190910101A0910201B091030180 46 | :1002D00066B5A89B05C06F3F19F00196A11DB11D21 47 | :1002E0007FBFBA2FA92F982F8827860F911DA11D98 48 | :1002F000B11D62E0880F991FAA1FBB1F6A95D1F735 49 | :10030000BC012DC0FFB7F8948091000190910101CC 50 | :10031000A0910201B0910301E6B5A89B05C0EF3F93 51 | :1003200019F00196A11DB11DFFBFBA2FA92F982F5B 52 | :1003300088278E0F911DA11DB11DE2E0880F991F26 53 | :10034000AA1FBB1FEA95D1F7861B970B885E9340C7 54 | :10035000C8F2215030404040504068517C4F211538 55 | :1003600031054105510571F60895789484B5826090 56 | :1003700084BD84B5816084BD85B5826085BD85B549 57 | :10038000816085BDEEE6F0E0808181608083E1E8F8 58 | :10039000F0E0108280818260808380818160808330 59 | :1003A000E0E8F0E0808181608083E1EBF0E0808133 60 | :1003B00084608083E0EBF0E0808181608083EAE705 61 | :1003C000F0E080818460808380818260808380818E 62 | :1003D000816080838081806880831092C10008954D 63 | :1003E0000E94B5010E9495000E948000FDCFF89404 64 | :0203F000FFCF3D 65 | :00000001FF 66 | -------------------------------------------------------------------------------- /dual-bootloader/firms/README.txt: -------------------------------------------------------------------------------- 1 | # 20110318 - D. Cuartielles for Arduino 2 | # make sure you are taking the right file for your case, since the wrong one will not be uploaded properly to your board 3 | -------------------------------------------------------------------------------- /dual-bootloader/mmc_fat.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/ethernet-bootloader/176a7671e8a1a048072dd15ebb9ef343e71280a1/dual-bootloader/mmc_fat.c -------------------------------------------------------------------------------- /dual-bootloader/mmc_fat.h: -------------------------------------------------------------------------------- 1 | /**********************************************************/ 2 | /* mmc_fat.h */ 3 | /* Copyright (c) 2010 by thomas seiler */ 4 | /* read a file from a FAT16 formatted MMC card */ 5 | /* Code taken from HolgerBootloader (public domain) */ 6 | /* from mikrokontroller.net and adapted for smaller size */ 7 | /* */ 8 | /* 20110318 - D. Cuartielles for Arduino */ 9 | /* modified files to compile for boards */ 10 | /* using the Arduino Ethernet Shield */ 11 | /* as the SD reader */ 12 | /* */ 13 | /* -------------------------------------------------------*/ 14 | /* */ 15 | /* This program is free software; you can redistribute it */ 16 | /* and/or modify it under the terms of the GNU General */ 17 | /* Public License as published by the Free Software */ 18 | /* Foundation; either version 2 of the License, or */ 19 | /* (at your option) any later version. */ 20 | /* */ 21 | /* This program is distributed in the hope that it will */ 22 | /* be useful, but WITHOUT ANY WARRANTY; without even the */ 23 | /* implied warranty of MERCHANTABILITY or FITNESS FOR A */ 24 | /* PARTICULAR PURPOSE. See the GNU General Public */ 25 | /* License for more details. */ 26 | /* */ 27 | /* You should have received a copy of the GNU General */ 28 | /* Public License along with this program; if not, write */ 29 | /* to the Free Software Foundation, Inc., */ 30 | /* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 31 | /* */ 32 | /* Licence can be viewed at */ 33 | /* http://www.fsf.org/licenses/gpl.txt */ 34 | /**********************************************************/ 35 | 36 | #ifndef _mmc_fat_h_ 37 | #define _mmc_fat_h_ 38 | 39 | #include 40 | 41 | /* This code has a rather big sector buffer of 512 bytes */ 42 | /* with this export, other code can use it, too */ 43 | extern uint8_t buff[512]; 44 | 45 | #if defined (__AVR_ATmega644__) 46 | #define SPCR SPCR0 47 | #define SPIE SPIE0 48 | #define SPE SPE0 49 | #define DORD DORD0 50 | #define MSTR MSTR0 51 | #define CPOL CPOL0 52 | #define CPHA CPHA0 53 | #define SPR1 SPR01 54 | #define SPR0 SPR00 55 | 56 | #define SPSR SPSR0 57 | #define SPIF SPIF0 58 | #define WCOL WCOL0 59 | #define SPI2X SPI2X0 60 | 61 | #define SPDR SPDR0 62 | #endif 63 | 64 | //Port & Pin definitions. Be sure to use a pin of the same port as SPI for CS (Chip Select) ! 65 | //Settings below are recommended for a MEGA16 66 | #define MMC_PORT PORTB 67 | #define MMC_DDR DDRB 68 | //XXX 69 | #define MMC_PORT_CS PORTD 70 | #define MMC_DDR_CS DDRD 71 | 72 | #define SPI_MISO PB4 //DataOut of MMC 73 | #define SPI_MOSI PB3 //DataIn of MMC 74 | #define SPI_CLK PB5 //Clock of MMC 75 | //XXX #define MMC_CS PB2 //ChipSelect of MMC 76 | #define MMC_CS PD4 //ChipSelect of MMC 77 | #define WIZ_CS PB2 //ChipSelect of Wiznet Chip 78 | 79 | //Clockrate while initialisation / reading / writing 80 | #define SPI_INIT_CLOCK 1< For hard disks: Value 0xF8 , DOS version 2.0 137 | uint16_t bsNrSeProFAT16; // 22-23 Number of sectors per FAT (9). 0 for FAT32. 138 | uint16_t bsSecPerTrk; // 24-25 Number of sectors per track (12) 139 | uint16_t bsNumHeads; // 26-27 Number of heads (2, for a double-sided diskette) 140 | uint32_t bsHiddSec; // 28-31 Number of hidden sectors (0) 141 | uint32_t bsTotSec32; // 32-35 Number of total sectors (in case the total was not given in bytes 19-20) 142 | union 143 | { 144 | struct 145 | { 146 | uint8_t bsLogDrvNr; // 36 Logical Drive Number (for use with INT 13, e.g. 0 or 0x80) 147 | uint8_t bsReserved; // 37 Reserved (Earlier: Current Head, the track containing the Boot Record) Used by Windows NT: bit 0: need disk check; bit 1: need surface scan 148 | uint8_t bsExtSign; // 38 Extended signature (0x29) Indicates that the three following fields are present. Windows NT recognizes either 0x28 or 0x29. 149 | uint32_t bsParSerNr; // 39-42 Serial number of partition 150 | }; 151 | 152 | struct 153 | { 154 | uint32_t SecPerFAT32; 155 | uint8_t reserved[3]; 156 | }; 157 | }; 158 | uint8_t bsVolLbl[11]; // 43-53 Volume label or "NO NAME " 159 | uint8_t bsFileSysType[8]; // 54-61 Filesystem type (E.g. "FAT12 ", "FAT16 ", "FAT ", or all zero.) 160 | uint8_t bsBootstrap[448]; // Bootstrap 161 | uint16_t bsSignature; // 510-511 Signature 55 aa 162 | } vbr_t; 163 | 164 | typedef struct 165 | { 166 | char name[11]; //8 chars filename 167 | uint8_t attr; //file attributes RSHA, Longname, Drive Label, Directory 168 | uint8_t reserved; 169 | uint8_t fcrttime; //Fine resolution creation time stamp, in tenths of a second 170 | uint32_t crttime; //Time of Creation 171 | uint16_t lactime; //Last Access Time 172 | uint16_t eaindex; //EA-Index (used by OS/2 and NT) in FAT12 and FAT16, high 2 ytes of first clusternumber in FAT32 173 | uint32_t lmodtime; //Last Modified Time 174 | uint16_t fstclust; //First cluster in FAT12 and FAT16, low 2 bytes of first clusternumber in FAT32 175 | uint32_t filesize; //File size 176 | } direntry_t; 177 | 178 | typedef struct 179 | { 180 | uint16_t fat_entry[256]; //0: Cluster unused, 1 - Clustercount: Next clusternum, 0xFFFF0 - 0xFFFF6: Reserved Cluster, 0xFFF7 dead Cluster, 0xFFF8 - 0xFFFF: EOF 181 | } fatsector_t; 182 | 183 | 184 | void mmc_updater(); 185 | 186 | 187 | 188 | #endif /* _mmc_fat_h_ */ 189 | -------------------------------------------------------------------------------- /dual-bootloader/prog_flash.c: -------------------------------------------------------------------------------- 1 | /**********************************************************/ 2 | /* prog_flash.c */ 3 | /* Copyright (c) 2010 by thomas seiler */ 4 | /* write to the internal flash of the uC */ 5 | /* */ 6 | /* -------------------------------------------------------*/ 7 | /* */ 8 | /* This program is free software; you can redistribute it */ 9 | /* and/or modify it under the terms of the GNU General */ 10 | /* Public License as published by the Free Software */ 11 | /* Foundation; either version 2 of the License, or */ 12 | /* (at your option) any later version. */ 13 | /* */ 14 | /* This program is distributed in the hope that it will */ 15 | /* be useful, but WITHOUT ANY WARRANTY; without even the */ 16 | /* implied warranty of MERCHANTABILITY or FITNESS FOR A */ 17 | /* PARTICULAR PURPOSE. See the GNU General Public */ 18 | /* License for more details. */ 19 | /* */ 20 | /* You should have received a copy of the GNU General */ 21 | /* Public License along with this program; if not, write */ 22 | /* to the Free Software Foundation, Inc., */ 23 | /* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 24 | /* */ 25 | /* Licence can be viewed at */ 26 | /* http://www.fsf.org/licenses/gpl.txt */ 27 | /**********************************************************/ 28 | 29 | #include "prog_flash.h" 30 | #include 31 | 32 | /* page buffer ---------------------------------------------------- */ 33 | uint8_t pagebuffer[SPM_PAGESIZE]; 34 | 35 | 36 | /* address buffer */ 37 | uint16_t address; 38 | 39 | /* access to flash memory------------------------------------------ */ 40 | 41 | void write_flash_page() 42 | { 43 | uint16_t i = 0; 44 | 45 | eeprom_busy_wait (); 46 | 47 | boot_page_erase (address); 48 | boot_spm_busy_wait (); // Wait until the memory is erased. 49 | 50 | for (i=0; i /* for SPM_PAGESIZE */ 33 | #include 34 | 35 | extern uint8_t pagebuffer[SPM_PAGESIZE]; 36 | void write_flash_page(); 37 | 38 | extern uint16_t address; 39 | 40 | #endif -------------------------------------------------------------------------------- /dual-bootloader/stk500v1.c: -------------------------------------------------------------------------------- 1 | /**********************************************************/ 2 | /* stk500v1.c */ 3 | /* Copyright (c) 2010 by thomas seiler */ 4 | /* Implementation of the AVR STK500v1 protocol */ 5 | /* Inspired by the original Arduino Bootloader code, */ 6 | /* But heavily rewritten for smaller code size */ 7 | /* */ 8 | /* -------------------------------------------------------*/ 9 | /* */ 10 | /* This program is free software; you can redistribute it */ 11 | /* and/or modify it under the terms of the GNU General */ 12 | /* Public License as published by the Free Software */ 13 | /* Foundation; either version 2 of the License, or */ 14 | /* (at your option) any later version. */ 15 | /* */ 16 | /* This program is distributed in the hope that it will */ 17 | /* be useful, but WITHOUT ANY WARRANTY; without even the */ 18 | /* implied warranty of MERCHANTABILITY or FITNESS FOR A */ 19 | /* PARTICULAR PURPOSE. See the GNU General Public */ 20 | /* License for more details. */ 21 | /* */ 22 | /* You should have received a copy of the GNU General */ 23 | /* Public License along with this program; if not, write */ 24 | /* to the Free Software Foundation, Inc., */ 25 | /* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 26 | /* */ 27 | /* Licence can be viewed at */ 28 | /* http://www.fsf.org/licenses/gpl.txt */ 29 | /**********************************************************/ 30 | 31 | #include 32 | #include "stk500v1.h" 33 | 34 | /* define this to loose a bit compatibility, but save a few bytes */ 35 | #define MINIMALISTIC 36 | 37 | /* set the default UART baud rate */ 38 | #ifndef BAUD_RATE 39 | #define BAUD_RATE 19200 40 | #endif 41 | 42 | /* for the SIGNATURE_X macros, and uart pins */ 43 | #include 44 | 45 | /* acces to the pagebuffer */ 46 | #include "prog_flash.h" 47 | 48 | /* we need to read/write the eeprom */ 49 | #if !defined(__AVR_ATmega168__) || !defined(__AVR_ATmega328P__) 50 | #include 51 | #endif 52 | 53 | /* we need to read the flash */ 54 | #include 55 | 56 | 57 | /* use the global pagebuffer as scratch pad */ 58 | 59 | /* some variables */ 60 | union length_union { 61 | uint16_t word; 62 | uint8_t byte[2]; 63 | } length; 64 | 65 | struct flags_struct { // changed from a packed struct to save some bytes 66 | uint8_t eeprom; 67 | uint8_t rampz; 68 | } flags; 69 | 70 | /* uart stuff --------------------------------------------*/ 71 | 72 | #ifdef __AVR_ATmega128__ 73 | static uint8_t bootuart = 0; 74 | #endif 75 | 76 | static inline void setup_uart() { 77 | 78 | /* initialize UART(s) depending on CPU defined */ 79 | 80 | #ifdef __AVR_ATmega128__ 81 | /* no bootuart was selected, default to uart 0 */ 82 | if(!bootuart) { 83 | bootuart = 1; 84 | } 85 | 86 | if(bootuart == 1) { 87 | UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); 88 | UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8; 89 | UCSR0A = 0x00; 90 | UCSR0C = 0x06; 91 | UCSR0B = _BV(TXEN0)|_BV(RXEN0); 92 | } 93 | if(bootuart == 2) { 94 | UBRR1L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); 95 | UBRR1H = (F_CPU/(BAUD_RATE*16L)-1) >> 8; 96 | UCSR1A = 0x00; 97 | UCSR1C = 0x06; 98 | UCSR1B = _BV(TXEN1)|_BV(RXEN1); 99 | } 100 | #elif defined __AVR_ATmega163__ 101 | UBRR = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); 102 | UBRRHI = (F_CPU/(BAUD_RATE*16L)-1) >> 8; 103 | UCSRA = 0x00; 104 | UCSRB = _BV(TXEN)|_BV(RXEN); 105 | #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) 106 | #ifdef DOUBLE_SPEED 107 | UCSR0A = (1<> 8; 110 | #else 111 | UBRR0L = (uint8_t)(F_CPU/(BAUD_RATE*16L)-1); 112 | UBRR0H = (F_CPU/(BAUD_RATE*16L)-1) >> 8; 113 | #endif 114 | 115 | UCSR0B = (1<>8; // set baud rate 126 | UBRRL = (((F_CPU/BAUD_RATE)/16)-1); 127 | UCSRB = (1<> 8; 133 | UCSRA = 0x00; 134 | UCSRC = 0x06; 135 | UCSRB = _BV(TXEN)|_BV(RXEN); 136 | #endif 137 | } 138 | 139 | static void putch(char ch) 140 | { 141 | /* send a byte to UART depending on CPU defined */ 142 | 143 | #ifdef __AVR_ATmega128__ 144 | if(bootuart == 1) { 145 | while (!(UCSR0A & _BV(UDRE0))); 146 | UDR0 = ch; 147 | } 148 | else if (bootuart == 2) { 149 | while (!(UCSR1A & _BV(UDRE1))); 150 | UDR1 = ch; 151 | } 152 | #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) 153 | while (!(UCSR0A & _BV(UDRE0))); 154 | UDR0 = ch; 155 | #else 156 | /* m8,16,32,169,8515,8535,163 */ 157 | while (!(UCSRA & _BV(UDRE))); 158 | UDR = ch; 159 | #endif 160 | } 161 | 162 | 163 | static char getch(void) 164 | { 165 | /* read a byte from UART depending on CPU defined */ 166 | 167 | #ifdef __AVR_ATmega128__ 168 | if(bootuart == 1) { 169 | while(!(UCSR0A & _BV(RXC0))); 170 | return UDR0; 171 | } 172 | else if(bootuart == 2) { 173 | while(!(UCSR1A & _BV(RXC1))); 174 | return UDR1; 175 | } 176 | return 0; 177 | #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) 178 | uint32_t count = 0; 179 | 180 | while(!(UCSR0A & _BV(RXC0))){ 181 | /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ 182 | /* HACKME:: here is a good place to count times*/ 183 | count++; 184 | if (count > MAX_TIME_COUNT) { 185 | WDTCSR = _BV(WDE); 186 | while (1); // 16 ms 187 | } 188 | } 189 | 190 | return UDR0; 191 | #else 192 | /* m8,16,32,169,8515,8535,163 */ 193 | uint32_t count = 0; 194 | while(!(UCSRA & _BV(RXC))){ 195 | /* 20060803 DojoCorp:: Addon coming from the previous Bootloader*/ 196 | /* HACKME:: here is a good place to count times*/ 197 | count++; 198 | if (count > MAX_TIME_COUNT) { 199 | WDTCSR = _BV(WDE); 200 | while (1); // 16 ms 201 | } 202 | } 203 | return UDR; 204 | #endif 205 | } 206 | 207 | 208 | /* handle the different commands ----------------------- */ 209 | 210 | #ifndef MINIMALISTIC 211 | static inline void handle_programmerID(void) { 212 | putch('A'); /* this is smaller than a string */ 213 | putch('V'); 214 | putch('R'); 215 | putch(' '); 216 | putch('I'); 217 | putch('S'); 218 | putch('P'); 219 | } 220 | #endif 221 | 222 | /* SW_MAJOR and MINOR needs to be updated from time to time to avoid warning message from AVR Studio */ 223 | /* never allow AVR Studio to do an update !!!! */ 224 | #define HW_VER 0x02 225 | #define SW_MAJOR 0x01 226 | #define SW_MINOR 0x10 227 | 228 | static inline void handle_programmerVER(void) { 229 | uint8_t ch = pagebuffer[0]; 230 | if(ch==0x80) putch(HW_VER); // Hardware version 231 | else if(ch==0x81) putch(SW_MAJOR); // Software major version 232 | else if(ch==0x82) putch(SW_MINOR); // Software minor version 233 | else if(ch==0x98) putch(0x03); // Unknown but seems to be required by avr studio 3.56 234 | else putch(0x00); // Covers various unnecessary responses we don't care about 235 | } 236 | 237 | static inline void handle_addr(void) { 238 | address = *((uint16_t*) &pagebuffer[0]); 239 | #ifdef __AVR_ATmega128__ 240 | if (address>0x7FFF) flags.rampz = 1; // No go with m256, FIXME 241 | else flags.rampz = 0; 242 | #endif 243 | address = address << 1; // address * 2 -> byte location 244 | } 245 | 246 | static inline void handle_spi() { 247 | if (pagebuffer[0] == 0x30) { 248 | if (pagebuffer[2] == 0) { 249 | putch(SIGNATURE_0); 250 | } else if (pagebuffer[2] == 1) { 251 | putch(SIGNATURE_1); 252 | } else { 253 | putch(SIGNATURE_2); 254 | } 255 | } else { 256 | putch(0x00); 257 | } 258 | } 259 | 260 | static inline void handle_sig() { 261 | putch(SIGNATURE_0); 262 | putch(SIGNATURE_1); 263 | putch(SIGNATURE_2); 264 | } 265 | 266 | static inline void handle_write() { 267 | uint8_t w; 268 | if (flags.eeprom) { //Write to EEPROM one byte at a time 269 | for(w=0;w"); 12 | System.exit(1); 13 | } 14 | int port = Integer.parseInt(args[0]); 15 | recv(port); 16 | } 17 | 18 | public static void recv(int port) { 19 | try { 20 | byte[] buf = new byte[256]; 21 | DatagramSocket socket = new DatagramSocket(port); 22 | DatagramPacket pack = new DatagramPacket(buf, buf.length); 23 | System.out.println("Listening on UDP port 5555."); 24 | System.out.println("Waiting for packets..."); 25 | socket.receive(pack); 26 | 27 | // display response 28 | String received = new String(pack.getData(), 0, pack.getLength()); 29 | System.out.println("Received: " + received); 30 | socket.close(); 31 | } catch (SocketException e) { 32 | e.printStackTrace(); 33 | } catch (IOException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /eth-bootloader/bootloader client/Send.java: -------------------------------------------------------------------------------- 1 | import java.io.IOException; 2 | import java.net.DatagramPacket; 3 | import java.net.DatagramSocket; 4 | import java.net.InetAddress; 5 | import java.net.SocketException; 6 | import java.net.UnknownHostException; 7 | 8 | public class Send { 9 | 10 | public static void main(String[] args) { 11 | if (args.length != 2) { 12 | System.out.println("Please specify send address and port"); 13 | System.out.println("Send "); 14 | System.exit(1); 15 | } 16 | try { 17 | InetAddress address = InetAddress.getByName(args[0]); 18 | int port = Integer.parseInt(args[1]); 19 | send(address, port); 20 | } catch (UnknownHostException e) { 21 | e.printStackTrace(); 22 | } 23 | } 24 | 25 | public static void send(InetAddress _addr, int _port) { 26 | 27 | try { 28 | byte[] magic = { 'a', 'r', 'd', 'u', 'i', 'n', 'o' }; 29 | DatagramPacket packet; 30 | packet = new DatagramPacket(magic, magic.length, _addr, _port); 31 | 32 | DatagramSocket socket = new DatagramSocket(); 33 | socket.send(packet); 34 | socket.close(); 35 | System.out.println("Packet sent."); 36 | } catch (SocketException e) { 37 | e.printStackTrace(); 38 | } catch (IOException e) { 39 | e.printStackTrace(); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /eth-bootloader/eboot.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 42; 7 | objects = { 8 | 9 | /* Begin PBXFileReference section */ 10 | 4079525E0CEA38CC00E202DC /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 11 | 4079525F0CEA38CC00E202DC /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; 12 | /* End PBXFileReference section */ 13 | 14 | /* Begin PBXGroup section */ 15 | 4079523B0CEA382200E202DC = { 16 | isa = PBXGroup; 17 | children = ( 18 | 4079525D0CEA38CC00E202DC /* firmware */, 19 | ); 20 | sourceTree = ""; 21 | }; 22 | 4079525D0CEA38CC00E202DC /* firmware */ = { 23 | isa = PBXGroup; 24 | children = ( 25 | 4079525F0CEA38CC00E202DC /* Makefile */, 26 | 4079525E0CEA38CC00E202DC /* main.c */, 27 | ); 28 | path = firmware; 29 | sourceTree = ""; 30 | }; 31 | /* End PBXGroup section */ 32 | 33 | /* Begin PBXLegacyTarget section */ 34 | 407952600CEA391500E202DC /* firmware */ = { 35 | isa = PBXLegacyTarget; 36 | buildArgumentsString = $ACTION; 37 | buildConfigurationList = 407952610CEA393300E202DC /* Build configuration list for PBXLegacyTarget "firmware" */; 38 | buildPhases = ( 39 | ); 40 | buildToolPath = /usr/bin/make; 41 | buildWorkingDirectory = firmware; 42 | dependencies = ( 43 | ); 44 | name = firmware; 45 | passBuildSettingsInEnvironment = 1; 46 | productName = "Build All"; 47 | }; 48 | /* End PBXLegacyTarget section */ 49 | 50 | /* Begin PBXProject section */ 51 | 4079523D0CEA382200E202DC /* Project object */ = { 52 | isa = PBXProject; 53 | buildConfigurationList = 4079523E0CEA382200E202DC /* Build configuration list for PBXProject "eboot" */; 54 | compatibilityVersion = "Xcode 2.4"; 55 | developmentRegion = English; 56 | hasScannedForEncodings = 0; 57 | knownRegions = ( 58 | English, 59 | Japanese, 60 | French, 61 | German, 62 | ); 63 | mainGroup = 4079523B0CEA382200E202DC; 64 | projectDirPath = ""; 65 | projectRoot = ""; 66 | targets = ( 67 | 407952600CEA391500E202DC /* firmware */, 68 | ); 69 | }; 70 | /* End PBXProject section */ 71 | 72 | /* Begin XCBuildConfiguration section */ 73 | 407952400CEA382200E202DC /* Release */ = { 74 | isa = XCBuildConfiguration; 75 | buildSettings = { 76 | COPY_PHASE_STRIP = YES; 77 | }; 78 | name = Release; 79 | }; 80 | 407952630CEA393300E202DC /* Release */ = { 81 | isa = XCBuildConfiguration; 82 | buildSettings = { 83 | PATH = "$(PATH):/usr/local/CrossPack-AVR/bin"; 84 | }; 85 | name = Release; 86 | }; 87 | /* End XCBuildConfiguration section */ 88 | 89 | /* Begin XCConfigurationList section */ 90 | 4079523E0CEA382200E202DC /* Build configuration list for PBXProject "eboot" */ = { 91 | isa = XCConfigurationList; 92 | buildConfigurations = ( 93 | 407952400CEA382200E202DC /* Release */, 94 | ); 95 | defaultConfigurationIsVisible = 0; 96 | defaultConfigurationName = Release; 97 | }; 98 | 407952610CEA393300E202DC /* Build configuration list for PBXLegacyTarget "firmware" */ = { 99 | isa = XCConfigurationList; 100 | buildConfigurations = ( 101 | 407952630CEA393300E202DC /* Release */, 102 | ); 103 | defaultConfigurationIsVisible = 0; 104 | defaultConfigurationName = Release; 105 | }; 106 | /* End XCConfigurationList section */ 107 | }; 108 | rootObject = 4079523D0CEA382200E202DC /* Project object */; 109 | } 110 | -------------------------------------------------------------------------------- /eth-bootloader/firmware/Makefile: -------------------------------------------------------------------------------- 1 | # Name: tftp.c 2 | # Author: Peter Knight, Tinker London 3 | # Copyright: 2010 Tinker London 4 | # License: All rights reserved. 5 | # Project: eboot 6 | # Function: tftp implementation and flasher 7 | # Version: 0.1 tftp / flashing functional 8 | 9 | # Important make targets: 10 | # install : flash bootloader using AVR ISP MkII 11 | # disasm : output disassembly of bootloader 12 | # test : flash bootloader, then upload an app over tftp 13 | # readback : read back flash contents to read.hex 14 | # testsequence: install bootloader, upload app and read back flash 15 | 16 | DEVICE = atmega328p 17 | CLOCK = 16000000 18 | PROGRAMMER = -c avrispmkII -P usb 19 | OBJECTS = main.o net.o tftp.o validate.o announce.o 20 | APPOBJECTS = app.o 21 | 22 | # 2Kword boot block 23 | FUSES = -U efuse:w:0x05:m -U hfuse:w:0xd8:m -U lfuse:w:0xff:m 24 | LDFLAGS = -Ttext=0x7000 25 | 26 | # 1Kword boot block 27 | #FUSES = -U efuse:w:0x05:m -U hfuse:w:0xda:m -U lfuse:w:0xff:m 28 | #LDFLAGS = -Ttext=0x7800 29 | 30 | # 512 word boot block 31 | #FUSES = -U efuse:w:0x05:m -U hfuse:w:0xdc:m -U lfuse:w:0xff:m 32 | #LDFLAGS = -Ttext=0x7C00 33 | 34 | # 256 word boot block 35 | #FUSES = -U efuse:w:0x05:m -U hfuse:w:0xde:m -U lfuse:w:0xff:m 36 | #LDFLAGS = -Ttext=0x7E00 37 | 38 | # Extended Fuse Byte: 39 | # 0x05 = 0 0 0 0 0 1 0 1 40 | # \---+---/ \-+-/ 41 | # | +------ BODLEVEL Brownout detect at 2.5 to 2.9V 42 | # +-------------- Unused 43 | # 44 | # High Fuse Byte: 45 | # 0xD8 = 1 1 0 1 1 0 0 0 <-- BOOTRST Reset to bootloader 46 | # ^ ^ ^ ^ ^ \+/ 47 | # | | | | | +------- BOOTSZ 2Kword bootloader, 0x3800-0x3FFF, reset at 0x3800 48 | # | | | | +---------- EESAVE EEPROM erased in chip erase 49 | # | | | +------------ WDTON Watchdog timer off 50 | # | | +-------------- SPIEN SPI programming enabled 51 | # | +---------------- DWEN DebugWIRE disabled 52 | # +------------------ RSTDISBL External Reset enabled 53 | # 54 | # Low Fuse Byte: 55 | # 0xFF = 1 1 1 1 1 1 1 1 56 | # | | \+/ \--+--/ 57 | # | | | +------- CKSEL Low power crystal, 16Kck delay 58 | # | | +------------- SUT 65ms delay 59 | # | +---------------- CKOUT No clock out 60 | # +------------------ CKDIV8 No divide by 8 prescaler 61 | 62 | AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE) 63 | 64 | # Compiler options to shrink bootloader size 65 | # 66 | CCOPT = -Os 67 | CCOPT += -mno-interrupts 68 | CCOPT += -mshort-calls 69 | CCOPT += -fno-inline-small-functions 70 | CCOPT += -fno-split-wide-types 71 | CCOPT += -Wl,--relax 72 | CCOPT += -nostartfiles 73 | 74 | # These optimisations have no effect, so turned off 75 | # 76 | #CCOPT += -mtiny-stack 77 | #CCOPT += -ffreestanding 78 | #CCOPT += -fpack-struct 79 | #CCOPT += -fno-jump-tables 80 | 81 | COMPILE = avr-gcc -Wall $(CCOPT) -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) 82 | OBJCOPY = avr-objcopy 83 | OBJDUMP = avr-objdump 84 | 85 | # symbolic targets: 86 | all: main.hex app.bin bigapp.bin settings.bin 87 | 88 | %.o: %.c 89 | $(COMPILE) -c $< -o $@ 90 | 91 | %.o: %.S 92 | $(COMPILE) -x assembler-with-cpp -c $< -o $@ 93 | # "-x assembler-with-cpp" should not be necessary since this is the default 94 | # file type for the .S (with capital S) extension. However, upper case 95 | # characters are not always preserved on Windows. To ensure WinAVR 96 | # compatibility define the file type manually. 97 | 98 | %.s: %.c 99 | $(COMPILE) -S $< -o $@ 100 | 101 | %.bin: %.elf 102 | rm -f $@ 103 | $(OBJCOPY) -j .text -j .data -O binary $< $@ 104 | 105 | %.hex: %.elf 106 | rm -f $@ 107 | $(OBJCOPY) -j .text -j .data -O ihex $< $@ 108 | 109 | # Programming targets - which are set up for an AVR ISP MkII USB programmer 110 | flash: main.hex 111 | $(AVRDUDE) -U flash:w:main.hex:i 112 | 113 | fuse: 114 | $(AVRDUDE) $(FUSES) 115 | 116 | # Xcode uses the Makefile targets "", "clean" and "install" 117 | install: flash fuse 118 | 119 | clean: 120 | rm -f *.hex *.elf *.bin 121 | 122 | # Bootloader 123 | # 124 | main.elf: $(OBJECTS) 125 | $(COMPILE) -o main.elf $(OBJECTS) $(LDFLAGS) 126 | 127 | # Small test app - fits in a single packet 128 | # 129 | app.elf: app.o 130 | $(COMPILE) -o app.elf app.o 131 | 132 | # Large test app - fills most of the flash 133 | # 134 | bigapp.elf: bigapp.o 135 | $(COMPILE) -o bigapp.elf bigapp.o 136 | 137 | # Change settings 138 | # 139 | settings.elf: settings.o 140 | $(COMPILE) -o settings.elf settings.o 141 | 142 | 143 | # Targets for code debugging and analysis: 144 | disasm: main.elf 145 | $(OBJDUMP) -d main.elf 146 | 147 | map: main.elf 148 | $(OBJDUMP) -h main.elf 149 | 150 | cpp: 151 | $(COMPILE) -E main.c 152 | 153 | test: install app.bin 154 | sleep 3 155 | echo "put app.bin\nquit\n" | tftp -e 192.168.1.250 156 | 157 | readback: 158 | $(AVRDUDE) -U flash:r:read.hex:i 159 | 160 | testsequence: clean test readback 161 | 162 | -------------------------------------------------------------------------------- /eth-bootloader/firmware/Readme.txt: -------------------------------------------------------------------------------- 1 | Name: Readme.txt 2 | Author: Peter Knight, Tinker.it! 3 | Copyright: 2010 Tinker.it! 4 | License: All rights reserved. 5 | Project: eboot 6 | Function: Project documentation 7 | Version: 0.1 tftp / flashing functional 8 | 9 | Ethernet bootloader for the ATmega328P / W5100 10 | 11 | Flashing bootloader: 12 | -------------------- 13 | Connect an AVR ISP MkII and "make install". 14 | 15 | Configuring your network: 16 | ------------------------- 17 | The bootloader default address is 192.168.1.250. 18 | Configure your computer network card to a static address of 192.168.1.1 with a subnet of 255.255.255.0. 19 | By default, the bootloader assumes an internet gateway is at address 192.168.1.1. 20 | 21 | Converting firmware to the right format: 22 | ---------------------------------------- 23 | The bootloader accepts raw binary images, starting at address 0x0000. 24 | These can be generated using avr-objcopy, part of WinAVR / AVR-GCC, using the "-O binary" option. 25 | Example: avr-objcopy -j .text -j .data -O binary app.elf app.bin 26 | 27 | Uploading firmware manually: 28 | ---------------------------- 29 | 1) Check the target board is powered, and connected to the computer ethernet. 30 | 2) Verify the computer network settings: Static IP of 192.168.1.1, Subnet of 255.255.255.0. 31 | 3) Push reset button to start the bootloader. The LED will blink rapidly. 32 | 4) In a console window: tftp -e 192.168.1.250 33 | 5) At the tftp> prompt: put app.bin (where app.bin is your application binary image) 34 | 6) The board will be reprogrammed. Type quit to exit tftp. 35 | 36 | Flash codes: 37 | ------------ 38 | Rapid blinking: Ethernet bootloader is running. 39 | Slow fading: Test application is running. 40 | 41 | 42 | Version history 43 | --------------- 44 | 0.1: First internal release. Supports uploads on tftp. 45 | 46 | -------------------------------------------------------------------------------- /eth-bootloader/firmware/Test list.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arduino/ethernet-bootloader/176a7671e8a1a048072dd15ebb9ef343e71280a1/eth-bootloader/firmware/Test list.txt -------------------------------------------------------------------------------- /eth-bootloader/firmware/announce.c: -------------------------------------------------------------------------------- 1 | /* Name: announce.c 2 | * Author: Peter Knight, Tinker London 3 | * Copyright: 2010 Tinker London 4 | * License: All rights reserved. 5 | * Project: eboot 6 | * Function: announcement (Network broadcast) 7 | * Version: 0.1 tftp / flashing functional 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "net.h" 15 | #include "w5100_reg.h" 16 | #include "tftp.h" 17 | #include "main.h" 18 | #include "validate.h" 19 | #include "debug.h" 20 | 21 | uint16_t readPointer; 22 | 23 | #define ANNOUNCE_PORT (5555) 24 | #define ANNOUNCE_DATA_SIZE 128 25 | 26 | char *hex="0123456789ABCDEF"; 27 | 28 | char bootloaderIdentString[] PROGMEM = "Ethernet 1.0"; 29 | #define bootloaderIdentStringLength (12) 30 | 31 | uint8_t readNextByte() { 32 | uint8_t returnValue; 33 | returnValue = readPointer++; 34 | if (readPointer == S2_RX_END) readPointer = S2_RX_START; 35 | return returnValue; 36 | } 37 | 38 | void announceReply() { 39 | uint8_t txBuffer[100]; 40 | uint8_t *txPtr; 41 | uint8_t packetLength = 0; 42 | uint16_t writePointer; 43 | uint8_t value; 44 | uint8_t i; 45 | 46 | writePointer = netReadWord(REG_S2_TX_WR0) + S2_TX_START; 47 | txPtr = txBuffer + 2; 48 | 49 | // Send IP address in hex 50 | // 51 | for (i=REG_SIPR0; i<=REG_SIPR3; i++) { 52 | value = netReadReg(i); 53 | *txPtr++ = hex[value>>4]; 54 | *txPtr++ = hex[value & 0xf]; 55 | } 56 | // 57 | // Tag on ident string 58 | // 59 | memcpy_P(txPtr,bootloaderIdentString,bootloaderIdentStringLength); 60 | packetLength = 8 + bootloaderIdentStringLength; 61 | 62 | // Write packet length at start of packet 63 | txBuffer[0] = 0; 64 | txBuffer[1] = packetLength; 65 | packetLength += 2; 66 | txPtr = txBuffer; 67 | while (packetLength--) { 68 | netWriteReg(writePointer++, *txPtr++); 69 | if (writePointer == S2_TX_END) writePointer = S2_TX_START; 70 | } 71 | netWriteWord(REG_S2_TX_WR0, writePointer - S2_TX_START); 72 | netWriteReg(REG_S2_CR,CR_SEND); 73 | while (netReadReg(REG_S2_CR)); 74 | } 75 | 76 | void announcePacket(uint16_t packetSize) { 77 | uint8_t buffer[ANNOUNCE_DATA_SIZE]; 78 | uint16_t packetLength; 79 | 80 | // Transfer entire packet to RAM 81 | uint8_t* bufPtr = buffer; 82 | uint16_t count; 83 | 84 | readPointer = netReadWord(REG_S2_RX_RD0) + S2_RX_START; 85 | 86 | // Read destination IP address 87 | for (count = 0; count<4; count++) { 88 | netWriteReg(REG_S2_DIPR0+count,readNextByte()); 89 | } 90 | 91 | // Read destination port - but ignore it and respond on 5555 anyway. 92 | readNextByte(); 93 | readNextByte(); 94 | netWriteWord(REG_S2_DPORT0, ANNOUNCE_PORT); 95 | 96 | // Read packet length 97 | packetLength = readNextByte() | (readNextByte()<<8); 98 | 99 | // Trim overlong packets 100 | if (packetLength > ANNOUNCE_DATA_SIZE) packetLength = ANNOUNCE_DATA_SIZE; 101 | for (count=packetLength; --count;) { 102 | *bufPtr++ = readNextByte(); 103 | } 104 | netWriteWord(REG_S2_RX_RD0,readPointer - S2_RX_START); // Write back new pointer 105 | netWriteWord(REG_S2_CR, CR_RECV); // Receive again 106 | 107 | // Dump packet 108 | bufPtr = buffer; 109 | 110 | // Parse packet 111 | if (memcmp(buffer,"arduino",7)==0) announceReply(); 112 | } 113 | 114 | void announceInit() { 115 | // Open socket 116 | do { 117 | netWriteWord(REG_S2_PORT0,ANNOUNCE_PORT); 118 | netWriteReg(REG_S2_MR,MR_UDP); 119 | netWriteReg(REG_S2_CR,CR_OPEN); 120 | if (netReadReg(REG_S2_SR) != SOCK_UDP) 121 | netWriteReg(REG_S2_CR,CR_CLOSE); 122 | } while (netReadReg(REG_S2_SR) != SOCK_UDP); 123 | } 124 | 125 | void announcePoll() { 126 | uint16_t packetSize = netReadWord(REG_S2_RX_RSR0); 127 | if (packetSize) { 128 | announcePacket(packetSize); 129 | netWriteReg(REG_S2_CR,CR_CLOSE); 130 | announceInit(); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /eth-bootloader/firmware/app.c: -------------------------------------------------------------------------------- 1 | /* Name: app.c 2 | * Author: Peter Knight, Tinker.it! 3 | * Copyright: 2010 Tinker.it! 4 | * License: All rights reserved. 5 | * Project: eboot 6 | * Function: Test app for bootloader 7 | * Version: 0.1 tftp / flashing functional 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | int main(void) { 14 | uint8_t a,b,c; 15 | DDRB = _BV(5); 16 | for(;;) { 17 | for (a=0; a<255; a++) { 18 | for (c=0; c<15; c++) { 19 | for (b=0; b<255; b++) { 20 | if (ab) PORTB |= _BV(5); 29 | else PORTB &= ~_BV(5); 30 | } 31 | } 32 | } 33 | } 34 | return 0; /* never reached */ 35 | } 36 | -------------------------------------------------------------------------------- /eth-bootloader/firmware/bigapp.c: -------------------------------------------------------------------------------- 1 | /* Name: bigapp.c 2 | * Author: Peter Knight, Tinker.it! 3 | * Copyright: 2010 Tinker.it! 4 | * License: All rights reserved. 5 | * Project: eboot 6 | * Function: Test big app for bootloader 7 | * Version: 0.1 tftp / flashing functional 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | prog_char dummy[28000] PROGMEM = {}; 15 | 16 | int main(void) { 17 | uint8_t a,b,c; 18 | DDRB = _BV(5); 19 | for(;;) { 20 | for (a=0; a<255; a++) { 21 | for (c=0; c<15; c++) { 22 | for (b=0; b<255; b++) { 23 | if (ab) PORTB |= _BV(5); 32 | else PORTB &= ~_BV(5); 33 | } 34 | } 35 | } 36 | } 37 | return 0; /* never reached */ 38 | } 39 | -------------------------------------------------------------------------------- /eth-bootloader/firmware/debug.c: -------------------------------------------------------------------------------- 1 | /* Name: debug.c 2 | * Author: Peter Knight, Tinker.it! 3 | * Copyright: 2010 Tinker.it! 4 | * License: All rights reserved. 5 | * Project: eboot 6 | * Function: Utility routines for bootloader debugging 7 | * Version: 0.1 tftp / flashing functional 8 | */ 9 | 10 | #include "debug.h" 11 | 12 | #ifdef DEBUG 13 | void debugInit() { 14 | UCSR0A = 0x22; 15 | UCSR0B = 0x08; 16 | //UCSR0C = 0x06; // = reset state 17 | UBRR0 = 16; // 115k2 baud 8N1 18 | DDRD = 0x92; 19 | } 20 | void trace(char* msg) { 21 | uint8_t c; 22 | while ((c = *msg++)) { 23 | UDR0 = c; 24 | while (!(UCSR0A & _BV(UDRE0))); 25 | } 26 | } 27 | void putchar(uint8_t c) { 28 | UDR0=c; 29 | while(!(UCSR0A & _BV(UDRE0))); 30 | } 31 | void puthex(uint8_t c) { 32 | c &= 0xf; 33 | if (c>9) c+=7; 34 | UDR0=c+'0'; 35 | while(!(UCSR0A & _BV(UDRE0))); 36 | } 37 | void tracenum(uint16_t num) { 38 | putchar('0'); 39 | putchar('x'); 40 | puthex(num>>12); 41 | puthex(num>>8); 42 | puthex(num>>4); 43 | puthex(num); 44 | } 45 | #else 46 | void debugInit() { 47 | ; 48 | } 49 | #endif 50 | -------------------------------------------------------------------------------- /eth-bootloader/firmware/debug.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //#define DEBUG 5 | 6 | #ifdef DEBUG 7 | #define TRACE(msg) trace(msg) 8 | void trace(char* msg); 9 | void puthex(uint8_t c); 10 | void tracenum(uint16_t num); 11 | #else 12 | #define TRACE(msg) 13 | #endif 14 | void debugInit(); 15 | -------------------------------------------------------------------------------- /eth-bootloader/firmware/main.c: -------------------------------------------------------------------------------- 1 | /* Name: main.c 2 | * Author: Peter Knight, Tinker.it! 3 | * Copyright: 2010 Tinker.it! 4 | * License: All rights reserved. 5 | * Project: eboot 6 | * Function: Bootloader core 7 | * Version: 0.1 tftp / flashing functional 8 | */ 9 | 10 | 11 | #include "main.h" 12 | #include "net.h" 13 | #include "tftp.h" 14 | #include 15 | //#include "debug.h" 16 | 17 | uint16_t lastTimer1; 18 | uint16_t tick = 0; 19 | 20 | #define TIMEOUT 3 21 | 22 | int main(void) __attribute__ ((naked)) __attribute__ ((section (".init9"))); 23 | 24 | 25 | // Function 26 | void (*app_start)(void) = 0x0000; 27 | 28 | void updateLed() { 29 | uint16_t nextTimer1 = TCNT1; 30 | if (nextTimer1 & 0x400) PORTB |= _BV(LED_PIN); 31 | else PORTB &= ~_BV(LED_PIN); 32 | if (nextTimer1 < lastTimer1) tick++; 33 | lastTimer1 = nextTimer1; 34 | } 35 | 36 | uint8_t timedOut() { 37 | // Never timeout if there is no code in Flash 38 | if (pgm_read_word(0x0000) == 0xFFFF) return 0; 39 | if (tick > TIMEOUT) return 1; 40 | return 0; 41 | } 42 | 43 | int main(void) { 44 | // cli(); 45 | // SP=RAMEND; // This is done by hardware reset 46 | // asm volatile ("clr __zero_reg__"); 47 | 48 | // Set up outputs to communicate with W5100 chip 49 | DDRB = _BV(SCK_PIN) | _BV(MOSI_PIN) | _BV(SS_PIN); 50 | PORTB = _BV(SCK_PIN) | _BV(MISO_PIN) | _BV(MOSI_PIN) | _BV(SS_PIN); 51 | 52 | // Set up Timer 1 as timekeeper for LED flashing 53 | TCCR1B = 0x05; 54 | SPSR = (1< 2 | #include 3 | #define LED_PIN 5 4 | 5 | void updateLed(); 6 | uint8_t timedOut(); -------------------------------------------------------------------------------- /eth-bootloader/firmware/net.c: -------------------------------------------------------------------------------- 1 | /* Name: net.c 2 | * Author: Peter Knight, Tinker.it! 3 | * Copyright: 2010 Tinker.it! 4 | * License: All rights reserved. 5 | * Project: eboot 6 | * Network and W5100 chip support 7 | * Version: 0.1 tftp / flashing functional 8 | */ 9 | 10 | 11 | #include "net.h" 12 | #include "main.h" 13 | //#include "debug.h" 14 | #include "neteeprom.h" 15 | 16 | #define REGISTER_BLOCK_SIZE 28 17 | 18 | uint8_t registerBuffer[REGISTER_BLOCK_SIZE] = { 19 | 0x80, // MR Mode - reset device 20 | 21 | // EEPROM block starts here 22 | 192,168,1,1, // GWR Gateway IP Address Register 23 | 255,255,255,0, // SUBR Subnet Mask Register 24 | 0x12,0x34,0x45,0x78,0x9A,0xBC, // SHAR Source Hardware Address Register 25 | 192,168,1,250, // SIPR Source IP Address Register 26 | // EEPROM block ends here 27 | 28 | 0,0, // Reserved locations 29 | 0, // IR Interrupt Register 30 | 0, // IMR Interrupt Mask Register 31 | 0x07,0xd0, // RTR Retry Time-value Register 32 | 0x80, // RCR Retry Count Register 33 | 0x55, // RMSR Rx Memory Size Register 34 | 0x55 // TMSR Tx Memory Size Register 35 | }; 36 | 37 | void netWriteReg(uint16_t address, uint8_t value) { 38 | SPCR = _BV(SPE) | _BV(MSTR); 39 | SS_LOW(); 40 | SPDR = SPI_WRITE; while(!(SPSR & _BV(SPIF))); 41 | SPDR = address >> 8; while(!(SPSR & _BV(SPIF))); 42 | SPDR = address & 0xff; while(!(SPSR & _BV(SPIF))); 43 | SPDR = value; while(!(SPSR & _BV(SPIF))); 44 | SS_HIGH(); 45 | SPCR = 0; 46 | } 47 | 48 | uint8_t netReadReg(uint16_t address) { 49 | uint8_t returnValue; 50 | SPCR = _BV(SPE) | _BV(MSTR); 51 | SS_LOW(); 52 | SPDR = SPI_READ; while(!(SPSR & _BV(SPIF))); 53 | SPDR = address >> 8; while(!(SPSR & _BV(SPIF))); 54 | SPDR = address & 0xff; while(!(SPSR & _BV(SPIF))); 55 | SPDR = 0; while(!(SPSR & _BV(SPIF))); 56 | SS_HIGH(); 57 | returnValue = SPDR; 58 | SPCR = 0; 59 | return returnValue; 60 | } 61 | uint16_t netReadWord(uint16_t address) { 62 | return (netReadReg(address++)<<8) | netReadReg(address); 63 | } 64 | void netWriteWord(uint16_t address, uint16_t value) { 65 | netWriteReg(address++, value >> 8); 66 | netWriteReg(address, value & 0xff); 67 | } 68 | 69 | void netInit() { 70 | // Set up SPI 71 | 72 | // Pull in altered presets if available 73 | if ( 74 | (eeprom_read_byte(EEPROM_SIG_1) == EEPROM_SIG_1_VALUE) 75 | && (eeprom_read_byte(EEPROM_SIG_2) == EEPROM_SIG_2_VALUE) 76 | ) { 77 | uint8_t i=0; 78 | //TRACE("Using EEPROM settings\n"); 79 | for (;i<18; i++) registerBuffer[i+1] = eeprom_read_byte(EEPROM_DATA+i); 80 | } else { 81 | //TRACE("Using 192.168.1.250\n"); 82 | ; 83 | } 84 | 85 | // Configure Wiznet chip 86 | uint8_t i=0; 87 | for (; i 2 | #include 3 | 4 | #define SCK_PIN 5 5 | #define MISO_PIN 4 6 | #define MOSI_PIN 3 7 | #define SS_PIN 2 8 | 9 | #define EEPROM_SIG_1 ((uint8_t*)0) 10 | #define EEPROM_SIG_2 ((uint8_t*)1) 11 | #define EEPROM_DATA ((uint8_t*)2) 12 | #define EEPROM_SIG_1_VALUE (0x55) 13 | #define EEPROM_SIG_2_VALUE (0xAA) 14 | 15 | void netWriteReg(uint16_t address, uint8_t value); 16 | uint8_t netReadReg(uint16_t address); 17 | uint16_t netReadWord(uint16_t address); 18 | void netWriteWord(uint16_t address, uint16_t value); 19 | 20 | void netInit(); 21 | 22 | #define SS_LOW() PORTB &= ~_BV(SS_PIN) 23 | #define SS_HIGH() PORTB |= _BV(SS_PIN) 24 | 25 | #define SPI_WRITE (0xF0) 26 | #define SPI_READ (0x0F) 27 | -------------------------------------------------------------------------------- /eth-bootloader/firmware/neteeprom.h: -------------------------------------------------------------------------------- 1 | #define EEPROM_SIG_1 ((uint8_t*)0) 2 | #define EEPROM_SIG_2 ((uint8_t*)1) 3 | #define EEPROM_DATA ((uint8_t*)2) 4 | #define EEPROM_GATEWAY ((uint8_t*)2) 5 | #define EEPROM_MAC ((uint8_t*)6) 6 | #define EEPROM_IP ((uint8_t*)12) 7 | 8 | #define EEPROM_SIG_1_VALUE (0x55) 9 | #define EEPROM_SIG_2_VALUE (0xAA) -------------------------------------------------------------------------------- /eth-bootloader/firmware/settings.c: -------------------------------------------------------------------------------- 1 | /* Name: settings.c 2 | * Author: Peter Knight, Tinker.it! 3 | * Copyright: 2010 Tinker.it! 4 | * License: All rights reserved. 5 | * Project: eboot 6 | * Function: Alter network EEPROM settings 7 | * Version: 0.1 tftp / flashing functional 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "neteeprom.h" 14 | 15 | /* Alter these to your network setting */ 16 | uint8_t ip_address[4] = {192, 168, 1, 250}; 17 | uint8_t gateway_address[4]= {192, 168, 1, 1}; 18 | uint8_t subnet_mask[4] = {255, 255, 255, 0}; 19 | 20 | uint8_t getRandom() { 21 | uint8_t result = 0; 22 | uint8_t i; 23 | for (i=8; i--;) { 24 | uint8_t bit = 0; 25 | uint8_t dummy; 26 | uint16_t j; 27 | ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); 28 | ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1); 29 | ADCSRB = 0; 30 | for (j=1000; i--;) { 31 | ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADPS2) | _BV(ADPS1); 32 | while(ADCSRA & _BV(ADSC)); 33 | bit ^= ADCL; 34 | dummy = ADCH; // ADC result is locked until ADCH is read 35 | } 36 | bit &= 1; 37 | result += result + bit; 38 | } 39 | return result; 40 | } 41 | 42 | int main(void) { 43 | uint8_t mac[6]; 44 | uint8_t i; 45 | 46 | // Deliberately corrupt network settings 47 | eeprom_write_byte(EEPROM_SIG_2,EEPROM_SIG_1_VALUE); 48 | 49 | // Write gateway 50 | for (i=0; i<4; i++) eeprom_write_byte(EEPROM_GATEWAY+i,gateway_address[i]); 51 | 52 | // Write a random MAC address 53 | for (i=0; i<6; i++) eeprom_write_byte(EEPROM_MAC+i,getRandom()); 54 | 55 | // Write IP address 56 | for (i=0; i<4; i++) eeprom_write_byte(EEPROM_IP+i,ip_address[i]); 57 | 58 | // Fix signature bytes 59 | eeprom_write_byte(EEPROM_SIG_1,EEPROM_SIG_1_VALUE); 60 | eeprom_write_byte(EEPROM_SIG_2,EEPROM_SIG_2_VALUE); 61 | 62 | // Stop 63 | while(1); 64 | } 65 | -------------------------------------------------------------------------------- /eth-bootloader/firmware/tftp.c: -------------------------------------------------------------------------------- 1 | /* Name: tftp.c 2 | * Author: Peter Knight, Tinker.it! 3 | * Copyright: 2010 Tinker.it! 4 | * License: All rights reserved. 5 | * Project: eboot 6 | * Function: tftp implementation and flasher 7 | * Version: 0.1 tftp / flashing functional 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #include "net.h" 14 | #include "w5100_reg.h" 15 | #include "tftp.h" 16 | #include "main.h" 17 | #include "validate.h" 18 | 19 | //#include "debug.h" 20 | 21 | 22 | 23 | // TFTP message types 24 | #define ERROR_UNKNOWN 0 25 | #define ERROR_INVALID 1 26 | #define ACK 2 27 | #define ERROR_FULL 3 28 | #define FINAL_ACK 4 // Like an ACK, but for the final data packet. 29 | #define INVALID_IMAGE 5 30 | 31 | #define TFTP_DATA_SIZE 512 32 | 33 | #define MAX_ADDR 0x7000 // For 328 with 1Kword bootloader 34 | 35 | #define TFTP_HEADER_SIZE 12 36 | #define TFTP_OPCODE_SIZE 2 37 | #define TFTP_BLOCKNO_SIZE 2 38 | #define TFTP_MAX_PAYLOAD 512 39 | #define TFTP_PACKET_MAX_SIZE ( TFTP_HEADER_SIZE + TFTP_OPCODE_SIZE + TFTP_BLOCKNO_SIZE + TFTP_MAX_PAYLOAD ) 40 | 41 | uint16_t lastPacket = 0; 42 | 43 | /* Opcode?: tftp operation is unsupported. The bootloader only supports 'put' */ 44 | #define TFTP_OPCODE_ERROR_LEN 12 45 | char tftp_opcode_error_packet[] PROGMEM = "\12" "\0\5" "\0\0" "Opcode?"; 46 | 47 | /* Full: Binary image file is larger than the available space. */ 48 | #define TFTP_FULL_ERROR_LEN 9 49 | char tftp_full_error_packet[] PROGMEM = "\x09" "\0\5" "\0\3" "Full"; 50 | 51 | /* General catch-all error for unknown errors */ 52 | #define TFTP_UNKNOWN_ERROR_LEN 10 53 | char tftp_unknown_error_packet[] PROGMEM = "\10" "\0\5" "\0\0" "Error"; 54 | 55 | /* Invalid image file: Doesn't look like a binary image file */ 56 | #define TFTP_INVALID_IMAGE 23 57 | char tftp_invalid_image_packet[] PROGMEM = "\23" "\0\5" "\0\0" "Invalid image file"; 58 | 59 | 60 | uint8_t processPacket(uint16_t packetSize) { 61 | uint8_t buffer[TFTP_PACKET_MAX_SIZE]; 62 | uint16_t readPointer; 63 | uint16_t writeAddr; 64 | 65 | // Transfer entire packet to RAM 66 | uint8_t* bufPtr = buffer; 67 | uint16_t count; 68 | 69 | //TRACE("Copying packet of length "); 70 | //tracenum(packetSize); 71 | //TRACE("\n"); 72 | 73 | readPointer = netReadWord(REG_S3_RX_RD0) + S3_RX_START; 74 | for (count=TFTP_PACKET_MAX_SIZE; count--;) { 75 | *bufPtr++ = netReadReg(readPointer++); 76 | if (readPointer == S3_RX_END) readPointer = S3_RX_START; 77 | } 78 | netWriteWord(REG_S3_RX_RD0,readPointer); // Write back new pointer 79 | 80 | // Dump packet 81 | bufPtr = buffer; 82 | for (count=TFTP_PACKET_MAX_SIZE; count--;) { 83 | uint16_t val = *bufPtr++; 84 | val |= (*bufPtr++) << 8; 85 | //tracenum(val); 86 | //TRACE(" "); 87 | } 88 | 89 | //TRACE("Setting return address\n"); 90 | 91 | // Set up return IP address and port 92 | uint8_t i; 93 | for (i=0; i<6; i++) netWriteReg(REG_S3_DIPR0+i,buffer[i]); 94 | 95 | // Parse packet 96 | uint16_t tftpDataLen = (buffer[6]<<8) + buffer[7]; 97 | uint16_t tftpOpcode = (buffer[8]<<8) + buffer[9]; 98 | uint16_t tftpBlock = (buffer[10]<<8) + buffer[11]; 99 | 100 | uint8_t returnCode = ERROR_UNKNOWN; 101 | uint16_t packetLength; 102 | switch (tftpOpcode) { 103 | case TFTP_OPCODE_RRQ: // Read request 104 | default: 105 | //tracenum(tftpOpcode); 106 | //TRACE("is invalid opcode\n"); 107 | // Invalid - return error 108 | returnCode = ERROR_INVALID; 109 | break; 110 | 111 | case TFTP_OPCODE_WRQ: // Write request 112 | //TRACE("Write request\n"); 113 | netWriteReg(REG_S3_CR,CR_RECV); 114 | netWriteReg(REG_S3_CR,CR_CLOSE); 115 | do { 116 | netWriteReg(REG_S3_MR,MR_UDP); 117 | netWriteReg(REG_S3_CR,CR_OPEN); 118 | netWriteWord(REG_S3_PORT0,(buffer[4]<<8) | ~buffer[5] ); // Generate a 'random' TID (RFC1350) 119 | if (netReadReg(REG_S3_SR) != SOCK_UDP) 120 | netWriteReg(REG_S3_CR,CR_CLOSE); 121 | } while (netReadReg(REG_S3_SR) != SOCK_UDP); 122 | //TRACE("Changed to port "); 123 | //tracenum((buffer[4]<<8) | (buffer[5]^0x55)); 124 | //TRACE("\n"); 125 | lastPacket = 0; 126 | returnCode = ACK; // Send back acknowledge for packet 0 127 | break; 128 | 129 | case TFTP_OPCODE_DATA: 130 | packetLength = tftpDataLen; 131 | lastPacket = tftpBlock; 132 | writeAddr = (tftpBlock-1) << 9; // Flash write address for this block 133 | //TRACE("Data for block "); 134 | //tracenum(lastPacket); 135 | //TRACE("\n"); 136 | 137 | 138 | if ((writeAddr+packetLength) > MAX_ADDR) { 139 | // Flash is full - abort with an error before a bootloader overwrite occurs 140 | // 141 | // Application is now corrupt, so do not hand over. 142 | // 143 | returnCode = ERROR_FULL; 144 | } else { 145 | //TRACE("Writing data from address "); 146 | //tracenum(writeAddr); 147 | //TRACE("\n"); 148 | 149 | uint8_t* pageBase = buffer + 12; // Start of block data 150 | uint16_t offset = 0; // Block offset 151 | 152 | // Round up packet length to a full flash sector size 153 | while (packetLength % SPM_PAGESIZE) packetLength++; 154 | 155 | if (writeAddr == 0) { 156 | // First sector - validate 157 | if (!validImage(pageBase)) { 158 | returnCode = INVALID_IMAGE; 159 | break; 160 | } 161 | } 162 | 163 | // Flash packets 164 | for (offset=0; offset < packetLength;) { 165 | uint16_t writeValue = (pageBase[offset]) | (pageBase[offset+1]<<8); 166 | boot_page_fill(writeAddr+offset,writeValue); 167 | offset+=2; 168 | if (offset % SPM_PAGESIZE == 0) { 169 | boot_page_erase(writeAddr + offset - SPM_PAGESIZE); 170 | boot_spm_busy_wait(); 171 | boot_page_write(writeAddr + offset - SPM_PAGESIZE); 172 | boot_spm_busy_wait(); 173 | boot_rww_enable(); 174 | } 175 | } 176 | 177 | if (packetLength < TFTP_DATA_SIZE) { 178 | // Flash is complete 179 | // Hand over to application 180 | returnCode = FINAL_ACK; 181 | } else { 182 | returnCode = ACK; 183 | } 184 | } 185 | break; 186 | 187 | case TFTP_OPCODE_ACK: // Acknowledgement 188 | //TRACE("Ack\n"); 189 | break; 190 | 191 | case TFTP_OPCODE_ERROR: // Error signal 192 | //TRACE("Error\n"); 193 | break; 194 | 195 | } 196 | return returnCode; 197 | } 198 | 199 | void sendResponse(uint16_t response) { 200 | uint8_t txBuffer[100]; 201 | uint8_t *txPtr = txBuffer; 202 | uint8_t packetLength; 203 | uint16_t writePointer; 204 | writePointer = netReadWord(REG_S3_TX_WR0) + S3_TX_START; 205 | switch (response) { 206 | default: 207 | case ERROR_UNKNOWN: 208 | // Send unknown error packet 209 | packetLength = TFTP_UNKNOWN_ERROR_LEN; 210 | memcpy_P(txBuffer,tftp_unknown_error_packet,packetLength); 211 | break; 212 | 213 | case ERROR_INVALID: 214 | // Send invalid opcode packet 215 | packetLength = TFTP_OPCODE_ERROR_LEN; 216 | memcpy_P(txBuffer,tftp_opcode_error_packet,packetLength); 217 | break; 218 | 219 | case ERROR_FULL: 220 | // Send unknown error packet 221 | packetLength = TFTP_FULL_ERROR_LEN; 222 | memcpy_P(txBuffer,tftp_full_error_packet,packetLength); 223 | break; 224 | 225 | case ACK: 226 | case FINAL_ACK: 227 | //TRACE("Send ACK "); 228 | //tracenum(lastPacket); 229 | //TRACE("\n"); 230 | packetLength = 4; 231 | *txPtr++ = TFTP_OPCODE_ACK >> 8; 232 | *txPtr++ = TFTP_OPCODE_ACK & 0xff; 233 | *txPtr++ = lastPacket >> 8; 234 | *txPtr = lastPacket & 0xff; 235 | break; 236 | } 237 | txPtr = txBuffer; 238 | while (packetLength--) { 239 | netWriteReg(writePointer++, *txPtr++); 240 | if (writePointer == S3_TX_END) writePointer = S3_TX_START; 241 | } 242 | netWriteWord(REG_S3_TX_WR0, writePointer - S3_TX_START); 243 | netWriteReg(REG_S3_CR,CR_SEND); 244 | while (netReadReg(REG_S3_CR)); 245 | } 246 | 247 | 248 | void tftpInit() { 249 | // Open socket 250 | do { 251 | netWriteWord(REG_S3_PORT0,TFTP_PORT); 252 | netWriteReg(REG_S3_MR,MR_UDP); 253 | netWriteReg(REG_S3_CR,CR_OPEN); 254 | if (netReadReg(REG_S3_SR) != SOCK_UDP) 255 | netWriteReg(REG_S3_CR,CR_CLOSE); 256 | } while (netReadReg(REG_S3_SR) != SOCK_UDP); 257 | } 258 | 259 | uint8_t tftpPoll() { 260 | uint8_t response = ACK; 261 | uint16_t packetSize = netReadWord(REG_S3_RX_RSR0); 262 | if (packetSize) { 263 | response = processPacket(packetSize); 264 | sendResponse(response); 265 | } 266 | if ((response == FINAL_ACK) || timedOut()) { 267 | netWriteReg(REG_S3_CR,CR_CLOSE); 268 | return 0; // Complete 269 | } 270 | return 1; // tftp continues 271 | } 272 | -------------------------------------------------------------------------------- /eth-bootloader/firmware/tftp.h: -------------------------------------------------------------------------------- 1 | // TFTP Opcode values from RFC 1350 2 | // 3 | #define TFTP_OPCODE_RRQ 1 4 | #define TFTP_OPCODE_WRQ 2 5 | #define TFTP_OPCODE_DATA 3 6 | #define TFTP_OPCODE_ACK 4 7 | #define TFTP_OPCODE_ERROR 5 8 | 9 | // TFTP Error codes from RFC 1350 10 | // 11 | #define TFTP_ERROR_UNDEF 0 12 | #define TFTP_ERROR_NOT_FOUND 1 13 | #define TFTP_ERROR_ACCESS 2 14 | #define TFTP_ERROR_FULL 3 15 | #define TFTP_ERROR_ILLEGAL_OP 4 16 | #define TFTP_ERROR_UNKNOWN_XFER 4 17 | #define TFTP_ERROR_EXISTS 6 18 | #define TFTP_ERROR_NO_SUCH_USER 7 19 | 20 | 21 | #define TFTP_PORT 69 22 | 23 | void tftpInit(); 24 | uint8_t tftpPoll(); 25 | -------------------------------------------------------------------------------- /eth-bootloader/firmware/validate.c: -------------------------------------------------------------------------------- 1 | /* Validate first sector is a genuine image */ 2 | #include 3 | 4 | uint8_t validImage(uint8_t *base) { 5 | /* Check that a jump table is present in the first flash sector */ 6 | uint8_t i; 7 | for (i=0; i<0x34; i+=4) { 8 | // For each vector, check it is of the form: 9 | // 0x0C 0x94 0xWX 0xYZ ; JMP 0xWXYZ 10 | // 11 | if (base[i] != 0x0C) return 0; 12 | if (base[i+1] != 0x94) return 0; 13 | } 14 | return 1; 15 | } 16 | -------------------------------------------------------------------------------- /eth-bootloader/firmware/validate.h: -------------------------------------------------------------------------------- 1 | uint8_t validImage(uint8_t *base); 2 | -------------------------------------------------------------------------------- /eth-bootloader/firmware/w5100_reg.h: -------------------------------------------------------------------------------- 1 | #define REG_MR 0x000 2 | #define REG_GAR0 0x001 3 | #define REG_GAR1 0x002 4 | #define REG_GAR2 0x003 5 | #define REG_GAR3 0x004 6 | #define REG_SUBR0 0x005 7 | #define REG_SUBR1 0x006 8 | #define REG_SUBR2 0x007 9 | #define REG_SUBR3 0x008 10 | #define REG_SHAR0 0x009 11 | #define REG_SHAR1 0x00A 12 | #define REG_SHAR2 0x00B 13 | #define REG_SHAR3 0x00C 14 | #define REG_SHAR4 0x00D 15 | #define REG_SHAR5 0x00E 16 | #define REG_SIPR0 0x00F 17 | #define REG_SIPR1 0x010 18 | #define REG_SIPR2 0x011 19 | #define REG_SIPR3 0x012 20 | #define REG_IR 0x015 21 | #define REG_IMR 0x016 22 | #define REG_RTR0 0x017 23 | #define REG_RTR1 0x018 24 | #define REG_RCR 0x019 25 | #define REG_RMSR 0x01A 26 | #define REG_TMSR 0x01B 27 | #define REG_PATR0 0x01C 28 | #define REG_PATR1 0x01D 29 | #define REG_PTIMER 0x028 30 | #define REG_PMAGIC 0x029 31 | #define REG_UIPR0 0x02A 32 | #define REG_UIPR1 0x02B 33 | #define REG_UIPR2 0x02C 34 | #define REG_UIPR3 0x02D 35 | #define REG_UPORT0 0x02E 36 | #define REG_UPORT1 0x02F 37 | 38 | #define REG_S0_MR 0x400 39 | #define REG_S0_CR 0x401 40 | #define REG_S0_IR 0x402 41 | #define REG_S0_SR 0x403 42 | #define REG_S0_PORT0 0x404 43 | #define REG_S0_PORT1 0x405 44 | #define REG_S0_DHAR0 0x406 45 | #define REG_S0_DHAR1 0x407 46 | #define REG_S0_DHAR2 0x408 47 | #define REG_S0_DHAR3 0x409 48 | #define REG_S0_DHAR4 0x40A 49 | #define REG_S0_DHAR5 0x40B 50 | #define REG_S0_DIPR0 0x40C 51 | #define REG_S0_DIPR1 0x40D 52 | #define REG_S0_DIPR2 0x40E 53 | #define REG_S0_DIPR3 0x40F 54 | #define REG_S0_DPORT0 0x410 55 | #define REG_S0_DPORT1 0x411 56 | #define REG_S0_MSSR0 0x412 57 | #define REG_S0_MSSR1 0x413 58 | #define REG_S0_PROTO 0x414 59 | #define REG_S0_TOS 0x415 60 | #define REG_S0_TTL 0x416 61 | #define REG_S0_TX_FSR0 0x420 62 | #define REG_S0_TX_FSR1 0x421 63 | #define REG_S0_TX_RD0 0x422 64 | #define REG_S0_TX_RD1 0x423 65 | #define REG_S0_TX_WR0 0x424 66 | #define REG_S0_TX_WR1 0x425 67 | #define REG_S0_RX_RSR0 0x426 68 | #define REG_S0_RX_RSR1 0x427 69 | #define REG_S0_RX_RD0 0x428 70 | #define REG_S0_RX_RD1 0x429 71 | 72 | #define REG_S1_MR 0x500 73 | #define REG_S1_CR 0x501 74 | #define REG_S1_IR 0x502 75 | #define REG_S1_SR 0x503 76 | #define REG_S1_PORT0 0x504 77 | #define REG_S1_PORT1 0x505 78 | #define REG_S1_DHAR0 0x506 79 | #define REG_S1_DHAR1 0x507 80 | #define REG_S1_DHAR2 0x508 81 | #define REG_S1_DHAR3 0x509 82 | #define REG_S1_DHAR4 0x50A 83 | #define REG_S1_DHAR5 0x50B 84 | #define REG_S1_DIPR0 0x50C 85 | #define REG_S1_DIPR1 0x50D 86 | #define REG_S1_DIPR2 0x50E 87 | #define REG_S1_DIPR3 0x50F 88 | #define REG_S1_DPORT0 0x510 89 | #define REG_S1_DPORT1 0x511 90 | #define REG_S1_MSSR0 0x512 91 | #define REG_S1_MSSR1 0x513 92 | #define REG_S1_PROTO 0x514 93 | #define REG_S1_TOS 0x515 94 | #define REG_S1_TTL 0x516 95 | #define REG_S1_TX_FSR0 0x520 96 | #define REG_S1_TX_FSR1 0x521 97 | #define REG_S1_TX_RD0 0x522 98 | #define REG_S1_TX_RD1 0x523 99 | #define REG_S1_TX_WR0 0x524 100 | #define REG_S1_TX_WR1 0x525 101 | #define REG_S1_RX_RSR0 0x526 102 | #define REG_S1_RX_RSR1 0x527 103 | #define REG_S1_RX_RD0 0x528 104 | #define REG_S1_RX_RD1 0x529 105 | 106 | #define REG_S2_MR 0x600 107 | #define REG_S2_CR 0x601 108 | #define REG_S2_IR 0x602 109 | #define REG_S2_SR 0x603 110 | #define REG_S2_PORT0 0x604 111 | #define REG_S2_PORT1 0x605 112 | #define REG_S2_DHAR0 0x606 113 | #define REG_S2_DHAR1 0x607 114 | #define REG_S2_DHAR2 0x608 115 | #define REG_S2_DHAR3 0x609 116 | #define REG_S2_DHAR4 0x60A 117 | #define REG_S2_DHAR5 0x60B 118 | #define REG_S2_DIPR0 0x60C 119 | #define REG_S2_DIPR1 0x60D 120 | #define REG_S2_DIPR2 0x60E 121 | #define REG_S2_DIPR3 0x60F 122 | #define REG_S2_DPORT0 0x610 123 | #define REG_S2_DPORT1 0x611 124 | #define REG_S2_MSSR0 0x612 125 | #define REG_S2_MSSR1 0x613 126 | #define REG_S2_PROTO 0x614 127 | #define REG_S2_TOS 0x615 128 | #define REG_S2_TTL 0x616 129 | #define REG_S2_TX_FSR0 0x620 130 | #define REG_S2_TX_FSR1 0x621 131 | #define REG_S2_TX_RD0 0x622 132 | #define REG_S2_TX_RD1 0x623 133 | #define REG_S2_TX_WR0 0x624 134 | #define REG_S2_TX_WR1 0x625 135 | #define REG_S2_RX_RSR0 0x626 136 | #define REG_S2_RX_RSR1 0x627 137 | #define REG_S2_RX_RD0 0x628 138 | #define REG_S2_RX_RD1 0x629 139 | 140 | #define REG_S3_MR 0x700 141 | #define REG_S3_CR 0x701 142 | #define REG_S3_IR 0x702 143 | #define REG_S3_SR 0x703 144 | #define REG_S3_PORT0 0x704 145 | #define REG_S3_PORT1 0x705 146 | #define REG_S3_DHAR0 0x706 147 | #define REG_S3_DHAR1 0x707 148 | #define REG_S3_DHAR2 0x708 149 | #define REG_S3_DHAR3 0x709 150 | #define REG_S3_DHAR4 0x70A 151 | #define REG_S3_DHAR5 0x70B 152 | #define REG_S3_DIPR0 0x70C 153 | #define REG_S3_DIPR1 0x70D 154 | #define REG_S3_DIPR2 0x70E 155 | #define REG_S3_DIPR3 0x70F 156 | #define REG_S3_DPORT0 0x710 157 | #define REG_S3_DPORT1 0x711 158 | #define REG_S3_MSSR0 0x712 159 | #define REG_S3_MSSR1 0x713 160 | #define REG_S3_PROTO 0x714 161 | #define REG_S3_TOS 0x715 162 | #define REG_S3_TTL 0x716 163 | #define REG_S3_TX_FSR0 0x720 164 | #define REG_S3_TX_FSR1 0x721 165 | #define REG_S3_TX_RD0 0x722 166 | #define REG_S3_TX_RD1 0x723 167 | #define REG_S3_TX_WR0 0x724 168 | #define REG_S3_TX_WR1 0x725 169 | #define REG_S3_RX_RSR0 0x726 170 | #define REG_S3_RX_RSR1 0x727 171 | #define REG_S3_RX_RD0 0x728 172 | #define REG_S3_RX_RD1 0x729 173 | 174 | #define S0_TX_START 0x4000 175 | #define S0_TX_END 0x4800 176 | #define S1_TX_START 0x4800 177 | #define S1_TX_END 0x5000 178 | #define S2_TX_START 0x5000 179 | #define S2_TX_END 0x5800 180 | #define S3_TX_START 0x5800 181 | #define S3_TX_END 0x6000 182 | #define S0_RX_START 0x6000 183 | #define S0_RX_END 0x6800 184 | #define S1_RX_START 0x6800 185 | #define S1_RX_END 0x7000 186 | #define S2_RX_START 0x7000 187 | #define S2_RX_END 0x7800 188 | #define S3_RX_START 0x7800 189 | #define S3_RX_END 0x8000 190 | 191 | 192 | #define MR_CLOSED 0x00 193 | #define MR_TCP 0x01 194 | #define MR_UDP 0x02 195 | #define MR_IPRAW 0x03 196 | #define MR_MACRAW 0x04 197 | #define MR_PPPOE 0x05 198 | 199 | #define CR_OPEN 0x01 200 | #define CR_LISTEN 0x02 201 | #define CR_CONNECT 0x04 202 | #define CR_DISCON 0x08 203 | #define CR_CLOSE 0x10 204 | #define CR_SEND 0x20 205 | #define CR_SEND_MAC 0x21 206 | #define CR_SEND_KEEP 0x22 207 | #define CR_RECV 0x40 208 | 209 | #define SOCK_CLOSED 0x00 210 | #define SOCK_ARP1 0x11 211 | #define SOCK_INIT 0x13 212 | #define SOCK_LISTEN 0x14 213 | #define SOCK_SYNSENT 0x15 214 | #define SOCK_SYNRECV 0x16 215 | #define SOCK_ESTABLISHED 0x17 216 | #define SOCK_FIN_WAIT 0x18 217 | #define SOCK_CLOSING 0x1A 218 | #define SOCK_TIME_WAIT 0x1B 219 | #define SOCK_CLOSE_WAIT 0x1C 220 | #define SOCK_LAST_ACK 0x1D 221 | #define SOCK_ARP2 0x21 222 | #define SOCK_UDP 0x22 223 | #define SOCK_ARP3 0x31 224 | #define SOCK_IPRAW 0x32 225 | #define SOCK_MACRAW 0x42 226 | #define SOCK_PPPOE 0x5F 227 | --------------------------------------------------------------------------------