Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it work with Python 3 and BusPirate #1

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ There is a Windows PC project for visual studio 2010. Multiplatform support is p

The FX2LP device software needs the Keil PK51 toolchain. It is a very simple firmware that implements i2c protocol and can be commanded via USB. There is a compiled binary i2c.iic you can upload to the FX2LP device as well.

##Python fork of the programmer
##Python version, with native I2C backend

Was created to use native i2c bus, available on raspberry pi. For the moment it is added python realization which is identical to original programmer, written in C++. You need just 3 wires attached to raspberry pi

Expand All @@ -50,3 +50,9 @@ Connect:

You need to enable i2c interface in raspi-config (if not yet) and then reboot.
Also you need to install smbus module for python (since programmer uses smbus to talk over i2c).

##Python version, using BusPirate

The Python version now supports BusPirate.

Requires [pyBusPirateLite](https://github.com/juhasch/pyBusPirateLite) to be installed, but other than that no other configuration is necessary.
170 changes: 108 additions & 62 deletions pyprog.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import smbus
import time
import os
import sys
Expand Down Expand Up @@ -61,6 +60,8 @@ def FindChip (jedec_id):
, #Microchip
( "SST25VF512", 0xBF4800, 64 , 256, 32)
, ("SST25VF032", 0xBF4A00, 4 * 1024, 256, 32)
, #PUYA
( "P25Q40" , 0x856013, 512 , 256, 64)
, ( 0, 0 , 0 , 0 , 0)
)
for Flash in FlashDevices:
Expand All @@ -83,14 +84,16 @@ def GetManufacturerName ( jedec_id ):
return "Macronix"
elif id==0xbf:
return "Microchip"
elif id==0x85:
return "PUYA"

return "Unknown"


def SetupChipCommands ( jedec_id, pr ):
id = GetManufacturedId ( jedec_id )
if id==0xef:
print "Setup chip commands for Winbond..."
if id==0xef or id==0x85:
print("Setup chip commands for Winbond...")
# These are the codes for Winbond
pr.WriteReg ( 0x62, 0x6 ) #// Flash Write enable op code
pr.WriteReg ( 0x63, 0x50 ) #// Flash Write register op code
Expand All @@ -99,7 +102,7 @@ def SetupChipCommands ( jedec_id, pr ):
pr.WriteReg ( 0x6d, 0x2 ) #// Flash program op code.
pr.WriteReg ( 0x6e, 0x5 ) #// Flash read status op code.
else:
print "Can not handle manufacturer code %02x\n" % id
print("Can not handle manufacturer code %02x\n" % id)
sys.exit ( -6 )


Expand All @@ -112,7 +115,7 @@ def __init__(self):
def ProcessCRC (self, data):
for byte in data:
self.gCrc ^= byte<<8
for i in xrange(8):
for i in range(8):
if self.gCrc & 0x8000:
self.gCrc ^= 0x1070<<3
self.gCrc <<= 1
Expand All @@ -129,7 +132,7 @@ def __init__(self, data):
self.datalen = len(data)

def HasData(self):
return self.mask<>0 or self.datalen<>0
return (not self.mask == 0) or (not self.datalen == 0)

def DataSize(self):
return self.datalen
Expand Down Expand Up @@ -184,10 +187,11 @@ def Decode(self):
return 6 if self.ReadBit() else 0xff
return 0xff

class rtd():
class rtd_smbus():
"""speaks over i2c with RTD2660"""

def __init__(self, bus, addr):
import smbus
self.addr = addr
self.b = smbus.SMBus(bus)

Expand All @@ -198,6 +202,8 @@ def ReadByteFromAddr (self, reg):
return self.b.read_byte_data(self.addr, reg)

def ReadBytesFromAddr (self, reg, length):
if length>64:
length=64
self.b.write_byte_data(self.addr, reg, length)
data = []
for x in range(length):
Expand All @@ -210,6 +216,33 @@ def WriteBytesToAddr (self, reg, data):
def ReadReg (self, reg):
return self.b.read_byte_data(self.addr, reg)


class rtd_buspirate():
"""speaks over i2c with RTD2660"""

def __init__(self, addr):
from pyBusPirateLite.pyBusPirateLite import I2Chigh
self.addr = addr
self.b = I2Chigh()
self.b.speed = '400kHz'

def ReadReg (self, reg):
f = self.b.write_then_read(2,0, [self.addr << 1, reg])
f = self.b.write_then_read(1,1, [(self.addr << 1) | 1])
return f[0]

def WriteReg ( self, reg, data ):
self.b.write_then_read(3,0, [self.addr << 1, reg, data & 0xff])

def ReadBytesFromAddr (self, reg, length):
if length>32:
length=32
self.b.write_then_read(2,0, [self.addr << 1, reg])
return self.b.write_then_read(1,length, [(self.addr << 1) | 1])

def WriteBytesToAddr (self, reg, data):
self.b.write_then_read(2 + len(data), 0, [self.addr << 1, reg] + data)

class SPI():
"""SPI interface over i2c"""

Expand Down Expand Up @@ -263,12 +296,8 @@ def SPIRead (self, address, length):
continue

data = []
while length>0:
read_len = len
if read_len>64:
read_len=64
data += self.b.ReadBytesFromAddr ( 0x70, read_len)
length -= read_len
while len(data) < length:
data += self.b.ReadBytesFromAddr ( 0x70, length - len(data))

return data

Expand Down Expand Up @@ -298,17 +327,15 @@ def SaveFlash (filename, chip_size, spi):
sys.stdout.write("Reading %d of %d\r" % (addr, chip_size))
sys.stdout.flush()
buf = spi.SPIRead (addr, 1024)
str = ''.join(chr(i) for i in buf)

fdump.write(str)
fdump.write(bytes(buf))
crc.ProcessCRC(buf)
addr += 1024

fdump.close()
data_crc = crc.GetCRC()
print ""
print "Received data CRC %x" % data_crc
print "Chip CRC %x" % chip_crc
print("")
print("Received data CRC %x" % data_crc)
print("Chip CRC %x" % chip_crc)
return data_crc==chip_crc


Expand Down Expand Up @@ -346,14 +373,14 @@ def DecodeGff(data):
def ReadFile (filename):
fsize = os.stat(filename).st_size
if fsize > 8*1024*1024:
print "This file looks too big %d" % fsize
print("This file looks too big %d" % fsize)
return None
with open (filename, "rb") as fl:
content = fl.read()
if content[0:12]=="GMI GFF V1.0":
print "Detected GFF image"
print("Detected GFF image")
if fsize<256:
print "This file looks too small %d" % fsize
print("This file looks too small %d" % fsize)
return None
reslt, out = DecodeGff(content[256:])
if reslt:
Expand All @@ -366,25 +393,25 @@ def ReadFile (filename):
def ShouldProgramPage (buff):
chff = chr(0xff)
for ch in buff:
if ch<>chff:
if not ch == chff:
return True
return False


def EraseFlash(pr):
spi = SPI(pr)
print "Erasing..."
print("Erasing...")
spi.SPICommonCommand(E_CC_WRITE_AFTER_EWSR, 1, 0, 1, 0) # Unprotect the Status Register
spi.SPICommonCommand(E_CC_WRITE_AFTER_WREN, 1, 0, 1, 0) # Unprotect the flash
spi.SPICommonCommand(E_CC_ERASE, 0xc7, 0, 0, 0) # Chip Erase Erase
print "done"
print("done")

def ProgramFlash (filename, chip_size, pr):
prog = ReadFile(filename)
if not prog:
return False

print "Will write %dKb" % (len(prog)/1024)
print("Will write %dKb" % (len(prog)/1024))
spi = SPI(pr)
addr = 0
data_len = len(prog)
Expand All @@ -402,8 +429,8 @@ def ProgramFlash (filename, chip_size, pr):
if lng>data_len:
lng = data_len
buff = []
for i in xrange (lng):
buff.append (ord(prog[data_ptr+i]))
for i in range (lng):
buff.append (prog[data_ptr+i])

data_ptr += lng
data_len -= lng
Expand Down Expand Up @@ -441,51 +468,25 @@ def ProgramFlash (filename, chip_size, pr):
spi.SPICommonCommand(E_CC_WRITE_AFTER_WREN, 1, 0, 1, 0x1c) # Protect the flash
data_crc = crc.GetCRC()
chip_crc = spi.SPIComputeCRC ( 0, addr-1 )
print ""
print "Received data CRC %x" % data_crc
print "Chip CRC %x" % chip_crc
print("")
print("Received data CRC %x" % data_crc)
print("Chip CRC %x" % chip_crc)
return data_crc == chip_crc


def main():
try:
pr = rtd(1, 0x4a)
pr.WriteReg(0x6f, 0x80)
res = pr.ReadReg(0x6f)
if res & 0x80 == 0:
print "Can't enable ISP mode"
sys.exit(-1)

spir = SPI(pr)
jedec_id = spir.SPICommonCommand(E_CC_READ, 0x9f, 3, 0, 0)
print "JEDEC ID: 0x%x" % jedec_id

chip = FindChip(jedec_id)
if not chip:
print "Inknown chip ID"
sys.exit(-1)

chipsize = chip[2] * 1024
print "Manufacturer %s " % GetManufacturerName(jedec_id)
print "Chip: %s" % chip[0]
print "Size: %dKB" % chip[2]

# Setup flash command codes
SetupChipCommands (jedec_id,pr)

b = spir.SPICommonCommand(E_CC_READ, 0x5, 1, 0, 0)

print "Flash status register: 0x%x" % (b)
opts, args = getopt.getopt(sys.argv[1:], 'r:w:e', ['save=','flash=','erase'])
opts, args = getopt.getopt(sys.argv[1:], 'r:w:eb:', ['save=','flash=','erase','backend='])
except getopt.GetoptError:
print USAGE
print(USAGE)
sys.exit(2)

save = False
write = False
erase = False
infile = ""
ofile = ""
backend = None
for o, a in opts:
if o in ('-r', '--save'):
save = True
Expand All @@ -496,16 +497,61 @@ def main():
infile = a
elif o in ('-e', '--erase'):
erase = True
elif o in ('-b','--backend'):
backend = a

if backend is None:
try:
pr = rtd_smbus(1, 0x4a)
print("Using SMBUS backend (--backend=smbus)")
except:
print("Can't use SMBUS backend (use --backend=smbus to force it anyway), attempting BusPirate...")
pr = rtd_buspirate(0x4a)
print("Using BusPirate backend (assuming --backend=buspirate)")
elif backend == "smbus":
pr = rtd_smbus(1, 0x4a)
elif backend == "buspirate":
pr = rtd_buspirate(0x4a)
else:
print("Unknown backend: %s" % backend)
sys.exit(-1)

pr.WriteReg(0x6f, 0x80)
res = pr.ReadReg(0x6f)
if res & 0x80 == 0:
print("Can't enable ISP mode")
sys.exit(-1)

spir = SPI(pr)
jedec_id = spir.SPICommonCommand(E_CC_READ, 0x9f, 3, 0, 0)
print("JEDEC ID: 0x%x" % jedec_id)

chip = FindChip(jedec_id)
if not chip:
print("Inknown chip ID")
sys.exit(-1)

chipsize = chip[2] * 1024
print("Manufacturer %s " % GetManufacturerName(jedec_id))
print("Chip: %s" % chip[0])
print("Size: %dKB" % chip[2])

# Setup flash command codes
SetupChipCommands (jedec_id,pr)

b = spir.SPICommonCommand(E_CC_READ, 0x5, 1, 0, 0)

print("Flash status register: 0x%x" % (b))

if save:
print "Save dump to %s" % ofile
print("Save dump to %s" % ofile)
SaveFlash(ofile, chipsize, spir)

if erase:
EraseFlash(pr)

if write:
print "Flashing %s" % infile
print("Flashing %s" % infile)
ProgramFlash(infile, chipsize, pr)


Expand Down