Redo fespi flash algorithm (#384)
* WIP, rewrite of flash algorithm. Just put all the flashing logic into the algorithm, instead of using an intermediate format. This should reduce total data written while flashing by about 9%, and also makes the code much simpler. Change-Id: I807e60c8ab4f9f376cceaecdbbd10a2326be1c79 * New algorithm works. Speeds up Arty flashing another 9%. wrote 2228224 bytes from file /media/sf_tnewsome/SiFive/arty_images/arty.E21TraceFPGAEvaluationConfig.mcs in 86.784538s (25.074 KiB/s) verified 2192012 bytes in 6.693336s (319.816 KiB/s) 8.66user 13.03system 1:33.91elapsed 23%CPU (0avgtext+0avgdata 12272maxresident)k Change-Id: Ie55c5250d667251be141cb32b144bbcf3713fce4 * Fix whitespace. Change-Id: I338d518fa11a108efb530ffe75a2030619457a0b * Don't reserve so much stack space. Also properly check XLEN in riscv_wrapper.S. Change-Id: Ifa0301f3ea80f648fb8a6d6b6c8bf39f386fe4a6debug-log-reg-failure
parent
8f2d2c27e8
commit
c5dee66a71
|
@ -2,27 +2,49 @@ BIN2C = ../../../../src/helper/bin2char.sh
|
||||||
|
|
||||||
CROSS_COMPILE ?= riscv64-unknown-elf-
|
CROSS_COMPILE ?= riscv64-unknown-elf-
|
||||||
|
|
||||||
CC=$(CROSS_COMPILE)gcc
|
RISCV_CC=$(CROSS_COMPILE)gcc
|
||||||
OBJCOPY=$(CROSS_COMPILE)objcopy
|
RISCV_OBJCOPY=$(CROSS_COMPILE)objcopy
|
||||||
OBJDUMP=$(CROSS_COMPILE)objdump
|
RISCV_OBJDUMP=$(CROSS_COMPILE)objdump
|
||||||
|
|
||||||
CFLAGS = -march=rv32i -mabi=ilp32 -x assembler-with-cpp -nostdlib -nostartfiles
|
RISCV32_CFLAGS = -march=rv32i -mabi=ilp32 -nostdlib -nostartfiles -Os -fPIC
|
||||||
|
RISCV64_CFLAGS = -march=rv64i -mabi=lp64 -nostdlib -nostartfiles -Os -fPIC
|
||||||
|
|
||||||
all: fespi.inc
|
all: riscv32_fespi.inc riscv64_fespi.inc
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
|
||||||
%.elf: %.S
|
# .c -> .o
|
||||||
$(CC) $(CFLAGS) $< -o $@
|
riscv32_%.o: riscv_%.c
|
||||||
|
$(RISCV_CC) -c $(RISCV32_CFLAGS) $^ -o $@
|
||||||
|
|
||||||
%.lst: %.elf
|
riscv64_%.o: riscv_%.c
|
||||||
$(OBJDUMP) -S $< > $@
|
$(RISCV_CC) -c $(RISCV64_CFLAGS) $< -o $@
|
||||||
|
|
||||||
|
# .S -> .o
|
||||||
|
riscv32_%.o: riscv_%.S
|
||||||
|
$(RISCV_CC) -c $(RISCV32_CFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
riscv64_%.o: riscv_%.S
|
||||||
|
$(RISCV_CC) -c $(RISCV64_CFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
# .o -> .elf
|
||||||
|
riscv32_%.elf: riscv32_%.o riscv32_wrapper.o
|
||||||
|
$(RISCV_CC) -T riscv.lds $(RISCV32_CFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
riscv64_%.elf: riscv64_%.o riscv64_wrapper.o
|
||||||
|
$(RISCV_CC) -T riscv.lds $(RISCV64_CFLAGS) $^ -o $@
|
||||||
|
|
||||||
|
# .elf -> .bin
|
||||||
%.bin: %.elf
|
%.bin: %.elf
|
||||||
$(OBJCOPY) -Obinary $< $@
|
$(RISCV_OBJCOPY) -Obinary $< $@
|
||||||
|
|
||||||
|
# .bin -> .inc
|
||||||
%.inc: %.bin
|
%.inc: %.bin
|
||||||
$(BIN2C) < $< > $@
|
$(BIN2C) < $< > $@
|
||||||
|
|
||||||
|
# utility
|
||||||
|
%.lst: %.elf
|
||||||
|
$(RISCV_OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-rm -f *.elf *.lst *.bin *.inc
|
-rm -f *.elf *.o *.lst *.bin *.inc
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
/* Autogenerated with ../../../../src/helper/bin2char.sh */
|
|
||||||
0x6f,0x00,0xc0,0x01,0x73,0x00,0x10,0x00,0x6f,0x00,0xc0,0x02,0x6f,0x00,0x00,0x05,
|
|
||||||
0x6f,0x00,0xc0,0x05,0x6f,0x00,0x00,0x07,0x6f,0x00,0x00,0x0a,0x83,0xc2,0x05,0x00,
|
|
||||||
0x93,0x85,0x15,0x00,0x17,0x03,0x00,0x00,0x13,0x03,0xc3,0xfd,0xb3,0x82,0x62,0x00,
|
|
||||||
0x67,0x80,0x02,0x00,0x03,0xc3,0x05,0x00,0x93,0x85,0x15,0x00,0x83,0x22,0x85,0x04,
|
|
||||||
0xe3,0xce,0x02,0xfe,0x83,0xc2,0x05,0x00,0x23,0x24,0x55,0x04,0x93,0x85,0x15,0x00,
|
|
||||||
0x13,0x03,0xf3,0xff,0xe3,0x44,0x60,0xfe,0x6f,0xf0,0x5f,0xfc,0x83,0x22,0x45,0x07,
|
|
||||||
0x93,0xf2,0x12,0x00,0xe3,0x8c,0x02,0xfe,0x6f,0xf0,0x5f,0xfb,0x83,0xc2,0x05,0x00,
|
|
||||||
0xb3,0x82,0xa2,0x00,0x03,0xc3,0x15,0x00,0x93,0x85,0x25,0x00,0x23,0xa0,0x62,0x00,
|
|
||||||
0x6f,0xf0,0xdf,0xf9,0x13,0x06,0x50,0x00,0xef,0x00,0x80,0x01,0x13,0x06,0x00,0x00,
|
|
||||||
0xef,0x00,0x00,0x01,0x93,0x72,0x16,0x00,0xe3,0x9a,0x02,0xfe,0x6f,0xf0,0x1f,0xf8,
|
|
||||||
0x83,0x22,0x85,0x04,0xe3,0xce,0x02,0xfe,0x23,0x24,0xc5,0x04,0x03,0x26,0xc5,0x04,
|
|
||||||
0xe3,0x4e,0x06,0xfe,0x67,0x80,0x00,0x00,0x83,0x22,0x05,0x04,0x13,0x03,0x70,0xff,
|
|
||||||
0xb3,0xf2,0x62,0x00,0x03,0xc3,0x05,0x00,0x93,0x85,0x15,0x00,0xb3,0xe2,0x62,0x00,
|
|
||||||
0x23,0x20,0x55,0x04,0x6f,0xf0,0x9f,0xf4,
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
OUTPUT_ARCH( "riscv" )
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x80000000;
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text.entry)
|
||||||
|
*(.text)
|
||||||
|
}
|
||||||
|
.data : { *(.data) }
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
/* Autogenerated with ../../../../src/helper/bin2char.sh */
|
||||||
|
0x17,0x01,0x00,0x00,0x03,0x21,0xc1,0x2a,0xef,0x00,0x00,0x10,0x73,0x00,0x10,0x00,
|
||||||
|
0x93,0x07,0x90,0x3e,0x93,0x87,0xf7,0xff,0x63,0x96,0x07,0x00,0x13,0x05,0x10,0x00,
|
||||||
|
0x67,0x80,0x00,0x00,0x03,0x27,0x45,0x07,0x13,0x77,0x17,0x00,0xe3,0x04,0x07,0xfe,
|
||||||
|
0x13,0x05,0x00,0x00,0x67,0x80,0x00,0x00,0x93,0x07,0x90,0x3e,0x93,0x87,0xf7,0xff,
|
||||||
|
0x63,0x96,0x07,0x00,0x13,0x05,0x10,0x00,0x67,0x80,0x00,0x00,0x03,0x27,0x85,0x04,
|
||||||
|
0xe3,0x46,0x07,0xfe,0x23,0x24,0xb5,0x04,0x13,0x05,0x00,0x00,0x67,0x80,0x00,0x00,
|
||||||
|
0x83,0x27,0x05,0x04,0x13,0x01,0x01,0xff,0x23,0x24,0x81,0x00,0x23,0x26,0x11,0x00,
|
||||||
|
0x23,0x22,0x91,0x00,0x93,0xf7,0x77,0xff,0x23,0x20,0xf5,0x04,0x93,0x07,0x20,0x00,
|
||||||
|
0x23,0x2c,0xf5,0x00,0x93,0x05,0x50,0x00,0x13,0x04,0x05,0x00,0xef,0xf0,0xdf,0xfa,
|
||||||
|
0x93,0x07,0x90,0x3e,0x93,0x87,0xf7,0xff,0x63,0x9e,0x07,0x00,0x13,0x05,0x10,0x00,
|
||||||
|
0x83,0x20,0xc1,0x00,0x03,0x24,0x81,0x00,0x83,0x24,0x41,0x00,0x13,0x01,0x01,0x01,
|
||||||
|
0x67,0x80,0x00,0x00,0x03,0x27,0xc4,0x04,0xe3,0x4e,0x07,0xfc,0x93,0x04,0x90,0x3e,
|
||||||
|
0x93,0x84,0xf4,0xff,0xe3,0x8c,0x04,0xfc,0x93,0x05,0x00,0x00,0x13,0x05,0x04,0x00,
|
||||||
|
0xef,0xf0,0x9f,0xf6,0x13,0x07,0x90,0x3e,0x13,0x07,0xf7,0xff,0xe3,0x00,0x07,0xfc,
|
||||||
|
0x83,0x27,0xc4,0x04,0xe3,0xca,0x07,0xfe,0x93,0xf7,0x17,0x00,0xe3,0x9a,0x07,0xfc,
|
||||||
|
0x23,0x2c,0x04,0x00,0x83,0x27,0x04,0x04,0x13,0x05,0x00,0x00,0x93,0xe7,0x87,0x00,
|
||||||
|
0x23,0x20,0xf4,0x04,0x6f,0xf0,0xdf,0xf9,0x13,0x01,0x01,0xfd,0x23,0x26,0x11,0x02,
|
||||||
|
0x23,0x24,0x81,0x02,0x23,0x22,0x91,0x02,0x13,0x04,0x05,0x00,0x23,0x20,0x21,0x03,
|
||||||
|
0x23,0x2e,0x31,0x01,0x23,0x2a,0x51,0x01,0x23,0x28,0x61,0x01,0x93,0x09,0x06,0x00,
|
||||||
|
0x13,0x8b,0x05,0x00,0x93,0x84,0x06,0x00,0x13,0x09,0x07,0x00,0x23,0x2c,0x41,0x01,
|
||||||
|
0x23,0x26,0x71,0x01,0x23,0x24,0x81,0x01,0xef,0xf0,0x9f,0xec,0x83,0x27,0x04,0x06,
|
||||||
|
0x13,0x05,0x04,0x00,0x93,0xf7,0xe7,0xff,0x23,0x20,0xf4,0x06,0xef,0xf0,0x5f,0xf0,
|
||||||
|
0x93,0x0a,0x05,0x00,0x63,0x1a,0x05,0x00,0x93,0x07,0xfb,0xff,0xb3,0xf7,0x97,0x00,
|
||||||
|
0x93,0x0b,0x20,0x00,0x63,0x12,0x09,0x04,0x83,0x27,0x04,0x06,0x83,0x20,0xc1,0x02,
|
||||||
|
0x13,0x85,0x0a,0x00,0x93,0xe7,0x17,0x00,0x23,0x20,0xf4,0x06,0x03,0x24,0x81,0x02,
|
||||||
|
0x83,0x24,0x41,0x02,0x03,0x29,0x01,0x02,0x83,0x29,0xc1,0x01,0x03,0x2a,0x81,0x01,
|
||||||
|
0x83,0x2a,0x41,0x01,0x03,0x2b,0x01,0x01,0x83,0x2b,0xc1,0x00,0x03,0x2c,0x81,0x00,
|
||||||
|
0x13,0x01,0x01,0x03,0x67,0x80,0x00,0x00,0x33,0x07,0xf9,0x00,0x13,0x0a,0x09,0x00,
|
||||||
|
0x63,0x74,0xeb,0x00,0x33,0x0a,0xfb,0x40,0x93,0x05,0x60,0x00,0x13,0x05,0x04,0x00,
|
||||||
|
0xef,0xf0,0x9f,0xe6,0x13,0x05,0x04,0x00,0xef,0xf0,0x9f,0xe3,0x93,0x05,0x20,0x00,
|
||||||
|
0x23,0x2c,0x74,0x01,0x13,0x05,0x04,0x00,0xef,0xf0,0x1f,0xe5,0x93,0xd5,0x04,0x01,
|
||||||
|
0x93,0xf5,0xf5,0x0f,0x13,0x05,0x04,0x00,0xef,0xf0,0x1f,0xe4,0x93,0xd5,0x84,0x00,
|
||||||
|
0x93,0xf5,0xf5,0x0f,0x13,0x05,0x04,0x00,0xef,0xf0,0x1f,0xe3,0x93,0xf5,0xf4,0x0f,
|
||||||
|
0x13,0x05,0x04,0x00,0xef,0xf0,0x5f,0xe2,0x33,0x8c,0x49,0x01,0x63,0x18,0x3c,0x03,
|
||||||
|
0x13,0x05,0x04,0x00,0xef,0xf0,0xdf,0xde,0x13,0x05,0x04,0x00,0x23,0x2c,0x04,0x00,
|
||||||
|
0xef,0xf0,0x1f,0xe3,0x63,0x16,0x05,0x02,0x93,0x09,0x0c,0x00,0xb3,0x84,0x44,0x01,
|
||||||
|
0x33,0x09,0x49,0x41,0x93,0x07,0x00,0x00,0x6f,0xf0,0xdf,0xf2,0x83,0xc5,0x09,0x00,
|
||||||
|
0x13,0x05,0x04,0x00,0x93,0x89,0x19,0x00,0xef,0xf0,0x1f,0xde,0x6f,0xf0,0x1f,0xfc,
|
||||||
|
0x93,0x0a,0x05,0x00,0x6f,0xf0,0x5f,0xf1,0x09,0x53,0x67,0x08,0x09,0x53,0x67,0x08,
|
||||||
|
0x09,0x53,0x67,0x08,0x09,0x53,0x67,0x08,0x09,0x53,0x67,0x08,0x09,0x53,0x67,0x08,
|
||||||
|
0x09,0x53,0x67,0x08,0x09,0x53,0x67,0x08,0x09,0x53,0x67,0x08,0x09,0x53,0x67,0x08,
|
||||||
|
0x09,0x53,0x67,0x08,0x09,0x53,0x67,0x08,0x09,0x53,0x67,0x08,0x09,0x53,0x67,0x08,
|
||||||
|
0x09,0x53,0x67,0x08,0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,0xa8,0x02,0x00,0x80,
|
||||||
|
0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
|
|
@ -0,0 +1,51 @@
|
||||||
|
/* Autogenerated with ../../../../src/helper/bin2char.sh */
|
||||||
|
0x17,0x01,0x00,0x00,0x03,0x31,0x81,0x30,0xef,0x00,0x80,0x10,0x73,0x00,0x10,0x00,
|
||||||
|
0x93,0x07,0x90,0x3e,0x9b,0x87,0xf7,0xff,0x63,0x96,0x07,0x00,0x13,0x05,0x10,0x00,
|
||||||
|
0x67,0x80,0x00,0x00,0x03,0x27,0x45,0x07,0x13,0x77,0x17,0x00,0xe3,0x04,0x07,0xfe,
|
||||||
|
0x13,0x05,0x00,0x00,0x67,0x80,0x00,0x00,0x93,0x07,0x90,0x3e,0x9b,0x87,0xf7,0xff,
|
||||||
|
0x63,0x96,0x07,0x00,0x13,0x05,0x10,0x00,0x67,0x80,0x00,0x00,0x03,0x27,0x85,0x04,
|
||||||
|
0xe3,0x46,0x07,0xfe,0x9b,0x85,0x05,0x00,0x23,0x24,0xb5,0x04,0x13,0x05,0x00,0x00,
|
||||||
|
0x67,0x80,0x00,0x00,0x83,0x27,0x05,0x04,0x13,0x01,0x01,0xfe,0x23,0x38,0x81,0x00,
|
||||||
|
0x23,0x3c,0x11,0x00,0x23,0x34,0x91,0x00,0x93,0xf7,0x77,0xff,0x23,0x20,0xf5,0x04,
|
||||||
|
0x93,0x07,0x20,0x00,0x23,0x2c,0xf5,0x00,0x93,0x05,0x50,0x00,0x13,0x04,0x05,0x00,
|
||||||
|
0xef,0xf0,0x9f,0xfa,0x93,0x07,0x90,0x3e,0x9b,0x87,0xf7,0xff,0x63,0x9e,0x07,0x00,
|
||||||
|
0x13,0x05,0x10,0x00,0x83,0x30,0x81,0x01,0x03,0x34,0x01,0x01,0x83,0x34,0x81,0x00,
|
||||||
|
0x13,0x01,0x01,0x02,0x67,0x80,0x00,0x00,0x03,0x27,0xc4,0x04,0xe3,0x4e,0x07,0xfc,
|
||||||
|
0x93,0x04,0x90,0x3e,0x9b,0x84,0xf4,0xff,0xe3,0x8c,0x04,0xfc,0x93,0x05,0x00,0x00,
|
||||||
|
0x13,0x05,0x04,0x00,0xef,0xf0,0x5f,0xf6,0x13,0x07,0x90,0x3e,0x1b,0x07,0xf7,0xff,
|
||||||
|
0xe3,0x00,0x07,0xfc,0x83,0x27,0xc4,0x04,0x9b,0x87,0x07,0x00,0xe3,0xc8,0x07,0xfe,
|
||||||
|
0x93,0xf7,0x17,0x00,0xe3,0x98,0x07,0xfc,0x23,0x2c,0x04,0x00,0x83,0x27,0x04,0x04,
|
||||||
|
0x13,0x05,0x00,0x00,0x93,0xe7,0x87,0x00,0x23,0x20,0xf4,0x04,0x6f,0xf0,0x9f,0xf9,
|
||||||
|
0x13,0x01,0x01,0xfb,0x23,0x34,0x11,0x04,0x23,0x30,0x81,0x04,0x23,0x3c,0x91,0x02,
|
||||||
|
0x13,0x04,0x05,0x00,0x23,0x38,0x21,0x03,0x23,0x30,0x41,0x03,0x23,0x38,0x61,0x01,
|
||||||
|
0x23,0x34,0x71,0x01,0x13,0x0a,0x06,0x00,0x93,0x8b,0x05,0x00,0x93,0x84,0x06,0x00,
|
||||||
|
0x13,0x09,0x07,0x00,0x23,0x34,0x31,0x03,0x23,0x3c,0x51,0x01,0x23,0x30,0x81,0x01,
|
||||||
|
0xef,0xf0,0x1f,0xec,0x83,0x27,0x04,0x06,0x13,0x05,0x04,0x00,0x93,0xf7,0xe7,0xff,
|
||||||
|
0x23,0x20,0xf4,0x06,0xef,0xf0,0x1f,0xf0,0x13,0x0b,0x05,0x00,0x63,0x1c,0x05,0x00,
|
||||||
|
0x9b,0x87,0xfb,0xff,0xb3,0xf7,0xf4,0x00,0x9b,0x87,0x07,0x00,0x13,0x0c,0x20,0x00,
|
||||||
|
0x63,0x12,0x09,0x04,0x83,0x27,0x04,0x06,0x83,0x30,0x81,0x04,0x13,0x05,0x0b,0x00,
|
||||||
|
0x93,0xe7,0x17,0x00,0x23,0x20,0xf4,0x06,0x03,0x34,0x01,0x04,0x83,0x34,0x81,0x03,
|
||||||
|
0x03,0x39,0x01,0x03,0x83,0x39,0x81,0x02,0x03,0x3a,0x01,0x02,0x83,0x3a,0x81,0x01,
|
||||||
|
0x03,0x3b,0x01,0x01,0x83,0x3b,0x81,0x00,0x03,0x3c,0x01,0x00,0x13,0x01,0x01,0x05,
|
||||||
|
0x67,0x80,0x00,0x00,0x3b,0x07,0xf9,0x00,0x93,0x09,0x09,0x00,0x63,0xf4,0xeb,0x00,
|
||||||
|
0xbb,0x89,0xfb,0x40,0x93,0x05,0x60,0x00,0x13,0x05,0x04,0x00,0xef,0xf0,0xdf,0xe5,
|
||||||
|
0x13,0x05,0x04,0x00,0xef,0xf0,0xdf,0xe2,0x93,0x05,0x20,0x00,0x23,0x2c,0x84,0x01,
|
||||||
|
0x13,0x05,0x04,0x00,0xef,0xf0,0x5f,0xe4,0x9b,0xd5,0x04,0x01,0x93,0xf5,0xf5,0x0f,
|
||||||
|
0x13,0x05,0x04,0x00,0xef,0xf0,0x5f,0xe3,0x9b,0xd5,0x84,0x00,0x93,0xf5,0xf5,0x0f,
|
||||||
|
0x13,0x05,0x04,0x00,0xef,0xf0,0x5f,0xe2,0x93,0xf5,0xf4,0x0f,0x13,0x05,0x04,0x00,
|
||||||
|
0xef,0xf0,0x9f,0xe1,0x93,0x0a,0x0a,0x00,0xbb,0x87,0x4a,0x41,0x63,0xec,0x37,0x03,
|
||||||
|
0x13,0x05,0x04,0x00,0xef,0xf0,0xdf,0xdd,0x13,0x05,0x04,0x00,0x23,0x2c,0x04,0x00,
|
||||||
|
0xef,0xf0,0x5f,0xe2,0x63,0x1a,0x05,0x02,0x93,0x97,0x09,0x02,0x93,0xd7,0x07,0x02,
|
||||||
|
0x33,0x0a,0xfa,0x00,0xbb,0x84,0x34,0x01,0x3b,0x09,0x39,0x41,0x93,0x07,0x00,0x00,
|
||||||
|
0x6f,0xf0,0x1f,0xf2,0x83,0xc5,0x0a,0x00,0x13,0x05,0x04,0x00,0x93,0x8a,0x1a,0x00,
|
||||||
|
0xef,0xf0,0x9f,0xdc,0x6f,0xf0,0x5f,0xfb,0x13,0x0b,0x05,0x00,0x6f,0xf0,0x9f,0xf0,
|
||||||
|
0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,
|
||||||
|
0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,
|
||||||
|
0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,
|
||||||
|
0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,
|
||||||
|
0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,
|
||||||
|
0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,
|
||||||
|
0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,
|
||||||
|
0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,0x09,0x53,0x67,0x08,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x80,0x00,0x00,0x00,0x00,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
@ -0,0 +1,255 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "../../../../src/flash/nor/spi.h"
|
||||||
|
|
||||||
|
/* Register offsets */
|
||||||
|
|
||||||
|
#define FESPI_REG_SCKDIV 0x00
|
||||||
|
#define FESPI_REG_SCKMODE 0x04
|
||||||
|
#define FESPI_REG_CSID 0x10
|
||||||
|
#define FESPI_REG_CSDEF 0x14
|
||||||
|
#define FESPI_REG_CSMODE 0x18
|
||||||
|
|
||||||
|
#define FESPI_REG_DCSSCK 0x28
|
||||||
|
#define FESPI_REG_DSCKCS 0x2a
|
||||||
|
#define FESPI_REG_DINTERCS 0x2c
|
||||||
|
#define FESPI_REG_DINTERXFR 0x2e
|
||||||
|
|
||||||
|
#define FESPI_REG_FMT 0x40
|
||||||
|
#define FESPI_REG_TXFIFO 0x48
|
||||||
|
#define FESPI_REG_RXFIFO 0x4c
|
||||||
|
#define FESPI_REG_TXCTRL 0x50
|
||||||
|
#define FESPI_REG_RXCTRL 0x54
|
||||||
|
|
||||||
|
#define FESPI_REG_FCTRL 0x60
|
||||||
|
#define FESPI_REG_FFMT 0x64
|
||||||
|
|
||||||
|
#define FESPI_REG_IE 0x70
|
||||||
|
#define FESPI_REG_IP 0x74
|
||||||
|
|
||||||
|
/* Fields */
|
||||||
|
|
||||||
|
#define FESPI_SCK_POL 0x1
|
||||||
|
#define FESPI_SCK_PHA 0x2
|
||||||
|
|
||||||
|
#define FESPI_FMT_PROTO(x) ((x) & 0x3)
|
||||||
|
#define FESPI_FMT_ENDIAN(x) (((x) & 0x1) << 2)
|
||||||
|
#define FESPI_FMT_DIR(x) (((x) & 0x1) << 3)
|
||||||
|
#define FESPI_FMT_LEN(x) (((x) & 0xf) << 16)
|
||||||
|
|
||||||
|
/* TXCTRL register */
|
||||||
|
#define FESPI_TXWM(x) ((x) & 0xffff)
|
||||||
|
/* RXCTRL register */
|
||||||
|
#define FESPI_RXWM(x) ((x) & 0xffff)
|
||||||
|
|
||||||
|
#define FESPI_IP_TXWM 0x1
|
||||||
|
#define FESPI_IP_RXWM 0x2
|
||||||
|
|
||||||
|
#define FESPI_FCTRL_EN 0x1
|
||||||
|
|
||||||
|
#define FESPI_INSN_CMD_EN 0x1
|
||||||
|
#define FESPI_INSN_ADDR_LEN(x) (((x) & 0x7) << 1)
|
||||||
|
#define FESPI_INSN_PAD_CNT(x) (((x) & 0xf) << 4)
|
||||||
|
#define FESPI_INSN_CMD_PROTO(x) (((x) & 0x3) << 8)
|
||||||
|
#define FESPI_INSN_ADDR_PROTO(x) (((x) & 0x3) << 10)
|
||||||
|
#define FESPI_INSN_DATA_PROTO(x) (((x) & 0x3) << 12)
|
||||||
|
#define FESPI_INSN_CMD_CODE(x) (((x) & 0xff) << 16)
|
||||||
|
#define FESPI_INSN_PAD_CODE(x) (((x) & 0xff) << 24)
|
||||||
|
|
||||||
|
/* Values */
|
||||||
|
|
||||||
|
#define FESPI_CSMODE_AUTO 0
|
||||||
|
#define FESPI_CSMODE_HOLD 2
|
||||||
|
#define FESPI_CSMODE_OFF 3
|
||||||
|
|
||||||
|
#define FESPI_DIR_RX 0
|
||||||
|
#define FESPI_DIR_TX 1
|
||||||
|
|
||||||
|
#define FESPI_PROTO_S 0
|
||||||
|
#define FESPI_PROTO_D 1
|
||||||
|
#define FESPI_PROTO_Q 2
|
||||||
|
|
||||||
|
#define FESPI_ENDIAN_MSB 0
|
||||||
|
#define FESPI_ENDIAN_LSB 1
|
||||||
|
/* Timeout in target "loops" */
|
||||||
|
#define FESPI_CMD_TIMEOUT 1000
|
||||||
|
#define FESPI_PROBE_TIMEOUT 1000
|
||||||
|
#define FESPI_MAX_TIMEOUT 30000
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ERROR_OK,
|
||||||
|
ERROR_FAIL
|
||||||
|
};
|
||||||
|
|
||||||
|
static int fespi_txwm_wait(volatile uint32_t *ctrl_base);
|
||||||
|
static void fespi_disable_hw_mode(volatile uint32_t *ctrl_base);
|
||||||
|
static void fespi_enable_hw_mode(volatile uint32_t *ctrl_base);
|
||||||
|
static int fespi_wip(volatile uint32_t *ctrl_base);
|
||||||
|
static int slow_fespi_write_buffer(volatile uint32_t *ctrl_base,
|
||||||
|
const uint8_t *buffer, unsigned offset, unsigned len);
|
||||||
|
|
||||||
|
int main(volatile uint32_t *ctrl_base, uint32_t page_size,
|
||||||
|
const uint8_t *buffer, unsigned offset, uint32_t count)
|
||||||
|
{
|
||||||
|
fespi_txwm_wait(ctrl_base);
|
||||||
|
|
||||||
|
/* Disable Hardware accesses*/
|
||||||
|
fespi_disable_hw_mode(ctrl_base);
|
||||||
|
|
||||||
|
/* poll WIP */
|
||||||
|
int retval = fespi_wip(ctrl_base);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
/* Assume page_size is a power of two so we don't need the modulus code. */
|
||||||
|
uint32_t page_offset = offset & (page_size - 1);
|
||||||
|
|
||||||
|
/* central part, aligned words */
|
||||||
|
while (count > 0) {
|
||||||
|
uint32_t cur_count;
|
||||||
|
/* clip block at page boundary */
|
||||||
|
if (page_offset + count > page_size)
|
||||||
|
cur_count = page_size - page_offset;
|
||||||
|
else
|
||||||
|
cur_count = count;
|
||||||
|
|
||||||
|
retval = slow_fespi_write_buffer(ctrl_base, buffer, offset, cur_count);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
page_offset = 0;
|
||||||
|
buffer += cur_count;
|
||||||
|
offset += cur_count;
|
||||||
|
count -= cur_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
/* Switch to HW mode before return to prompt */
|
||||||
|
fespi_enable_hw_mode(ctrl_base);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t fespi_read_reg(volatile uint32_t *ctrl_base, unsigned address)
|
||||||
|
{
|
||||||
|
return ctrl_base[address / 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fespi_write_reg(volatile uint32_t *ctrl_base, unsigned address, uint32_t value)
|
||||||
|
{
|
||||||
|
ctrl_base[address / 4] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fespi_disable_hw_mode(volatile uint32_t *ctrl_base)
|
||||||
|
{
|
||||||
|
uint32_t fctrl = fespi_read_reg(ctrl_base, FESPI_REG_FCTRL);
|
||||||
|
fespi_write_reg(ctrl_base, FESPI_REG_FCTRL, fctrl & ~FESPI_FCTRL_EN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fespi_enable_hw_mode(volatile uint32_t *ctrl_base)
|
||||||
|
{
|
||||||
|
uint32_t fctrl = fespi_read_reg(ctrl_base, FESPI_REG_FCTRL);
|
||||||
|
fespi_write_reg(ctrl_base, FESPI_REG_FCTRL, fctrl | FESPI_FCTRL_EN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fespi_txwm_wait(volatile uint32_t *ctrl_base)
|
||||||
|
{
|
||||||
|
unsigned timeout = 1000;
|
||||||
|
|
||||||
|
while (timeout--) {
|
||||||
|
uint32_t ip = fespi_read_reg(ctrl_base, FESPI_REG_IP);
|
||||||
|
if (ip & FESPI_IP_TXWM)
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fespi_set_dir(volatile uint32_t *ctrl_base, bool dir)
|
||||||
|
{
|
||||||
|
uint32_t fmt = fespi_read_reg(ctrl_base, FESPI_REG_FMT);
|
||||||
|
fespi_write_reg(ctrl_base, FESPI_REG_FMT,
|
||||||
|
(fmt & ~(FESPI_FMT_DIR(0xFFFFFFFF))) | FESPI_FMT_DIR(dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fespi_tx(volatile uint32_t *ctrl_base, uint8_t in)
|
||||||
|
{
|
||||||
|
unsigned timeout = 1000;
|
||||||
|
|
||||||
|
while (timeout--) {
|
||||||
|
uint32_t txfifo = fespi_read_reg(ctrl_base, FESPI_REG_TXFIFO);
|
||||||
|
if (!(txfifo >> 31)) {
|
||||||
|
fespi_write_reg(ctrl_base, FESPI_REG_TXFIFO, in);
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fespi_rx(volatile uint32_t *ctrl_base, uint8_t *out)
|
||||||
|
{
|
||||||
|
unsigned timeout = 1000;
|
||||||
|
|
||||||
|
while (timeout--) {
|
||||||
|
uint32_t value = fespi_read_reg(ctrl_base, FESPI_REG_RXFIFO);
|
||||||
|
if (!(value >> 31)) {
|
||||||
|
if (out)
|
||||||
|
*out = value & 0xff;
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fespi_wip(volatile uint32_t *ctrl_base)
|
||||||
|
{
|
||||||
|
fespi_set_dir(ctrl_base, FESPI_DIR_RX);
|
||||||
|
|
||||||
|
fespi_write_reg(ctrl_base, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
|
||||||
|
|
||||||
|
fespi_tx(ctrl_base, SPIFLASH_READ_STATUS);
|
||||||
|
if (fespi_rx(ctrl_base, NULL) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
unsigned timeout = 1000;
|
||||||
|
while (timeout--) {
|
||||||
|
fespi_tx(ctrl_base, 0);
|
||||||
|
uint8_t rx;
|
||||||
|
if (fespi_rx(ctrl_base, &rx) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
if ((rx & SPIFLASH_BSY_BIT) == 0) {
|
||||||
|
fespi_write_reg(ctrl_base, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
|
||||||
|
fespi_set_dir(ctrl_base, FESPI_DIR_TX);
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int slow_fespi_write_buffer(volatile uint32_t *ctrl_base,
|
||||||
|
const uint8_t *buffer, unsigned offset, unsigned len)
|
||||||
|
{
|
||||||
|
fespi_tx(ctrl_base, SPIFLASH_WRITE_ENABLE);
|
||||||
|
fespi_txwm_wait(ctrl_base);
|
||||||
|
|
||||||
|
fespi_write_reg(ctrl_base, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
|
||||||
|
|
||||||
|
fespi_tx(ctrl_base, SPIFLASH_PAGE_PROGRAM);
|
||||||
|
|
||||||
|
fespi_tx(ctrl_base, offset >> 16);
|
||||||
|
fespi_tx(ctrl_base, offset >> 8);
|
||||||
|
fespi_tx(ctrl_base, offset);
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < len; i++)
|
||||||
|
fespi_tx(ctrl_base, buffer[i]);
|
||||||
|
|
||||||
|
fespi_txwm_wait(ctrl_base);
|
||||||
|
|
||||||
|
fespi_write_reg(ctrl_base, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
|
||||||
|
|
||||||
|
return fespi_wip(ctrl_base);
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
#if __riscv_xlen == 64
|
||||||
|
# define LREG ld
|
||||||
|
# define SREG sd
|
||||||
|
# define REGBYTES 8
|
||||||
|
#else
|
||||||
|
# define LREG lw
|
||||||
|
# define SREG sw
|
||||||
|
# define REGBYTES 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.section .text.entry
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
la sp, stack_end
|
||||||
|
jal main
|
||||||
|
ebreak
|
||||||
|
|
||||||
|
.section .data
|
||||||
|
stack:
|
||||||
|
.fill 16, REGBYTES, 0x8675309
|
||||||
|
stack_end:
|
|
@ -471,262 +471,13 @@ static int slow_fespi_write_buffer(struct flash_bank *bank,
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t algorithm_bin[] = {
|
static const uint8_t riscv32_bin[] = {
|
||||||
#include "../../../contrib/loaders/flash/fespi/fespi.inc"
|
#include "../../../contrib/loaders/flash/fespi/riscv32_fespi.inc"
|
||||||
};
|
|
||||||
#define STEP_EXIT 4
|
|
||||||
#define STEP_TX 8
|
|
||||||
#define STEP_TXWM_WAIT 12
|
|
||||||
#define STEP_WRITE_REG 16
|
|
||||||
#define STEP_WIP_WAIT 20
|
|
||||||
#define STEP_SET_DIR 24
|
|
||||||
#define STEP_NOP 0xff
|
|
||||||
|
|
||||||
struct algorithm_steps {
|
|
||||||
unsigned size;
|
|
||||||
unsigned used;
|
|
||||||
uint8_t **steps;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct algorithm_steps *as_new(void)
|
static const uint8_t riscv64_bin[] = {
|
||||||
{
|
#include "../../../contrib/loaders/flash/fespi/riscv64_fespi.inc"
|
||||||
struct algorithm_steps *as = calloc(1, sizeof(struct algorithm_steps));
|
};
|
||||||
as->size = 8;
|
|
||||||
as->steps = malloc(as->size * sizeof(as->steps[0]));
|
|
||||||
return as;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct algorithm_steps *as_delete(struct algorithm_steps *as)
|
|
||||||
{
|
|
||||||
for (unsigned step = 0; step < as->used; step++) {
|
|
||||||
free(as->steps[step]);
|
|
||||||
as->steps[step] = NULL;
|
|
||||||
}
|
|
||||||
free(as->steps);
|
|
||||||
free(as);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int as_empty(struct algorithm_steps *as)
|
|
||||||
{
|
|
||||||
for (unsigned s = 0; s < as->used; s++) {
|
|
||||||
if (as->steps[s][0] != STEP_NOP)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return size of compiled program. */
|
|
||||||
static unsigned as_compile(struct algorithm_steps *as, uint8_t *target,
|
|
||||||
unsigned target_size)
|
|
||||||
{
|
|
||||||
unsigned offset = 0;
|
|
||||||
bool finish_early = false;
|
|
||||||
for (unsigned s = 0; s < as->used && !finish_early; s++) {
|
|
||||||
unsigned bytes_left = target_size - offset;
|
|
||||||
switch (as->steps[s][0]) {
|
|
||||||
case STEP_NOP:
|
|
||||||
break;
|
|
||||||
case STEP_TX:
|
|
||||||
{
|
|
||||||
unsigned size = as->steps[s][1];
|
|
||||||
if (size + 3 > bytes_left) {
|
|
||||||
finish_early = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
memcpy(target + offset, as->steps[s], size + 2);
|
|
||||||
offset += size + 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STEP_WRITE_REG:
|
|
||||||
if (4 > bytes_left) {
|
|
||||||
finish_early = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
memcpy(target + offset, as->steps[s], 3);
|
|
||||||
offset += 3;
|
|
||||||
break;
|
|
||||||
case STEP_SET_DIR:
|
|
||||||
if (3 > bytes_left) {
|
|
||||||
finish_early = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
memcpy(target + offset, as->steps[s], 2);
|
|
||||||
offset += 2;
|
|
||||||
break;
|
|
||||||
case STEP_TXWM_WAIT:
|
|
||||||
case STEP_WIP_WAIT:
|
|
||||||
if (2 > bytes_left) {
|
|
||||||
finish_early = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
memcpy(target + offset, as->steps[s], 1);
|
|
||||||
offset += 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(0);
|
|
||||||
}
|
|
||||||
if (!finish_early)
|
|
||||||
as->steps[s][0] = STEP_NOP;
|
|
||||||
}
|
|
||||||
assert(offset + 1 <= target_size);
|
|
||||||
target[offset++] = STEP_EXIT;
|
|
||||||
|
|
||||||
LOG_DEBUG("%d-byte program:", offset);
|
|
||||||
for (unsigned i = 0; i < offset;) {
|
|
||||||
char buf[80];
|
|
||||||
for (unsigned x = 0; i < offset && x < 16; x++, i++)
|
|
||||||
sprintf(buf + x*3, "%02x ", target[i]);
|
|
||||||
LOG_DEBUG("%s", buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void as_add_step(struct algorithm_steps *as, uint8_t *step)
|
|
||||||
{
|
|
||||||
if (as->used == as->size) {
|
|
||||||
as->size *= 2;
|
|
||||||
as->steps = realloc(as->steps, sizeof(as->steps[0]) * as->size);
|
|
||||||
LOG_DEBUG("Increased size to 0x%x", as->size);
|
|
||||||
}
|
|
||||||
as->steps[as->used] = step;
|
|
||||||
as->used++;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void as_add_tx(struct algorithm_steps *as, unsigned count, const uint8_t *data)
|
|
||||||
{
|
|
||||||
LOG_DEBUG("count=%d", count);
|
|
||||||
while (count > 0) {
|
|
||||||
unsigned step_count = MIN(count, 255);
|
|
||||||
uint8_t *step = malloc(step_count + 2);
|
|
||||||
step[0] = STEP_TX;
|
|
||||||
step[1] = step_count;
|
|
||||||
memcpy(step + 2, data, step_count);
|
|
||||||
as_add_step(as, step);
|
|
||||||
data += step_count;
|
|
||||||
count -= step_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void as_add_tx1(struct algorithm_steps *as, uint8_t byte)
|
|
||||||
{
|
|
||||||
uint8_t data[1];
|
|
||||||
data[0] = byte;
|
|
||||||
as_add_tx(as, 1, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void as_add_write_reg(struct algorithm_steps *as, uint8_t offset, uint8_t data)
|
|
||||||
{
|
|
||||||
uint8_t *step = malloc(3);
|
|
||||||
step[0] = STEP_WRITE_REG;
|
|
||||||
step[1] = offset;
|
|
||||||
step[2] = data;
|
|
||||||
as_add_step(as, step);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void as_add_txwm_wait(struct algorithm_steps *as)
|
|
||||||
{
|
|
||||||
uint8_t *step = malloc(1);
|
|
||||||
step[0] = STEP_TXWM_WAIT;
|
|
||||||
as_add_step(as, step);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void as_add_wip_wait(struct algorithm_steps *as)
|
|
||||||
{
|
|
||||||
uint8_t *step = malloc(1);
|
|
||||||
step[0] = STEP_WIP_WAIT;
|
|
||||||
as_add_step(as, step);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void as_add_set_dir(struct algorithm_steps *as, bool dir)
|
|
||||||
{
|
|
||||||
uint8_t *step = malloc(2);
|
|
||||||
step[0] = STEP_SET_DIR;
|
|
||||||
step[1] = FESPI_FMT_DIR(dir);
|
|
||||||
as_add_step(as, step);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This should write something less than or equal to a page.*/
|
|
||||||
static int steps_add_buffer_write(struct algorithm_steps *as,
|
|
||||||
const uint8_t *buffer, uint32_t chip_offset, uint32_t len)
|
|
||||||
{
|
|
||||||
if (chip_offset & 0xFF000000) {
|
|
||||||
LOG_ERROR("FESPI interface does not support greater than 3B addressing, can't write to offset 0x%x",
|
|
||||||
chip_offset);
|
|
||||||
return ERROR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
as_add_tx1(as, SPIFLASH_WRITE_ENABLE);
|
|
||||||
as_add_txwm_wait(as);
|
|
||||||
as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
|
|
||||||
|
|
||||||
uint8_t setup[] = {
|
|
||||||
SPIFLASH_PAGE_PROGRAM,
|
|
||||||
chip_offset >> 16,
|
|
||||||
chip_offset >> 8,
|
|
||||||
chip_offset,
|
|
||||||
};
|
|
||||||
as_add_tx(as, sizeof(setup), setup);
|
|
||||||
|
|
||||||
as_add_tx(as, len, buffer);
|
|
||||||
as_add_txwm_wait(as);
|
|
||||||
as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
|
|
||||||
|
|
||||||
/* fespi_wip() */
|
|
||||||
as_add_set_dir(as, FESPI_DIR_RX);
|
|
||||||
as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_HOLD);
|
|
||||||
as_add_wip_wait(as);
|
|
||||||
as_add_write_reg(as, FESPI_REG_CSMODE, FESPI_CSMODE_AUTO);
|
|
||||||
as_add_set_dir(as, FESPI_DIR_TX);
|
|
||||||
|
|
||||||
return ERROR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int steps_execute(struct algorithm_steps *as,
|
|
||||||
struct flash_bank *bank, struct working_area *algorithm_wa,
|
|
||||||
struct working_area *data_wa)
|
|
||||||
{
|
|
||||||
struct target *target = bank->target;
|
|
||||||
struct fespi_flash_bank *fespi_info = bank->driver_priv;
|
|
||||||
uint32_t ctrl_base = fespi_info->ctrl_base;
|
|
||||||
int xlen = riscv_xlen(target);
|
|
||||||
|
|
||||||
struct reg_param reg_params[2];
|
|
||||||
init_reg_param(®_params[0], "a0", xlen, PARAM_OUT);
|
|
||||||
init_reg_param(®_params[1], "a1", xlen, PARAM_OUT);
|
|
||||||
buf_set_u64(reg_params[0].value, 0, xlen, ctrl_base);
|
|
||||||
buf_set_u64(reg_params[1].value, 0, xlen, data_wa->address);
|
|
||||||
|
|
||||||
int retval = ERROR_OK;
|
|
||||||
while (!as_empty(as)) {
|
|
||||||
keep_alive();
|
|
||||||
uint8_t *data_buf = malloc(data_wa->size);
|
|
||||||
unsigned bytes = as_compile(as, data_buf, data_wa->size);
|
|
||||||
retval = target_write_buffer(target, data_wa->address, bytes,
|
|
||||||
data_buf);
|
|
||||||
free(data_buf);
|
|
||||||
if (retval != ERROR_OK) {
|
|
||||||
LOG_ERROR("Failed to write data to " TARGET_ADDR_FMT ": %d",
|
|
||||||
data_wa->address, retval);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
|
|
||||||
algorithm_wa->address, algorithm_wa->address + 4,
|
|
||||||
10000, NULL);
|
|
||||||
if (retval != ERROR_OK) {
|
|
||||||
LOG_ERROR("Failed to execute algorithm at " TARGET_ADDR_FMT ": %d",
|
|
||||||
algorithm_wa->address, retval);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exit:
|
|
||||||
destroy_reg_param(®_params[1]);
|
|
||||||
destroy_reg_param(®_params[0]);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
|
static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||||
uint32_t offset, uint32_t count)
|
uint32_t offset, uint32_t count)
|
||||||
|
@ -737,8 +488,7 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||||
int sector;
|
int sector;
|
||||||
int retval = ERROR_OK;
|
int retval = ERROR_OK;
|
||||||
|
|
||||||
LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32,
|
LOG_DEBUG("offset=0x%08" PRIx32 " count=0x%08" PRIx32, offset, count);
|
||||||
__func__, offset, count);
|
|
||||||
|
|
||||||
if (target->state != TARGET_HALTED) {
|
if (target->state != TARGET_HALTED) {
|
||||||
LOG_ERROR("Target not halted");
|
LOG_ERROR("Target not halted");
|
||||||
|
@ -763,80 +513,143 @@ static int fespi_write(struct flash_bank *bank, const uint8_t *buffer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct working_area *algorithm_wa;
|
int xlen = riscv_xlen(target);
|
||||||
if (target_alloc_working_area(target, sizeof(algorithm_bin),
|
struct working_area *algorithm_wa = NULL;
|
||||||
&algorithm_wa) != ERROR_OK) {
|
struct working_area *data_wa = NULL;
|
||||||
LOG_WARNING("Couldn't allocate %zd-byte working area.",
|
const uint8_t *bin;
|
||||||
sizeof(algorithm_bin));
|
size_t bin_size;
|
||||||
algorithm_wa = NULL;
|
if (xlen == 32) {
|
||||||
|
bin = riscv32_bin;
|
||||||
|
bin_size = sizeof(riscv32_bin);
|
||||||
} else {
|
} else {
|
||||||
|
bin = riscv64_bin;
|
||||||
|
bin_size = sizeof(riscv64_bin);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned data_wa_size = 0;
|
||||||
|
if (target_alloc_working_area(target, bin_size, &algorithm_wa) == ERROR_OK) {
|
||||||
retval = target_write_buffer(target, algorithm_wa->address,
|
retval = target_write_buffer(target, algorithm_wa->address,
|
||||||
sizeof(algorithm_bin), algorithm_bin);
|
bin_size, bin);
|
||||||
if (retval != ERROR_OK) {
|
if (retval != ERROR_OK) {
|
||||||
LOG_ERROR("Failed to write code to " TARGET_ADDR_FMT ": %d",
|
LOG_ERROR("Failed to write code to " TARGET_ADDR_FMT ": %d",
|
||||||
algorithm_wa->address, retval);
|
algorithm_wa->address, retval);
|
||||||
target_free_working_area(target, algorithm_wa);
|
target_free_working_area(target, algorithm_wa);
|
||||||
algorithm_wa = NULL;
|
algorithm_wa = NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
struct working_area *data_wa = NULL;
|
data_wa_size = MIN(target->working_area_size - algorithm_wa->size, count);
|
||||||
unsigned data_wa_size = 2 * count;
|
while (1) {
|
||||||
while (1) {
|
if (data_wa_size < 128) {
|
||||||
if (data_wa_size < 128) {
|
LOG_WARNING("Couldn't allocate data working area.");
|
||||||
LOG_WARNING("Couldn't allocate data working area.");
|
target_free_working_area(target, algorithm_wa);
|
||||||
target_free_working_area(target, algorithm_wa);
|
algorithm_wa = NULL;
|
||||||
algorithm_wa = NULL;
|
}
|
||||||
}
|
if (target_alloc_working_area_try(target, data_wa_size, &data_wa) ==
|
||||||
if (target_alloc_working_area_try(target, data_wa_size, &data_wa) ==
|
ERROR_OK) {
|
||||||
ERROR_OK) {
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
data_wa_size /= 2;
|
data_wa_size = data_wa_size * 3 / 4;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG_WARNING("Couldn't allocate %zd-byte working area.", bin_size);
|
||||||
|
algorithm_wa = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If no valid page_size, use reasonable default. */
|
/* If no valid page_size, use reasonable default. */
|
||||||
page_size = fespi_info->dev->pagesize ?
|
page_size = fespi_info->dev->pagesize ?
|
||||||
fespi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
|
fespi_info->dev->pagesize : SPIFLASH_DEF_PAGESIZE;
|
||||||
|
|
||||||
fespi_txwm_wait(bank);
|
if (algorithm_wa) {
|
||||||
|
struct reg_param reg_params[5];
|
||||||
|
init_reg_param(®_params[0], "a0", xlen, PARAM_IN_OUT);
|
||||||
|
init_reg_param(®_params[1], "a1", xlen, PARAM_OUT);
|
||||||
|
init_reg_param(®_params[2], "a2", xlen, PARAM_OUT);
|
||||||
|
init_reg_param(®_params[3], "a3", xlen, PARAM_OUT);
|
||||||
|
init_reg_param(®_params[4], "a4", xlen, PARAM_OUT);
|
||||||
|
|
||||||
/* Disable Hardware accesses*/
|
while (count > 0) {
|
||||||
if (fespi_disable_hw_mode(bank) != ERROR_OK)
|
cur_count = MIN(count, data_wa_size);
|
||||||
return ERROR_FAIL;
|
buf_set_u64(reg_params[0].value, 0, xlen, fespi_info->ctrl_base);
|
||||||
|
buf_set_u64(reg_params[1].value, 0, xlen, page_size);
|
||||||
|
buf_set_u64(reg_params[2].value, 0, xlen, data_wa->address);
|
||||||
|
buf_set_u64(reg_params[3].value, 0, xlen, offset);
|
||||||
|
buf_set_u64(reg_params[4].value, 0, xlen, cur_count);
|
||||||
|
|
||||||
struct algorithm_steps *as = as_new();
|
retval = target_write_buffer(target, data_wa->address, cur_count,
|
||||||
|
buffer);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_DEBUG("Failed to write %d bytes to " TARGET_ADDR_FMT ": %d",
|
||||||
|
cur_count, data_wa->address, retval);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
/* poll WIP */
|
LOG_DEBUG("write(ctrl_base=0x%" TARGET_PRIxADDR ", page_size=0x%x, "
|
||||||
retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
|
"address=0x%" TARGET_PRIxADDR ", offset=0x%" PRIx32
|
||||||
if (retval != ERROR_OK)
|
", count=0x%" PRIx32 "), buffer=%02x %02x %02x %02x %02x %02x ..." PRIx32,
|
||||||
goto err;
|
fespi_info->ctrl_base, page_size, data_wa->address, offset, cur_count,
|
||||||
|
buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
|
||||||
|
retval = target_run_algorithm(target, 0, NULL, 5, reg_params,
|
||||||
|
algorithm_wa->address, 0, 10000, NULL);
|
||||||
|
if (retval != ERROR_OK) {
|
||||||
|
LOG_ERROR("Failed to execute algorithm at " TARGET_ADDR_FMT ": %d",
|
||||||
|
algorithm_wa->address, retval);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
page_offset = offset % page_size;
|
int algorithm_result = buf_get_u64(reg_params[0].value, 0, xlen);
|
||||||
/* central part, aligned words */
|
if (algorithm_result != 0) {
|
||||||
while (count > 0) {
|
LOG_ERROR("Algorithm returned error %d", algorithm_result);
|
||||||
/* clip block at page boundary */
|
retval = ERROR_FAIL;
|
||||||
if (page_offset + count > page_size)
|
goto err;
|
||||||
cur_count = page_size - page_offset;
|
}
|
||||||
else
|
|
||||||
cur_count = count;
|
|
||||||
|
|
||||||
if (algorithm_wa)
|
page_offset = 0;
|
||||||
retval = steps_add_buffer_write(as, buffer, offset, cur_count);
|
buffer += cur_count;
|
||||||
else
|
offset += cur_count;
|
||||||
retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
|
count -= cur_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
target_free_working_area(target, data_wa);
|
||||||
|
target_free_working_area(target, algorithm_wa);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
fespi_txwm_wait(bank);
|
||||||
|
|
||||||
|
/* Disable Hardware accesses*/
|
||||||
|
if (fespi_disable_hw_mode(bank) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
/* poll WIP */
|
||||||
|
retval = fespi_wip(bank, FESPI_PROBE_TIMEOUT);
|
||||||
if (retval != ERROR_OK)
|
if (retval != ERROR_OK)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
page_offset = 0;
|
page_offset = offset % page_size;
|
||||||
buffer += cur_count;
|
/* central part, aligned words */
|
||||||
offset += cur_count;
|
while (count > 0) {
|
||||||
count -= cur_count;
|
/* clip block at page boundary */
|
||||||
|
if (page_offset + count > page_size)
|
||||||
|
cur_count = page_size - page_offset;
|
||||||
|
else
|
||||||
|
cur_count = count;
|
||||||
|
|
||||||
|
retval = slow_fespi_write_buffer(bank, buffer, offset, cur_count);
|
||||||
|
if (retval != ERROR_OK)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
page_offset = 0;
|
||||||
|
buffer += cur_count;
|
||||||
|
offset += cur_count;
|
||||||
|
count -= cur_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Switch to HW mode before return to prompt */
|
||||||
|
if (fespi_enable_hw_mode(bank) != ERROR_OK)
|
||||||
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (algorithm_wa)
|
return ERROR_OK;
|
||||||
retval = steps_execute(as, bank, algorithm_wa, data_wa);
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (algorithm_wa) {
|
if (algorithm_wa) {
|
||||||
|
@ -844,11 +657,10 @@ err:
|
||||||
target_free_working_area(target, algorithm_wa);
|
target_free_working_area(target, algorithm_wa);
|
||||||
}
|
}
|
||||||
|
|
||||||
as_delete(as);
|
|
||||||
|
|
||||||
/* Switch to HW mode before return to prompt */
|
/* Switch to HW mode before return to prompt */
|
||||||
if (fespi_enable_hw_mode(bank) != ERROR_OK)
|
if (fespi_enable_hw_mode(bank) != ERROR_OK)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1480,6 +1480,12 @@ static int riscv_run_algorithm(struct target *target, int num_mem_params,
|
||||||
LOG_ERROR(" start = 0x%08x", (uint32_t) start);
|
LOG_ERROR(" start = 0x%08x", (uint32_t) start);
|
||||||
riscv_halt(target);
|
riscv_halt(target);
|
||||||
old_or_new_riscv_poll(target);
|
old_or_new_riscv_poll(target);
|
||||||
|
for (enum gdb_regno regno = 0; regno <= GDB_REGNO_PC; regno++) {
|
||||||
|
riscv_reg_t reg_value;
|
||||||
|
if (riscv_get_register(target, ®_value, regno) != ERROR_OK)
|
||||||
|
break;
|
||||||
|
LOG_ERROR("%s = 0x%" PRIx64, gdb_regno_name(regno), reg_value);
|
||||||
|
}
|
||||||
return ERROR_TARGET_TIMEOUT;
|
return ERROR_TARGET_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2790,10 +2796,68 @@ const char *gdb_regno_name(enum gdb_regno regno)
|
||||||
switch (regno) {
|
switch (regno) {
|
||||||
case GDB_REGNO_ZERO:
|
case GDB_REGNO_ZERO:
|
||||||
return "zero";
|
return "zero";
|
||||||
|
case GDB_REGNO_RA:
|
||||||
|
return "ra";
|
||||||
|
case GDB_REGNO_SP:
|
||||||
|
return "sp";
|
||||||
|
case GDB_REGNO_GP:
|
||||||
|
return "gp";
|
||||||
|
case GDB_REGNO_TP:
|
||||||
|
return "tp";
|
||||||
|
case GDB_REGNO_T0:
|
||||||
|
return "t0";
|
||||||
|
case GDB_REGNO_T1:
|
||||||
|
return "t1";
|
||||||
|
case GDB_REGNO_T2:
|
||||||
|
return "t2";
|
||||||
case GDB_REGNO_S0:
|
case GDB_REGNO_S0:
|
||||||
return "s0";
|
return "s0";
|
||||||
case GDB_REGNO_S1:
|
case GDB_REGNO_S1:
|
||||||
return "s1";
|
return "s1";
|
||||||
|
case GDB_REGNO_A0:
|
||||||
|
return "a0";
|
||||||
|
case GDB_REGNO_A1:
|
||||||
|
return "a1";
|
||||||
|
case GDB_REGNO_A2:
|
||||||
|
return "a2";
|
||||||
|
case GDB_REGNO_A3:
|
||||||
|
return "a3";
|
||||||
|
case GDB_REGNO_A4:
|
||||||
|
return "a4";
|
||||||
|
case GDB_REGNO_A5:
|
||||||
|
return "a5";
|
||||||
|
case GDB_REGNO_A6:
|
||||||
|
return "a6";
|
||||||
|
case GDB_REGNO_A7:
|
||||||
|
return "a7";
|
||||||
|
case GDB_REGNO_S2:
|
||||||
|
return "s2";
|
||||||
|
case GDB_REGNO_S3:
|
||||||
|
return "s3";
|
||||||
|
case GDB_REGNO_S4:
|
||||||
|
return "s4";
|
||||||
|
case GDB_REGNO_S5:
|
||||||
|
return "s5";
|
||||||
|
case GDB_REGNO_S6:
|
||||||
|
return "s6";
|
||||||
|
case GDB_REGNO_S7:
|
||||||
|
return "s7";
|
||||||
|
case GDB_REGNO_S8:
|
||||||
|
return "s8";
|
||||||
|
case GDB_REGNO_S9:
|
||||||
|
return "s9";
|
||||||
|
case GDB_REGNO_S10:
|
||||||
|
return "s10";
|
||||||
|
case GDB_REGNO_S11:
|
||||||
|
return "s11";
|
||||||
|
case GDB_REGNO_T3:
|
||||||
|
return "t3";
|
||||||
|
case GDB_REGNO_T4:
|
||||||
|
return "t4";
|
||||||
|
case GDB_REGNO_T5:
|
||||||
|
return "t5";
|
||||||
|
case GDB_REGNO_T6:
|
||||||
|
return "t6";
|
||||||
case GDB_REGNO_PC:
|
case GDB_REGNO_PC:
|
||||||
return "pc";
|
return "pc";
|
||||||
case GDB_REGNO_FPR0:
|
case GDB_REGNO_FPR0:
|
||||||
|
|
Loading…
Reference in New Issue