-
Notifications
You must be signed in to change notification settings - Fork 1
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
Programming CC430F6137 With MSP-FET430UIF Ubuntu #1
Comments
For my CC430F6137 project, I've been using the BSL rather than JTAG programming. I wasn't able to get any publicly available BSL clients to work, so I wrote the following client which works reliably up to 38400 baud. (I use the upper half of SRAM, which is unprotected by the BSL, as a dmesg buffer for failure analysis, so ignore anything referencing 'dmesg' in your own designs. Intel Hex checksums are shotgun parsed and not verified.) 73 from Pizza Rat City, #!/usr/bin/python2
## This is a quick and dirty BSL client by Travis Goodspeed for the
## CC430F6137, written out of frustration when another tool generated
## bad checksums. It is free for any use, provided you tip your
## bartender.
import serial, time, sys, argparse, progressbar;
class BSL:
def __init__(self, port):
#print("Opening %s" % port);
self.serial=serial.Serial(port,
baudrate=9600,
parity=serial.PARITY_EVEN,
stopbits=serial.STOPBITS_ONE,
timeout=1);
#Low level functions first.
def setTST(self,level):
"""Sets the TST pin."""
self.serial.setRTS(level)
time.sleep(0.01);
def setRST(self,level):
"""Sets the !RST pin."""
self.serial.setDTR(level);
time.sleep(0.01);
def enter_bsl(self):
"""Activates the bootloader by the sequence in SLAU319N."""
self.setRST(False)
self.setTST(False)
time.sleep(0.250)
self.setRST(True)
#Minimum two rising edges are required, but it helps to have three or more.
self.setTST(False)
self.setTST(True)
self.setTST(False)
self.setTST(True)
self.setTST(False)
self.setTST(True)
self.setTST(False)
self.setTST(True)
self.setRST(False)
self.setTST(False)
time.sleep(0.250)
self.serial.flushInput();
def reset(self):
"""Exits the BSL by resetting the chip."""
self.setTST(True)
self.setRST(True);
self.setRST(False);
self.setRST(True);
def crc(self,msg):
"""Returns a two-byte string of the checksum of a message."""
crc=0xFFFF
#msg should already include header bytes.
for char in msg:
byte=ord(char)
x=((crc>>8)^byte)&0xFF;
x^=x>>4;
crc=(crc<<8)^(x<<12)^(x<<5)^x;
return chr(crc&0xFF)+""+chr((crc>>8)&0xFF);
def transact(self,msg):
"""Sends a message, wrapped with a prefix and checksum.
Result's wrapper is stripped."""
#Send the message.
length=len(msg);
ll=chr(length&0xFF);
lh=chr((length>>8)&0xFF);
crc=self.crc(msg);
self.serial.write("\x80"+ll+lh+msg+crc);
#Get the reply.
reply=self.serial.read(1);
if len(reply)!=1:
print "Error, missing reply.";
sys.exit(1);
elif msg[0]=='\x52':
#Change baud rate command has a briefer reply.
pass;
elif ord(reply[0])==0x00:
#Success
eighty=ord(self.serial.read(1));
ll=ord(self.serial.read(1)[0]);
lh=ord(self.serial.read(1)[0]);
length=ll|(lh<<8);
rep=self.serial.read(length);
crc=self.serial.read(2);
assert(crc==self.crc(rep));
return rep;
else:
print "Error 0x%02x." % ord(reply[0]);
#Not sure whether data is coming, so grab a chunk just in case.
self.serial.read(10);
def unlock(self,
password=None):
"""Unlocks the bootloader, optionally with a password."""
#Password must be 32 bytes; read from a file otherwise.
if password==None:
password="\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
if len(password)!=32:
password=self.passwordfromfile(password);
assert(len(password)==32);
resp=self.transact("\x11"+password);
assert(len(resp)==2);
assert(resp[0]=='\x3b');
code=ord(resp[1]);
if code==0x05:
print "Incorrect password. Flash was erased."
return self.unlock();
elif code==0x00:
#success
return True;
else:
print "Unexpected password core message 0x%02x."%code;
return False;
def version(self):
"""Gets the BSL version and related bytes."""
resp=self.transact("\x19");
assert(len(resp)==5);
vendor=ord(resp[1]); # 0 for TI
interpreter=ord(resp[2]);
api=ord(resp[3]); # 0 for flash, 30 for sram, 80 for restricted cmd set
peripheral=ord(resp[4]);
return vendor, interpreter, api, peripheral;
def masserase(self):
"""Bulk erases the device."""
resp=self.transact("\x15");
assert resp=="\x3b\x00"
def read(self,adr,length=32):
"""Dumps memory from the given address."""
al=chr(adr&0xFF)
am=chr((adr>>8)&0xFF)
ah=chr((adr>>16)&0xFF)
ll=chr(length&0xFF)
lh=chr((length>>8)&0xFF)
resp=self.transact("\x18"+al+am+ah+ll+lh)
if resp[0]=="\x3b":
print "Error: You need to unlock before reading."
assert(resp[0]=="\x3a");
return resp[1:]
def write(self,adr,data=""):
"""Writes memory to the given address."""
al=chr(adr&0xFF)
am=chr((adr>>8)&0xFF)
ah=chr((adr>>16)&0xFF)
resp=self.transact("\x10"+al+am+ah+data)
return resp[1:]
def erasesegment(self,adr):
"""Erases one segment of Flash at a given address."""
al=chr(adr&0xFF)
am=chr((adr>>8)&0xFF)
ah=chr((adr>>16)&0xFF)
resp=self.transact("\x12"+al+am+ah)
return resp[1:]
def unlocklockinfo(self):
"""Unlocks or locks Info FLash."""
resp=self.transact("\x13")
return resp[1:]
def loadpc(self,adr):
"""Begins execution at a given address."""
al=chr(adr&0xFF)
am=chr((adr>>8)&0xFF)
ah=chr((adr>>16)&0xFF)
resp=self.transact("\x17"+al+am+ah)
return resp[1:]
def setbaud(self,rate=9600):
"""Sets the baud rate."""
#First we inform the BSL of the rate.
if rate==9600:
ratebyte='\x02';
elif rate==19200:
ratebyte='\x03';
elif rate==38400:
ratebyte='\x04';
elif rate==57600:
ratebyte='\x05';
elif rate==115200:
ratebyte='\x06';
#Command the rate change.
resp=self.transact("\x52"+ratebyte);
#Then we jump the port to the new rate.
#self.serial.setBaudrate(rate); #Old convention.
self.serial.baudrate=rate; #New convention.
MAXLEN=256; #Maximum bytes per read request.
def readbulk(self,adr,length):
"""Reads a large volume from the target, in multiple transactions."""
i=adr;
buf="";
while i<adr+length:
buf=buf+self.read(i,min(self.MAXLEN,adr+length-i));
i=adr+len(buf);
assert(len(buf)==length);
return buf;
def writebulk(self,adr,data):
"""Writes a large volume to the target, in multiple transactions."""
length=len(data);
i=adr;
while i<adr+length:
thislength=min(self.MAXLEN,adr+length-i);
self.write(i,data[i-adr:i-adr+thislength]);
i=i+thislength;
#assert(i==adr+length);
return True;
def writeihexline(self,line):
"""Writes one line of an Intel Hex file. (Langsec sin!)"""
assert(line[0]==':');
length=int(line[1:3],16);
adr=int(line[3:7],16);
verb=int(line[7:9],16);
data=line[9:(9+length*2)].decode('hex');
if verb==0: #Data
self.write(adr,data);
def writeihexfile(self,filename):
"""Writes an Intel Hex file to the CC430."""
bar=progressbar.ProgressBar();
f=open(filename,'r');
lines=f.readlines();
for l in bar(lines):
self.writeihexline(l.strip());
def handlepasswordline(self,line):
"""Returns a password fragment from the line, if available."""
assert(line[0]==':');
length=int(line[1:3],16);
adr=int(line[3:7],16);
verb=int(line[7:9],16);
data=line[9:(9+length*2)].decode('hex');
if verb==0 and adr>=0xFFE0:
#Return the password bytes from this line.
return data;
#Empty string by default.
return "";
def passwordfromfile(self,filename):
"""Returns the password from an ihex file, for unlocking."""
f=open(filename,'r');
lines=f.readlines();
password="";
for l in lines:
password+=self.handlepasswordline(l);
return password;
def coredump(bsl):
"""Prints all of memory."""
print "\n\n\nDumping most of memory as a read test.";
##Dump the BSL
bulk=bsl.readbulk(0x1000,2048)
print "Got %d bytes of the BSL." % len(bulk);
print bulk.encode('hex');
##Dump Info
bulk=bsl.readbulk(0x1800,512)
print "Got %d bytes of Info Flash." % len(bulk);
print bulk.encode('hex');
##Dump RAM
bulk=bsl.readbulk(0x1C00,4096)
print "Got %d bytes of RAM." % len(bulk);
print bulk.encode('hex');
##Dump ROM
print "Dumping Flash ROM. Please be patient."
bulk=bsl.readbulk(0x8000,32*1024)
print "Got %d bytes of Flash ROM." % len(bulk);
print bulk.encode('hex');
def dmesg(bsl):
"""Prints the dmesg buffer."""
##Dump RAM
bulk=bsl.readbulk(0x2400,2048)
print bulk;
def writetest(bsl):
"""Tests writing an image to Flash."""
print "\n\n\nMass erasing, then performing a write test.";
bsl.masserase();
msg="Hello world! Hogy vagy? Jo vagyok!"*35
bsl.writebulk(0x8000,msg);
readmsg=bsl.readbulk(0x8000,len(msg));
print "Wrote: %s" % msg.encode('hex');
print "Read: %s" % readmsg.encode('hex');
assert(readmsg==msg);
if __name__=='__main__':
parser = argparse.ArgumentParser(description='CC430F6137 BSL Client')
parser.add_argument('-e','--erase', help='Mass Erase (w/o Info)',action='count');
parser.add_argument('-E','--eraseinfo', help='Mass Erase (w/ Info)',action='count');
parser.add_argument('-p','--port',
help='Serial Port',default='/dev/ttyUSB0');
parser.add_argument('-f','--file', help='Flash File');
parser.add_argument('-P','--password', help='Password File or Hex');
parser.add_argument('-d','--dump',
help='Produce a core dump.',action='count');
parser.add_argument('-D','--dmesg',
help='Prints the dmesg.',action='count');
parser.add_argument('-u','--unlock',
help='Unlock BSL.',action='count');
parser.add_argument('-t','--time',
help='Set the Time.',action='count');
parser.add_argument('-r','--rate',
help='Baud Rate', default=9600);
args = parser.parse_args()
bsl=BSL(args.port);
bsl.enter_bsl();
if int(args.rate)!=9600:
print("Setting baud rate to %d"% int(args.rate));
bsl.setbaud(int(args.rate));
if args.erase!=None:
print "Mass erasing."
bsl.masserase();
bsl.unlock();
if args.eraseinfo!=None:
print "Mass erasing, plus Info."
bsl.masserase();
bsl.unlock();
#We don't need to call unlocklockinfo() because we are
#targetting the banks directly.
bsl.erasesegment(0x1800);
bsl.erasesegment(0x1880);
bsl.erasesegment(0x1900);
bsl.erasesegment(0x1980);
if args.unlock!=None:
#print "Unlocking."
bsl.unlock(args.password);
if args.file!=None:
print "Writing %s as Intel hex." % args.file
bsl.writeihexfile(args.file);
if args.time!=None:
lt=time.localtime()
#See firmware/rtc.c for the format.
timestr=(
#Hour, Minute, Second first.
chr(lt.tm_hour)+chr(lt.tm_min)+chr(lt.tm_sec)+"\xFF"+
#u16 Year, u8 Month, u8 Day
chr(lt.tm_year&0xFF)+chr(lt.tm_year>>8)+chr(lt.tm_mon)+chr(lt.tm_mday)
);
bsl.write(0xFF00,timestr);
if args.dump!=None:
coredump(bsl);
if args.dmesg!=None:
dmesg(bsl);
bsl.reset(); |
Thank you Travis! I'll give this a shot later today. I was wondering if bsl
was a good way forward although this means I lose the ability to debug
right? That's something I'm not use to but especially with RIOT I may not
need debugging functionality since I could get console output...
Thanks!!!
…On Dec 7, 2017 11:41, "Travis Goodspeed" ***@***.***> wrote:
For my CC430F6137 project, I've been using the BSL rather than JTAG
programming.
I wasn't able to get any publicly available BSL clients to work, so I
wrote the following client which works reliably up to 38400 baud. (I use
the upper half of SRAM, which is unprotected by the BSL, as a dmesg buffer
for failure analysis, so ignore anything referencing 'dmesg' in your own
designs. Intel Hex checksums are shotgun parsed and not verified.)
73 from Pizza Rat City,
--Travis
#!/usr/bin/python2
## This is a quick and dirty BSL client by Travis Goodspeed for the## CC430F6137, written out of frustration when another tool generated## bad checksums. It is free for any use, provided you tip your## bartender.
import serial, time, sys, argparse, progressbar;
class BSL:
def __init__(self, port):
#print("Opening %s" % port);
self.serial=serial.Serial(port,
baudrate=9600,
parity=serial.PARITY_EVEN,
stopbits=serial.STOPBITS_ONE,
timeout=1);
#Low level functions first.
def setTST(self,level):
"""Sets the TST pin."""
self.serial.setRTS(level)
time.sleep(0.01);
def setRST(self,level):
"""Sets the !RST pin."""
self.serial.setDTR(level);
time.sleep(0.01);
def enter_bsl(self):
"""Activates the bootloader by the sequence in SLAU319N."""
self.setRST(False)
self.setTST(False)
time.sleep(0.250)
self.setRST(True)
#Minimum two rising edges are required, but it helps to have three or more.
self.setTST(False)
self.setTST(True)
self.setTST(False)
self.setTST(True)
self.setTST(False)
self.setTST(True)
self.setTST(False)
self.setTST(True)
self.setRST(False)
self.setTST(False)
time.sleep(0.250)
self.serial.flushInput();
def reset(self):
"""Exits the BSL by resetting the chip."""
self.setTST(True)
self.setRST(True);
self.setRST(False);
self.setRST(True);
def crc(self,msg):
"""Returns a two-byte string of the checksum of a message."""
crc=0xFFFF
#msg should already include header bytes.
for char in msg:
byte=ord(char)
x=((crc>>8)^byte)&0xFF;
x^=x>>4;
crc=(crc<<8)^(x<<12)^(x<<5)^x;
return chr(crc&0xFF)+""+chr((crc>>8)&0xFF);
def transact(self,msg):
"""Sends a message, wrapped with a prefix and checksum. Result's wrapper is stripped."""
#Send the message.
length=len(msg);
ll=chr(length&0xFF);
lh=chr((length>>8)&0xFF);
crc=self.crc(msg);
self.serial.write("\x80"+ll+lh+msg+crc);
#Get the reply.
reply=self.serial.read(1);
if len(reply)!=1:
print "Error, missing reply.";
sys.exit(1);
elif msg[0]=='\x52':
#Change baud rate command has a briefer reply.
pass;
elif ord(reply[0])==0x00:
#Success
eighty=ord(self.serial.read(1));
ll=ord(self.serial.read(1)[0]);
lh=ord(self.serial.read(1)[0]);
length=ll|(lh<<8);
rep=self.serial.read(length);
crc=self.serial.read(2);
assert(crc==self.crc(rep));
return rep;
else:
print "Error 0x%02x." % ord(reply[0]);
#Not sure whether data is coming, so grab a chunk just in case.
self.serial.read(10);
def unlock(self,
password=None):
"""Unlocks the bootloader, optionally with a password."""
#Password must be 32 bytes; read from a file otherwise.
if password==None:
password="\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
if len(password)!=32:
password=self.passwordfromfile(password);
assert(len(password)==32);
resp=self.transact("\x11"+password);
assert(len(resp)==2);
assert(resp[0]=='\x3b');
code=ord(resp[1]);
if code==0x05:
print "Incorrect password. Flash was erased."
return self.unlock();
elif code==0x00:
#success
return True;
else:
print "Unexpected password core message 0x%02x."%code;
return False;
def version(self):
"""Gets the BSL version and related bytes."""
resp=self.transact("\x19");
assert(len(resp)==5);
vendor=ord(resp[1]); # 0 for TI
interpreter=ord(resp[2]);
api=ord(resp[3]); # 0 for flash, 30 for sram, 80 for restricted cmd set
peripheral=ord(resp[4]);
return vendor, interpreter, api, peripheral;
def masserase(self):
"""Bulk erases the device."""
resp=self.transact("\x15");
assert resp=="\x3b\x00"
def read(self,adr,length=32):
"""Dumps memory from the given address."""
al=chr(adr&0xFF)
am=chr((adr>>8)&0xFF)
ah=chr((adr>>16)&0xFF)
ll=chr(length&0xFF)
lh=chr((length>>8)&0xFF)
resp=self.transact("\x18"+al+am+ah+ll+lh)
if resp[0]=="\x3b":
print "Error: You need to unlock before reading."
assert(resp[0]=="\x3a");
return resp[1:]
def write(self,adr,data=""):
"""Writes memory to the given address."""
al=chr(adr&0xFF)
am=chr((adr>>8)&0xFF)
ah=chr((adr>>16)&0xFF)
resp=self.transact("\x10"+al+am+ah+data)
return resp[1:]
def erasesegment(self,adr):
"""Erases one segment of Flash at a given address."""
al=chr(adr&0xFF)
am=chr((adr>>8)&0xFF)
ah=chr((adr>>16)&0xFF)
resp=self.transact("\x12"+al+am+ah)
return resp[1:]
def unlocklockinfo(self):
"""Unlocks or locks Info FLash."""
resp=self.transact("\x13")
return resp[1:]
def loadpc(self,adr):
"""Begins execution at a given address."""
al=chr(adr&0xFF)
am=chr((adr>>8)&0xFF)
ah=chr((adr>>16)&0xFF)
resp=self.transact("\x17"+al+am+ah)
return resp[1:]
def setbaud(self,rate=9600):
"""Sets the baud rate."""
#First we inform the BSL of the rate.
if rate==9600:
ratebyte='\x02';
elif rate==19200:
ratebyte='\x03';
elif rate==38400:
ratebyte='\x04';
elif rate==57600:
ratebyte='\x05';
elif rate==115200:
ratebyte='\x06';
#Command the rate change.
resp=self.transact("\x52"+ratebyte);
#Then we jump the port to the new rate.
#self.serial.setBaudrate(rate); #Old convention.
self.serial.baudrate=rate; #New convention.
MAXLEN=256; #Maximum bytes per read request.
def readbulk(self,adr,length):
"""Reads a large volume from the target, in multiple transactions."""
i=adr;
buf="";
while i<adr+length:
buf=buf+self.read(i,min(self.MAXLEN,adr+length-i));
i=adr+len(buf);
assert(len(buf)==length);
return buf;
def writebulk(self,adr,data):
"""Writes a large volume to the target, in multiple transactions."""
length=len(data);
i=adr;
while i<adr+length:
thislength=min(self.MAXLEN,adr+length-i);
self.write(i,data[i-adr:i-adr+thislength]);
i=i+thislength;
#assert(i==adr+length);
return True;
def writeihexline(self,line):
"""Writes one line of an Intel Hex file. (Langsec sin!)"""
assert(line[0]==':');
length=int(line[1:3],16);
adr=int(line[3:7],16);
verb=int(line[7:9],16);
data=line[9:(9+length*2)].decode('hex');
if verb==0: #Data
self.write(adr,data);
def writeihexfile(self,filename):
"""Writes an Intel Hex file to the CC430."""
bar=progressbar.ProgressBar();
f=open(filename,'r');
lines=f.readlines();
for l in bar(lines):
self.writeihexline(l.strip());
def handlepasswordline(self,line):
"""Returns a password fragment from the line, if available."""
assert(line[0]==':');
length=int(line[1:3],16);
adr=int(line[3:7],16);
verb=int(line[7:9],16);
data=line[9:(9+length*2)].decode('hex');
if verb==0 and adr>=0xFFE0:
#Return the password bytes from this line.
return data;
#Empty string by default.
return "";
def passwordfromfile(self,filename):
"""Returns the password from an ihex file, for unlocking."""
f=open(filename,'r');
lines=f.readlines();
password="";
for l in lines:
password+=self.handlepasswordline(l);
return password;
def coredump(bsl):
"""Prints all of memory."""
print "\n\n\nDumping most of memory as a read test.";
##Dump the BSL
bulk=bsl.readbulk(0x1000,2048)
print "Got %d bytes of the BSL." % len(bulk);
print bulk.encode('hex');
##Dump Info
bulk=bsl.readbulk(0x1800,512)
print "Got %d bytes of Info Flash." % len(bulk);
print bulk.encode('hex');
##Dump RAM
bulk=bsl.readbulk(0x1C00,4096)
print "Got %d bytes of RAM." % len(bulk);
print bulk.encode('hex');
##Dump ROM
print "Dumping Flash ROM. Please be patient."
bulk=bsl.readbulk(0x8000,32*1024)
print "Got %d bytes of Flash ROM." % len(bulk);
print bulk.encode('hex');
def dmesg(bsl):
"""Prints the dmesg buffer."""
##Dump RAM
bulk=bsl.readbulk(0x2400,2048)
print bulk;
def writetest(bsl):
"""Tests writing an image to Flash."""
print "\n\n\nMass erasing, then performing a write test.";
bsl.masserase();
msg="Hello world! Hogy vagy? Jo vagyok!"*35
bsl.writebulk(0x8000,msg);
readmsg=bsl.readbulk(0x8000,len(msg));
print "Wrote: %s" % msg.encode('hex');
print "Read: %s" % readmsg.encode('hex');
assert(readmsg==msg);
if __name__=='__main__':
parser = argparse.ArgumentParser(description='CC430F6137 BSL Client')
parser.add_argument('-e','--erase', help='Mass Erase (w/o Info)',action='count');
parser.add_argument('-E','--eraseinfo', help='Mass Erase (w/ Info)',action='count');
parser.add_argument('-p','--port',
help='Serial Port',default='/dev/ttyUSB0');
parser.add_argument('-f','--file', help='Flash File');
parser.add_argument('-P','--password', help='Password File or Hex');
parser.add_argument('-d','--dump',
help='Produce a core dump.',action='count');
parser.add_argument('-D','--dmesg',
help='Prints the dmesg.',action='count');
parser.add_argument('-u','--unlock',
help='Unlock BSL.',action='count');
parser.add_argument('-t','--time',
help='Set the Time.',action='count');
parser.add_argument('-r','--rate',
help='Baud Rate', default=9600);
args = parser.parse_args()
bsl=BSL(args.port);
bsl.enter_bsl();
if int(args.rate)!=9600:
print("Setting baud rate to %d"% int(args.rate));
bsl.setbaud(int(args.rate));
if args.erase!=None:
print "Mass erasing."
bsl.masserase();
bsl.unlock();
if args.eraseinfo!=None:
print "Mass erasing, plus Info."
bsl.masserase();
bsl.unlock();
#We don't need to call unlocklockinfo() because we are
#targetting the banks directly.
bsl.erasesegment(0x1800);
bsl.erasesegment(0x1880);
bsl.erasesegment(0x1900);
bsl.erasesegment(0x1980);
if args.unlock!=None:
#print "Unlocking."
bsl.unlock(args.password);
if args.file!=None:
print "Writing %s as Intel hex." % args.file
bsl.writeihexfile(args.file);
if args.time!=None:
lt=time.localtime()
#See firmware/rtc.c for the format.
timestr=(
#Hour, Minute, Second first.
chr(lt.tm_hour)+chr(lt.tm_min)+chr(lt.tm_sec)+"\xFF"+
#u16 Year, u8 Month, u8 Day
chr(lt.tm_year&0xFF)+chr(lt.tm_year>>8)+chr(lt.tm_mon)+chr(lt.tm_mday)
);
bsl.write(0xFF00,timestr);
if args.dump!=None:
coredump(bsl);
if args.dmesg!=None:
dmesg(bsl);
bsl.reset();
—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
<kb1lqd#1 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAUsyA9YWekbq-nOzpfVzj6eQwkBIUrYks5s-D9wgaJpZM4Q5s_z>
.
|
Forgot the leave a pinout in the comments:
|
Thanks @travisgoodspeed ! If you have any comments on the following that would be appreciated. I believe I have a decent plan located at the end to get this working for Faraday but does need .dll files as currently known to execute to toggle RST and TST pins. @kb1lqc for awareness. Relevant information for conversion of the BSL program you provided for use with Faraday is below. This will not be super straightforward due to the use of RST and TST pins of the CC430 being controlled by CBUS pins from the FTDI. UART-RX: P1.5 (device) RST and TEST pins on the CC430 are connected to the FTDI CBUS pins CBUS0: !RST This is controllable through the FTDI program I created a FTDI python wrapper script for the .DLL provided by FTDI to control the CBUS status in the original (windows only, due to to the TI .exe file for BSL) located: https://github.com/FaradayRF/Faraday-Software/blob/master/Firmware_Bootstrap_Loader/faradaybsl/faradayftdi.py As long as I can run this CBUS control wrapper that interfaces to a .DLL file in linux this should be easy to implement... Tasks
|
OK I'm looking to use http://pylibftdi.readthedocs.io/en/0.15.0/quickstart.html#install-pylibftdi It supports the FT-230X and GPIO: https://www.intra2net.com/en/developer/libftdi/index.php I created and added the rule for the usb vendor:device:
I'm currently getting no response from the "list devices". Below shows how to reload the rules. http://notebook.chaopricha.com/?m=201607 brent@brent-580-005t:~/Git/kb1lqd/faradayio/tools$ sudo udevadm control --reload-rules My user LIsting out a Faraday FTDI attributes:
OK I think I found a clue! The id of the product is
# Opening / searching for a device uses this list of IDs to search
# by default. These can be extended directly after import if required.
FTDI_VENDOR_ID = 0x0403
USB_VID_LIST = [FTDI_VENDOR_ID]
USB_PID_LIST = [0x6001, 0x6010, 0x6011, 0x6014] Literally PylibFTDI also mentions this addition of new vendor product ID's is needed: http://pylibftdi.readthedocs.io/en/0.15.0/how_to.html I added to the pylibftdi example script from pylibftdi import USB_PID_LIST
USB_PID_LIST.append(0x6015) Success! brent@brent-580-005t:/usr/local/lib/python2.7/dist-packages/pylibftdi/examples$ sudo python -m pylibftdi/examples/list_devices
FaradayRF:Faraday:18 |
I made a working program that adds PID's to brent@brent-580-005t:~/Git/kb1lqd/faradayio/tools$ sudo python pylibftdi-add-pid-example.py
Imported USB_PID_LIST: ['0x6001', '0x6010', '0x6011', '0x6014']
Updated USB_PID_LIST: ['0x6001', '0x6010', '0x6011', '0x6014', '0x6015']
[('FaradayRF', 'Faraday', '48')]
Devices: FaradayRF:Faraday:48
Source: https://github.com/kb1lqd/faradayio/blob/master/tools/pylibftdi-add-pid-example.py """
A quick dirty pylibftdi implementation of adding an FT230X vendor product
ID to the pylibftdi valid ID list. Run as sudo or with proper USB permissions.
The program will simply list out connected devices as long as thier product ID's
are in the valid list. This is a copy of the list_devices pylibftdi example
except exampled is actively adding new ID's.
"""
import pylibftdi
def get_ftdi_device_list():
"""
return a list of lines, each a colon-separated
vendor:product:serial summary of detected devices
"""
dev_list = []
for device in pylibftdi.Driver().list_devices():
# list_devices returns bytes rather than strings
dev_info = map(lambda x: x.decode('latin1'), device)
# device must always be this triple
vendor, product, serial = dev_info
dev_list.append("%s:%s:%s" % (vendor, product, serial))
return dev_list
def main():
# Print as imported USB_PID_LIST
print "Imported USB_PID_LIST:", map(hex,pylibftdi.USB_PID_LIST)
# Append new USB PID number to the USB_PID_LIST
pylibftdi.USB_PID_LIST.append(0x6015)
# Print updated USB_PID_LIST
print "Updated USB_PID_LIST:", map(hex,pylibftdi.USB_PID_LIST)
print pylibftdi.Driver().list_devices()
for device in get_ftdi_device_list():
print "Devices:", (device)
if __name__ == "__main__":
main() |
Opening A DeviceApparently the serial number of the device is used to OPEN it as a class object: pylibftdi Issues 12/13/17I seem to be able to query for the device but either leaving the device blank or using serial number I get an error saying the device cannot be found. brent@brent-580-005t:~/Git/kb1lqd/faradayio/tools$ python faraday_ftdi_gpio.py
Traceback (most recent call last):
File "faraday_ftdi_gpio.py", line 5, in <module>
test = BitBangDevice()
File "/usr/local/lib/python2.7/dist-packages/pylibftdi/bitbang.py", line 60, in __init__
self.open()
File "/usr/local/lib/python2.7/dist-packages/pylibftdi/bitbang.py", line 66, in open
super(BitBangDevice, self).open()
File "/usr/local/lib/python2.7/dist-packages/pylibftdi/device.py", line 156, in open
raise FtdiError(msg)
pylibftdi._base.FtdiError: device not found (-3) Querying the pylibftdi version I see odd messages: >>> from pylibftdi import driver
>>> driver.Driver().libftdi_version()
libftdi_version(major=0, minor=0, micro=0, version_str='< 1.0 - no ftdi_get_library_version()', snapshot_str='unknown') |
Similar bug for windows that went unanswered: https://bitbucket.org/codedstructure/pylibftdi/issues/26/device-not-found-error-3-windows-10 Wait, got it (I Think) this issue reported and worked on indicates standard Ubuntu 16.04 libftdi causes the error and building a new build newer than the ubuntu repo's is needed. https://bitbucket.org/codedstructure/pylibftdi/issues/25/using-bitbangdevice-causes-segmentation OK! So looks like I had installed Prior (
Post (
Although I haven't gotten the GPIO CBUS outputs to change I do see a working BitBang device connection! I need to have the PID added for the FT230X but now I can connect:
Note that BitBangDevice() assumes the first found device is used (not including the PID addition causes device not found). using @kb1lqc and @travisgoodspeed for awareness. Just need to figure out how to toggle CBUS in bitbang now that I can connect! |
OK so I decided to dive into learning C development for non-embedded platforms and created this simple C program that directly uses https://github.com/kb1lqd/faradayio/blob/master/c_tools/cbus_toggle_1/main.c |
Yeah @kb1lqd this seems good. At some point just do what you need to make progress in a reasonable manner. |
OK so I'm ready to enable BSL mode and program a HEX file onto the CC430. I'd like to us mspgcc to compile and then use a modified version of @travisgoodspeed BSL program above that using my C program for toggling CBUS lines for BSL mode entry/exit. The python BSL program above from Travis needs an Also, TI seems to have a converter tool? http://downloads.ti.com/docs/esd/SLAU131K/Content/SLAU131K_HTML/hex_conversion_utility_description.html This webpage seems to detail how to compile and create an ihex file from mspgcc: http://mylightswitch.com/2010/08/12/compiling-the-first-program/ |
Binutils will happily do the conversion, or the TI format is easy enough to parse. Here's how the GoodWatch firmware is built and flashed with GCC. |
Thanks @travisgoodspeed ! I created a HEX file but then ran into a After using libftdi to connect and bitbang the CBUS pins on disconnect the
This causes your python script to error when it tries to send over the serial line: ...
DISABLECBUS0: CBUS Bitmask = 0x30
ENABLECBUS1: CBUS Bitmask = 0x32
CBUS Bitmask = 0x32
ENABLECBUS0: CBUS Bitmask = 0x33
ENABLECBUS1: CBUS Bitmask = 0x33
CBUS Bitmask = 0x33
ENABLECBUS0: CBUS Bitmask = 0x33
DISABLECBUS1: CBUS Bitmask = 0x31
CBUS Bitmask = 0x31
CBUS Direction Bitmask = 0x00
disabling bitbang mode
Mass erasing, plus Info.
Traceback (most recent call last):
File "travisgoodspeeddirtybsl.py", line 343, in <module>
bsl.masserase();
File "travisgoodspeeddirtybsl.py", line 131, in masserase
resp=self.transact("\x15");
File "travisgoodspeeddirtybsl.py", line 64, in transact
self.serial.write("\x80"+ll+lh+msg+crc);
File "/usr/local/lib/python2.7/dist-packages/serial/serialposix.py", line 571, in write
raise SerialException('write failed: {}'.format(e))
serial.serialutil.SerialException: write failed: [Errno 5] Input/output error
brent@brent-580-005t:~/Git/kb1lqd/faradayio/Faraday_BSL$ @travisgoodspeed Do you know of a suggestion here? It seems like that link I provided with the known libftdi disconnect error has a diff patch, I'm not familiar at all with these but I imagine there's got a to be a more stable and portable way to solve this problem after 2 years? Reconnect signal? Thanks! |
It's probably cleanest for you to import or rewrite my BSL client into your libftdi client, rather than trying to use the chip with two different drivers for a single transaction. |
I am having issues connecting to and using the MSP-FET430UIF on Ubuntu. I can't seem to communicate with the device using mspdebug.
Immediate Programming Options
The text was updated successfully, but these errors were encountered: