Browse Source

Flash integration started (import from Wolfgang)

master
kaqu 6 months ago
parent
commit
702443ce05
6 changed files with 247 additions and 20 deletions
  1. +150
    -0
      bit_to_flash.py
  2. +42
    -14
      firmware/main.c
  3. +30
    -0
      neopixelar.py
  4. +7
    -6
      prepare_firmware.py
  5. +5
    -0
      prog/openocd.cfg
  6. +13
    -0
      prog/openocd_colorlight_5a_75b (copy).cfg

+ 150
- 0
bit_to_flash.py View File

@ -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)

+ 42
- 14
firmware/main.c View File

@ -68,6 +68,16 @@ static void boot_sequence(void)
}
}
long mysleep(long delayms)
{
long r;
for(long l=0;l<delayms;l++)
for(long m=0;m<0xFFFFFFl;m++)
r += (long)(m*l/(m * m));
return r;
}
int main(int i, char **c)
{
char buffer[CMD_LINE_BUFFER_SIZE];
@ -77,22 +87,40 @@ int main(int i, char **c)
int nb_params;
int sdr_ok;
//npe_b24Data2Load_write(uint32_t)
//npe_b8LoadOffset_write(uint8_t v)
//npe_b8Len_write(uint8_t v)
//npe_bEnable_write(uint8_t v)
// This is the new illumination logic ------------------
int32_t green = 0x010000;
int32_t red = 0x000100;
int32_t blue = 0x000001;
for(int j=0;j<1000;j++) {
for(int i=0;i<27;i+=3)
{
npe_b8LoadOffset_write(i); // @Offset
npe_b24Data2Load_write(green); // G
npe_b8LoadOffset_write(i+1); // @Offset
npe_b24Data2Load_write(red); // R
npe_b8LoadOffset_write(i+2); // @Offset
npe_b24Data2Load_write(blue); // B
}
if(!j) { // Only on init. ...
npe_b8Len_write(27); // Length
npe_bEnable_write(1); // Enable!
}
mysleep(100000); // 100ms or so ... ;)
green <<= 1, red <<= 1, blue <<=1; // Increase intensity
if((green & 0xff0000) == 0) // High bit gone missing?
green = 1, red = 1, blue = 1; // Yap, reload!
}
for(int i=0;i<27;i+=3)
{
npe_b8LoadOffset_write(i); // @Offset 0
npe_b24Data2Load_write(0x040000); // G
npe_b8LoadOffset_write(i+1); // @Offset 0
npe_b24Data2Load_write(0x000400); // R
npe_b8LoadOffset_write(i+2); // @Offset 0
npe_b24Data2Load_write(0x000004); // B
if(!i) // Only on init. ...
npe_b8Len_write(27); // Length
npe_bEnable_write(1); // Enable!
{ //
npe_b8LoadOffset_write(i); // @Offset
npe_b24Data2Load_write(0); // G
npe_b8LoadOffset_write(i+1); // @Offset
npe_b24Data2Load_write(0); // R
npe_b8LoadOffset_write(i+2); // @Offset
npe_b24Data2Load_write(0); // B
}
// end of illumination logic -----------------------------
#ifdef CONFIG_CPU_HAS_INTERRUPT
irq_setmask(0);


+ 30
- 0
neopixelar.py View File

@ -341,6 +341,21 @@ class BaseSoC(SoCCore):
self.comb += platform.request("gpio", i).eq(self.npe.bDataPin) # Output data pin
# Build --------------------------------------------------------------------------------------------
def load(file):
import os
os.system("mkdir -p prog")
print("--------")
f = open("prog/openocd.cfg", "w")
f.write(
"""
interface vsllink
adapter_khz 100
reset_config none
jtag newtap ecp5 tap -irlen 8 -expected-id 0x41111043
""")
f.close()
os.system(f"openocd -f prog/openocd.cfg -c \"transport select jtag; init; svf {file}; exit\"")
exit()
def main():
parser = argparse.ArgumentParser(description="LiteX SoC on Colorlight 5A-75X")
@ -361,6 +376,7 @@ def main():
parser.add_argument("--sdram-rate", default="1:1", help="SDRAM Rate 1:1 Full Rate (default), 1:2 Half Rate")
parser.add_argument("--csr_csv", default="build/csr.csv", help="CSR list location")
parser.add_argument("--doc", action="store_true", help="Create doc files for sphinx generator")
parser.add_argument("--flash", action="store_true", help="Load bitstream to flash")
args = parser.parse_args()
assert not (args.with_ethernet and args.with_etherbone)
@ -374,6 +390,13 @@ def main():
use_internal_osc = args.use_internal_osc,
sdram_rate = args.sdram_rate,
**soc_core_argdict(args))
# 32MBit SPIFlash ---------------------------------------------------------------------------------
soc.mem_map["spiflash"] = 0xc0000000
# Boot at +1MB
soc.add_constant("FLASH_BOOT_ADDRESS", soc.mem_map["spiflash"] + 1024*1024)
soc.add_spi_flash(name="spiflash", mode="1x", dummy_cycles=8, clk_freq=5e6)
builder = Builder(soc, **builder_argdict(args))
builder.build(**trellis_argdict(args), run=args.build) # Written here to (local) build tree
@ -386,6 +409,13 @@ def main():
prog = soc.platform.create_programmer()
prog.load_bitstream(os.path.join(builder.gateware_dir, soc.build_name + ".svf"))
if args.flash: # Convert Bit File to Jtag Write Flash command
name = os.path.join(builder.gateware_dir, soc.build_name)
print(f"Executing ./bit_to_flash.py {name}.bit {name}.svf.flash")
os.system(f"./bit_to_flash.py {name}.bit {name}.svf.flash")
load(name + ".svf.flash")
return
if __name__ == "__main__":
copyjob() # Create backup if nec. & move our firmware to the correct location
main()


+ 7
- 6
prepare_firmware.py View File

@ -5,6 +5,8 @@
#
# Utility to temporarily move project local resources to LiteX path
# (w/ backing up of original data)
#
# Hint: Don't forget to adjust local litex path BEFORE usage!
#
# History:
# --------
@ -14,16 +16,15 @@
import os
import shutil
import litex.soc
def copyjob():
#for ev in os.environ:
# print(ev, " = ", os.environ[ev])
# $PWD path to working directory
# $HOME path to home directory of current user
localpath = os.environ["PWD"] + "/firmware/"
path2firmware = os.environ["HOME"] + "/fpga/litex/litex/litex/soc/software/bios/"
path2firmware = os.path.dirname(litex.soc.__file__) + "/software/bios/"
localpath = os.environ["PWD"] + "/firmware/"
originalfilename = "main.c"
backupfilename = "main.c.bak"
backupfilename2 = "main.c.original"
if os.path.isfile(path2firmware + backupfilename): # Check for existing backup
print("Backup already exists")
else: # Ok, no backup. Let's create one in-place & one to our local project directory ...


+ 5
- 0
prog/openocd.cfg View File

@ -0,0 +1,5 @@
interface vsllink
adapter_khz 100
reset_config none
jtag newtap ecp5 tap -irlen 8 -expected-id 0x41111043

+ 13
- 0
prog/openocd_colorlight_5a_75b (copy).cfg View File

@ -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…
Cancel
Save