6 changed files with 247 additions and 20 deletions
@ -0,0 +1,150 @@
|
||||
#!/usr/bin/env python3 |
||||
|
||||
import sys |
||||
import textwrap |
||||
|
||||
# Very basic bitstream to SVF converter, tested with the ULX3S WiFi interface |
||||
|
||||
flash_page_size = 256 |
||||
erase_block_size = 64*1024 |
||||
|
||||
|
||||
def bitreverse(x): |
||||
y = 0 |
||||
for i in range(8): |
||||
if (x >> (7 - i)) & 1 == 1: |
||||
y |= (1 << i) |
||||
return y |
||||
|
||||
with open(sys.argv[1], 'rb') as bitf: |
||||
bs = bitf.read() |
||||
# Autodetect IDCODE from bitstream |
||||
idcode_cmd = bytes([0xE2, 0x00, 0x00, 0x00]) |
||||
idcode = None |
||||
for i in range(len(bs) - 4): |
||||
if bs[i:i+4] == idcode_cmd: |
||||
idcode = bs[i+4] << 24 |
||||
idcode |= bs[i+5] << 16 |
||||
idcode |= bs[i+6] << 8 |
||||
idcode |= bs[i+7] |
||||
break |
||||
if idcode is None: |
||||
print("Failed to find IDCODE in bitstream, check bitstream is valid") |
||||
sys.exit(1) |
||||
print("IDCODE in bitstream is 0x%08x" % idcode) |
||||
bitf.seek(0) |
||||
|
||||
address = 0 |
||||
last_page = -1 |
||||
|
||||
with open(sys.argv[2], 'w') as svf: |
||||
print(""" |
||||
STATE RESET; |
||||
HDR 0; |
||||
HIR 0; |
||||
TDR 0; |
||||
TIR 0; |
||||
ENDDR DRPAUSE; |
||||
ENDIR IRPAUSE; |
||||
STATE IDLE; |
||||
""", file=svf) |
||||
print(""" |
||||
SIR 8 TDI (E0); |
||||
SDR 32 TDI (00000000) |
||||
TDO ({:08X}) |
||||
MASK (FFFFFFFF); |
||||
""".format(idcode), file=svf) |
||||
print(""" |
||||
SIR 8 TDI (1C); |
||||
SDR 510 TDI (3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF |
||||
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); |
||||
|
||||
// Enter Programming mode |
||||
SIR 8 TDI (C6); |
||||
SDR 8 TDI (00); |
||||
RUNTEST IDLE 2 TCK 1.00E-02 SEC; |
||||
|
||||
// Erase |
||||
SIR 8 TDI (0E); |
||||
SDR 8 TDI (01); |
||||
RUNTEST IDLE 2 TCK 2.0E-1 SEC; |
||||
|
||||
// Read STATUS |
||||
SIR 8 TDI (3C); |
||||
SDR 32 TDI (00000000) |
||||
TDO (00000000) |
||||
MASK (0000B000); |
||||
|
||||
// Exit Programming mode |
||||
SIR 8 TDI (26); |
||||
RUNTEST IDLE 2 TCK 1.00E-02 SEC; |
||||
|
||||
// BYPASS |
||||
SIR 8 TDI (FF); |
||||
STATE IDLE; |
||||
RUNTEST 32 TCK; |
||||
RUNTEST 2.00E-2 SEC; |
||||
|
||||
// Enter SPI mode |
||||
|
||||
SIR 8 TDI (3A); |
||||
SDR 16 TDI (68FE); |
||||
STATE IDLE; |
||||
RUNTEST 32 TCK; |
||||
RUNTEST 2.00E-2 SEC; |
||||
|
||||
// SPI IO |
||||
SDR 8 TDI (D5); |
||||
|
||||
RUNTEST 2.00E-0 SEC; |
||||
|
||||
// CONFIRM FLASH ID |
||||
!SDR 32 TDI (000000F9) |
||||
! TDO (68FFFFFF) |
||||
! MASK (FF000000); |
||||
|
||||
!SDR 8 TDI(60); |
||||
!SDR 16 TDI(0080); |
||||
!RUNTEST 1.00E-0 SEC; |
||||
|
||||
|
||||
""", file=svf) |
||||
while True: |
||||
if((address // 0x10000) != last_page): |
||||
last_page = (address // 0x10000) |
||||
print("""SDR 8 TDI (60); |
||||
""", file=svf) |
||||
address_flipped = [bitreverse(x) for x in [0xd8,int(address // 0x10000),0x00,0x00]] |
||||
hex_address= ["{:02X}".format(x) for x in reversed(address_flipped)] |
||||
print("\n".join(textwrap.wrap("SDR {} TDI ({});".format(8*len(hex_address), "".join(hex_address)), 100)), file=svf) |
||||
print("""RUNTEST 3.00 SEC; |
||||
""", file=svf) |
||||
|
||||
chunk = bitf.read(flash_page_size) |
||||
if not chunk: |
||||
break |
||||
# Convert chunk to bit-reversed hex |
||||
br_chunk = [bitreverse(x) for x in bytes([0x02, int(address / 0x10000 % 0x100),int(address / 0x100 % 0x100),int(address % 0x100)]) + chunk] |
||||
address += len(chunk) |
||||
hex_chunk = ["{:02X}".format(x) for x in reversed(br_chunk)] |
||||
print(""" |
||||
SDR 8 TDI (60); |
||||
""", file=svf) |
||||
print("\n".join(textwrap.wrap("SDR {} TDI ({});".format(8*len(br_chunk), "".join(hex_chunk)), 100)), file=svf) |
||||
print(""" |
||||
RUNTEST 2.50E-2 SEC; |
||||
""", file=svf) |
||||
|
||||
print(""" |
||||
// BYPASS |
||||
SIR 8 TDI (FF); |
||||
|
||||
//REFRESH |
||||
SIR 8 TDI(79); |
||||
SDR 24 TDI(000000); |
||||
|
||||
STATE IDLE; |
||||
RUNTEST 32 TCK; |
||||
RUNTEST 2.00E-2 SEC; |
||||
STATE RESET; |
||||
""", file=svf) |
@ -0,0 +1,5 @@
|
||||
|
||||
interface vsllink |
||||
adapter_khz 100 |
||||
reset_config none |
||||
jtag newtap ecp5 tap -irlen 8 -expected-id 0x41111043 |
@ -0,0 +1,13 @@
|
||||
# Wolfgang's configuration for STM Versaloon adapter |
||||
telnet_port 4444 |
||||
debug_level 0 |
||||
interface vsllink |
||||
adapter_khz 100 |
||||
transport select jtag |
||||
reset_config none |
||||
jtag newtap ecp5 tap -irlen 8 -expected-id 0x41111043 |
||||
#Neglect tests? |
||||
#init |
||||
#scan_chain |
||||
#svf -progress blink.svf |
||||
#shutdown |
Loading…
Reference in new issue