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

Programming CC430F6137 With MSP-FET430UIF Ubuntu #1

Open
kb1lqd opened this issue Dec 7, 2017 · 15 comments
Open

Programming CC430F6137 With MSP-FET430UIF Ubuntu #1

kb1lqd opened this issue Dec 7, 2017 · 15 comments
Assignees

Comments

@kb1lqd
Copy link
Collaborator

kb1lqd commented Dec 7, 2017

I am having issues connecting to and using the MSP-FET430UIF on Ubuntu. I can't seem to communicate with the device using mspdebug.

image

Immediate Programming Options

@kb1lqd kb1lqd self-assigned this Dec 7, 2017
@travisgoodspeed
Copy link

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();

@kb1lqd
Copy link
Collaborator Author

kb1lqd commented Dec 7, 2017 via email

@travisgoodspeed
Copy link

Forgot the leave a pinout in the comments:

DTR to !RST
RTS to TST
P1.5 is device RX, host TX.
P1.6 is device TX, host RX.

@kb1lqd
Copy link
Collaborator Author

kb1lqd commented Dec 12, 2017

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)
UART-TX: P1.6 (device)

image

RST and TEST pins on the CC430 are connected to the FTDI CBUS pins

image

CBUS0: !RST
CBUS1: TST

This is controllable through the FTDI program FT_PROG to GPIO and other outputs. Unfortunately making a CBUS pin a !RST or DTR pin doesn't look directly possible.

image

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

@kb1lqd
Copy link
Collaborator Author

kb1lqd commented Dec 13, 2017

OK I'm looking to use pylibftdi to communicate with the FT-230X on Faraday and control the CBUS GPIO.

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:

SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6015", GROUP="dialout", MODE="0660"

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 brent is a member of group dialout for proper serial/usb permissions.

LIsting out a Faraday FTDI attributes:

 looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-1':
    KERNELS=="1-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{authorized}=="1"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bMaxPacketSize0}=="8"
    ATTRS{bMaxPower}=="500mA"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bcdDevice}=="1000"
    ATTRS{bmAttributes}=="80"
    ATTRS{busnum}=="1"
    ATTRS{configuration}==""
    ATTRS{devnum}=="7"
    ATTRS{devpath}=="1"
    ATTRS{idProduct}=="6015"
    ATTRS{idVendor}=="0403"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="FaradayRF"
    ATTRS{maxchild}=="0"
    ATTRS{product}=="Faraday"
    ATTRS{quirks}=="0x0"
    ATTRS{removable}=="removable"
    ATTRS{serial}=="18"
    ATTRS{speed}=="12"
    ATTRS{urbnum}=="17"
    ATTRS{version}==" 2.00"

OK I think I found a clue! The id of the product is 6015 and it is not in the valid ID list in:

/usr/local/lib/python2.7/dist-packages/pylibftdi/driver.py

# 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]

https://stackoverflow.com/questions/31143376/failed-to-connect-ft232rl-device-with-pylibftdi-thorlabs-apt-dc-motor-controlle

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 list_devices.py after the import of the pylibftdi class (this is NOT a long term solution, but a method to solve by adding to the ID number of the FT-230X):

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

@kb1lqd
Copy link
Collaborator Author

kb1lqd commented Dec 14, 2017

I made a working program that adds PID's to pylibftdi and queries for local units connected!

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

@kb1lqd
Copy link
Collaborator Author

kb1lqd commented Dec 14, 2017

Opening A Device

Apparently the serial number of the device is used to OPEN it as a class object:

image

pylibftdi Issues 12/13/17

I 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')

@kb1lqd
Copy link
Collaborator Author

kb1lqd commented Dec 19, 2017

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 libftdi-dev which is legacy and removing and installing libftdi1-dev looks promising.

Prior (libftdi-dev)

brent@brent-580-005t:~/Git/kb1lqd/faradayio/tools$ python -m pylibftdi.examples.info
pylibftdi version     : 0.16.1.2
libftdi version       : libftdi_version(major=0, minor=0, micro=0, version_str='< 1.0 - no ftdi_get_library_version()', snapshot_str='unknown')
libftdi library name  : libftdi.so.1
libusb version        : libusb_version(major=1, minor=0, micro=20, nano=11004, rc='', describe='http://libusb.info')
libusb library name   : libusb-1.0.so.0
Python version        : 2.7.12
OS platform           : Linux-4.10.0-42-generic-x86_64-with-Ubuntu-16.04-xenial

Post (libftdi1-dev)

brent@brent-580-005t:~/Git/kb1lqd/faradayio/tools$ python -m pylibftdi.examples.info
pylibftdi version     : 0.16.1.2
libftdi version       : libftdi_version(major=1, minor=2, micro=0, version_str='1.2', snapshot_str='unknown')
libftdi library name  : libftdi1.so.2
libusb version        : libusb_version(major=1, minor=0, micro=20, nano=11004, rc='', describe='http://libusb.info')
libusb library name   : libusb-1.0.so.0
Python version        : 2.7.12
OS platform           : Linux-4.10.0-42-generic-x86_64-with-Ubuntu-16.04-xenial

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:

from pylibftdi import BitBangDevice
from pylibftdi import driver

# Append new USB PID number to the USB_PID_LIST
driver.USB_PID_LIST.append(0x6015)

with BitBangDevice() as bb:
    bb.direction = 0x00
    bb.port &= 0xFF
    #bb.port |= 0xFF

print "Completed."

Note that BitBangDevice() assumes the first found device is used (not including the PID addition causes device not found). using BitBangDevice('serialnumber') where the FTDI device serial number is used selects a specific device.

@kb1lqc and @travisgoodspeed for awareness. Just need to figure out how to toggle CBUS in bitbang now that I can connect!

@kb1lqd
Copy link
Collaborator Author

kb1lqd commented Jan 4, 2018

@kb1lqd
Copy link
Collaborator Author

kb1lqd commented Jan 8, 2018

OK so I decided to dive into learning C development for non-embedded platforms and created this simple C program that directly uses libftdi in Linux to toggle CBUS0 ON and OFF every 5 seconds. I verified that it works.

https://github.com/kb1lqd/faradayio/blob/master/c_tools/cbus_toggle_1/main.c

@travisgoodspeed @kb1lqc

@kb1lqc
Copy link
Member

kb1lqc commented Jan 9, 2018

Yeah @kb1lqd this seems good. At some point just do what you need to make progress in a reasonable manner.

@kb1lqd
Copy link
Collaborator Author

kb1lqd commented Jan 15, 2018

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 Intel HEX file not a TI-TEXT file like the TI scripter program. This is a more supported format it seems for MSPGCC.

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/

@travisgoodspeed
Copy link

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.
https://github.com/travisgoodspeed/goodwatch/blob/master/firmware/Makefile

@kb1lqd
Copy link
Collaborator Author

kb1lqd commented Jan 15, 2018

Thanks @travisgoodspeed !

I created a HEX file but then ran into a libftdi issue that seems to be known and not fixed http://developer.intra2net.com/mailarchive/html/libftdi/2016/msg00009.html

After using libftdi to connect and bitbang the CBUS pins on disconnect the /dev/ttyUSB0 is removed and not reconnected.

dmesg | grep tty shows the last action after enabling BSL mode:

[229083.250740] ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected from ttyUSB0

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!

@travisgoodspeed
Copy link

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.

kb1lqd added a commit that referenced this issue Feb 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants