diff --git a/mendel/Makefile b/mendel/Makefile index 3808d03..3fcf90c 100644 --- a/mendel/Makefile +++ b/mendel/Makefile @@ -36,8 +36,8 @@ CC = $(ARCH)gcc OBJDUMP = $(ARCH)objdump OBJCOPY = $(ARCH)objcopy -OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once -DDEBUG=1 -# OPTIMIZE = -O0 +# OPTIMIZE = -Os -ffunction-sections -finline-functions-called-once -DDEBUG=1 +OPTIMIZE = -O0 CFLAGS = -g -Wall -Wstrict-prototypes $(OPTIMIZE) -mmcu=$(MCU_TARGET) -DF_CPU=$(F_CPU) $(DEFS) -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -save-temps LDFLAGS = -Wl,--as-needed -Wl,--gc-sections @@ -72,6 +72,7 @@ clean: rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.al *.i *.s *~ size: $(PROGRAM).hex + @echo -n " SIZE " @objdump -h mendel.elf | perl -ne '/.(data|text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf "%d bytes (%d%% of %dkb)\n", $$a, $$a * 100 / 16384, 16 }' %.o: %.c diff --git a/mendel/copier.c b/mendel/copier.c new file mode 100644 index 0000000..c483389 --- /dev/null +++ b/mendel/copier.c @@ -0,0 +1,94 @@ +#include "copier.h" + +#include + +#include "arduino.h" +#include "timer.h" +#include "serial.h" + +uint32_t copier_xchange(uint32_t cmd) { + uint32_t r = 0, c = cmd; + uint8_t i = 0; + + for (i = 0; i < 32; i++) { + WRITE(COPIER_MOSI, c & 0x80000000); delay_us(5); + c <<= 1; + WRITE(COPIER_SCK, 1); delay_us(5); + r = (r << 1) | (READ(COPIER_MISO)?1:0); + WRITE(COPIER_SCK, 0); + } + + delay_us(5); + + return r; +} + +void init_chip(void); +void init_chip() { + do { + WRITE(COPIER_SCK, 0); + // power up + WRITE(COPIER_RESET, 1); + delay_ms(10); + WRITE(COPIER_RESET, 0); + delay_ms(10); + // hopefully enter programming mode + } while ((copier_xchange(CMD_PROGRAMMING_ENABLE) & (CMD_PROGRAMMING_ENABLE >> 8)) != (CMD_PROGRAMMING_ENABLE >> 8)); +} + +void copy() { + // initialise + WRITE(COPIER_RESET, 0); SET_OUTPUT(COPIER_RESET); + WRITE(COPIER_SCK, 0); SET_OUTPUT(COPIER_SCK); + WRITE(COPIER_MOSI, 0); SET_OUTPUT(COPIER_MOSI); + SET_INPUT(COPIER_MISO); WRITE(COPIER_MISO, 1); + + delay_ms(50); + + init_chip(); + + // verify device signature- should be same as current chip since we haven't the space for the functionality necessary to program anything else + if ((copier_xchange(CMD_READ_SIGNATURE | 0x00) & 0xFF) != SIGNATURE_0) + return; + if ((copier_xchange(CMD_READ_SIGNATURE | 0x01) & 0xFF) != SIGNATURE_1) + return; + if ((copier_xchange(CMD_READ_SIGNATURE | 0x02) & 0xFF) != SIGNATURE_2) + return; + + // erase chip + copier_xchange(CMD_CHIP_ERASE); + delay_ms(15); //minimum is 9.0ms + + // re-initialise + init_chip(); + + uint8_t f; + // copy fuses + // first low byte + SPMCSR |= MASK(BLBSET) | MASK(SELFPRGEN); + f = pgm_read_byte_near(0); + copier_xchange(CMD_WRITE_FUSE_BITS | f); + + // high byte + SPMCSR |= MASK(BLBSET) | MASK(SELFPRGEN); + f = pgm_read_byte_near(3); + copier_xchange(CMD_WRITE_FUSE_HIGH_BITS | f); + + // extended byte + SPMCSR |= MASK(BLBSET) | MASK(SELFPRGEN); + f = pgm_read_byte_near(2); + copier_xchange(CMD_WRITE_FUSE_EXTENDED_BITS | f); + + // start copying flash + uint16_t i; + for (i = 0; i < (FLASHEND / 2); i += (SPM_PAGESIZE / 2)) { + uint8_t j; + for (j = 0; j < (SPM_PAGESIZE / 2); j++) { + uint16_t w = pgm_read_word_near((i | j) << 1); + copier_xchange(CMD_LOAD_PROGMEM_LOW_BYTE | (j << 8) | (w & 0xFF)); + copier_xchange(CMD_LOAD_PROGMEM_HIGH_BYTE | (j << 8) | (w >> 8)); + } + copier_xchange(CMD_WRITE_PROGMEM_PAGE | ((i / (SPM_PAGESIZE / 2)) << 8)); + delay_ms(10); //minimum is 4.5ms + } +} diff --git a/mendel/copier.h b/mendel/copier.h new file mode 100644 index 0000000..5fde02b --- /dev/null +++ b/mendel/copier.h @@ -0,0 +1,45 @@ +#ifndef _COPIER_H +#define _COPIER_H + +// operation instructions +#define CMD_PROGRAMMING_ENABLE 0xAC530000 +#define CMD_CHIP_ERASE 0xAC800000 +#define CMD_POLL 0xF0000000 + +// load instructions +#define CMD_LOAD_EXTENDED_ADDRESS 0x4D000000 +#define CMD_LOAD_PROGMEM_HIGH_BYTE 0x48000000 +#define CMD_LOAD_PROGMEM_LOW_BYTE 0x40000000 +#define CMD_LOAD_EEPROM_PAGE 0xC1000000 + +// read instructions +#define CMD_READ_PROGMEM_HIGH_BYTE 0x28000000 +#define CMD_READ_PROGMEM_LOW_BYTE 0x20000000 +#define CMD_READ_EEPROM 0xA0000000 +#define CMD_READ_LOCK_BITS 0x58000000 +#define CMD_READ_SIGNATURE 0x30000000 +#define CMD_READ_FUSE_BITS 0x50000000 +#define CMD_READ_FUSE_HIGH_BITS 0x58080000 +#define CMD_READ_FUSE_EXTENDED_BITS 0x50080000 +#define CMD_READ_CALIBRATION_BYTE 0x38000000 + +// write instructions +#define CMD_WRITE_PROGMEM_PAGE 0x4C000000 +#define CMD_WRITE_EEPROM 0xC0000000 +#define CMD_WRITE_EEPROM_PAGE 0xC2000000 +#define CMD_WRITE_LOCK_BITS 0xACE00000 +#define CMD_WRITE_FUSE_BITS 0xACA00000 +#define CMD_WRITE_FUSE_HIGH_BITS 0xACA80000 +#define CMD_WRITE_FUSE_EXTENDED_BITS 0xACA40000 + +//pinout +#define COPIER_RESET AIO1 +#define COPIER_SCK AIO2 +#define COPIER_MOSI AIO3 +#define COPIER_MISO AIO4 + +//functions + +void copy(void); + +#endif /* _COPIER_H */