Ejemplo n.º 1
0
    def __init__(self):
        ScopeTemplate.__init__(self)
        self._is_connected = False

        self.params.init()

        self._cwusb = NAEUSB()
        self.ser = self._cwusb
        self.scopetype = self
        self.dev = self

        self.xmega = XMEGAPDI(self._cwusb)
        self.avr = AVRISP(self._cwusb)
        self.usart = USART(self._cwusb)
        self.serialstm32f = STM32FSerial(cwserial=self.usart)
        self.serialstm32f.scope = self
        self.io = GPIOSettings(self._cwusb)
        self.adc = ADCSettings(self._cwusb)
        self.glitch = GlitchSettings(self._cwusb)
        self._timeout = 2

        self._lasttrace = None

        self.getParams().addChildren([
            {'name':"CW-Lite XMEGA Programmer", 'tip':"Open XMEGA Programmer (ChipWhisperer-Lite Only)", 'type':"menu", "action":lambda _:self.getCwliteXMEGA().show()},
            {'name':"CW-Lite AVR Programmer", 'tip':"Open AVR Programmer (ChipWhisperer-Lite Only)", 'type':"menu", "action":lambda _:self.getCwliteAVR().show()},
            {'name':'Serial STM32F Programmer', 'tip':"Open STM32F Programmer (Serial/ChipWhisperer)", 'type':"menu", "action":lambda _:self.getSerialSTM32F().show()}
        ])

        self.disable_newattr()
Ejemplo n.º 2
0
def get_cw_type(sn=None):
    """ Gets the scope type of the connected ChipWhisperer

    If multiple connected, sn must be specified
    """
    from chipwhisperer.hardware.naeusb.naeusb import NAEUSB
    from chipwhisperer.capture import scopes
    possible_ids = [0xace0, 0xace2, 0xace3]

    cwusb = NAEUSB()
    possible_sn = cwusb.get_possible_devices(idProduct=possible_ids)
    name = ""
    if len(possible_sn) == 0:
        raise OSError("USB Device not found. Did you connect it first?")

    if (len(possible_sn) > 1):
        if sn is None:
            serial_numbers = []
            for d in possible_sn:
                serial_numbers.append("sn = {} ({})".format(str(d['sn']), str(d['product'])))
            raise Warning("Multiple chipwhisperers connected, but device and/or serial number not specified.\nDevices:\n{}".format(serial_numbers))
        else:
            for d in possible_sn:
                if d['sn'] == sn:
                    name = d['product']
    else:
        name = possible_sn[0]['product']

    #print(name)
    if (name == "ChipWhisperer Lite") or (name == "ChipWhisperer CW1200"):
        return scopes.OpenADC
    elif name == "ChipWhisperer Nano":
        return scopes.CWNano
    def __init__(self):
        self._cwusb = NAEUSB()

        # Connect required modules up here
        self.fpga = FPGA(self._cwusb)
        self.xmega = XMEGAPDI(self._cwusb)
        self.avr = AVRISP(self._cwusb)
        self.usart = USART(self._cwusb)

        self.getParams().addChildren([{
            'name':
            "CW-Lite XMEGA Programmer",
            'tip':
            "Open XMEGA Programmer (ChipWhisperer-Lite Only)",
            'type':
            "menu",
            "action":
            lambda _: self.getCwliteXMEGA().show()
        }, {
            'name':
            "CW-Lite AVR Programmer",
            'tip':
            "Open AVR Programmer (ChipWhisperer-Lite Only)",
            'type':
            "menu",
            "action":
            lambda _: self.getCwliteAVR().show()
        }])
Ejemplo n.º 4
0
    def __init__(self):
        self._cwusb = NAEUSB()

        # Connect required modules up here
        self.fpga = FPGA(self._cwusb)
        self.xmega = XMEGAPDI(self._cwusb)
        self.avr = AVRISP(self._cwusb)
        self.usart = USART(self._cwusb)
        self.serialstm32f = STM32FSerial(cwserial=self.usart, cwapi=None)
Ejemplo n.º 5
0
    def __init__(self,
                 target,
                 scope,
                 defines_files=None,
                 bs='',
                 force_bitfile=False):
        """
        Args:
            target: SimpleSerial target
            scope: CW scope
            naeusb: NewAE USB interface
            platform (string): CW305 or CW610 (PhyWhisperer)
            defines_files (list of 2 strings): path to defines_trace.v and defines_pw.v
        """
        super().__init__()
        self._trace_port_width = 4
        self._base_target_clock = 7.384e6
        self._base_baud = 38400
        self._usb_clock = 96e6
        self._uart_clock = self._usb_clock * 2
        self.expected_verilog_defines = 107
        self.swo_mode = False
        self.board_rev = 4
        self._scope = scope
        # Detect whether we exist on CW305 or CW610 based on the target we're given:
        if target._name == 'Simple Serial':
            self.platform = 'CW610'
            self._ss = target
            self._naeusb = NAEUSB()
            self._naeusb.con(idProduct=[0xC610])
            # we're using the CW NAEUSB, which has no knowledge of PW firmware, so let's manually
            # check the FW version here:
            fw_latest = [1, 1]
            if self._naeusb.readFwVersion()[0] < fw_latest[0]:
                logging.warning(
                    'Your PhyWhisperer firmware is outdated - latest is %d.%d'
                    % (fw_latest[0], fw_latest[1]) +
                    '. Suggested to update firmware, as you may experience errors.'
                )

            self._fpga = FPGA(self._naeusb)
            if not self._fpga.isFPGAProgrammed() or force_bitfile:
                if not bs:
                    bs = pkg_resources.resource_filename(
                        'chipwhisperer',
                        'hardware/firmware/tracewhisperer_top.bit')
                self._fpga.FPGAProgram(open(bs, 'rb'),
                                       exceptOnDoneFailure=False)
        else:
            self.platform = 'CW305'
            self._ss = cw.target(scope)
            self._naeusb = target._naeusb

        self.slurp_defines(defines_files)
        self._set_defaults()
Ejemplo n.º 6
0
    def __init__(self):
        TargetTemplate.__init__(self)
        self._naeusb = NAEUSB()
        self.pll = PLLCDCE906(self._naeusb, ref_freq=12.0E6)
        self.fpga = FPGA(self._naeusb)

        self.hw = None
        self.oa = None

        self._woffset = 0x400
        self._woffset_sam3U = 0x000

        self._clksleeptime = 1
        self._clkusbautooff = True
        self.last_key = bytearray([0] * 16)
Ejemplo n.º 7
0
    def __init__(self):
        TargetTemplate.__init__(self)
        self._naeusb = NAEUSB()
        self.pll = PLLCDCE906(self._naeusb, ref_freq = 12.0E6, parent=self)
        self.fpga = FPGA(self._naeusb)

        self.hw = None
        # self._fpgabs = QSettings().value("cw305-bitstream", '')
        self.oa = None

        self._woffset = 0x400

        self.params.addChildren([
            {'name':'PLL Settings', 'key':'pll', 'type':'group', 'children':[
                {'name':'Enabled', 'key':'pllenabled', 'type':'bool', 'default':False, 'set':self.pll.pll_enable_set, 'get':self.pll.pll_enable_get, 'psync':False},
                {'name':'CLK-SMA (X6)', 'key':'pll0', 'type':'group', 'children':[
                    {'name':'CLK-SMA Enabled', 'key':'pll0enabled', 'type':'bool', 'default':False, 'set':partial(self.pll.pll_outenable_set, outnum=0), 'get':partial(self.pll.pll_outenable_get, outnum=0), 'psync':False},
                    {'name':'CLK-SMA Source', 'key':'pll0source', 'type':'list', 'values':['PLL0', 'PLL1', 'PLL2'], 'default':'PLL0', 'set':partial(self.pll.pll_outsource_set, outnum=0), 'get':partial(self.pll.pll_outsource_get, outnum=0), 'psync':False},
                    {'name':'CLK-SMA Slew Rate', 'key':'pll0slew', 'type':'list', 'values':['+3nS', '+2nS', '+1nS', '+0nS'], 'default':'+0nS', 'set':partial(self.pll.pll_outslew_set, outnum=0), 'get':partial(self.pll.pll_outslew_get, outnum=0), 'psync':False},
                    {'name':'PLL0 Frequency', 'key':'pll0freq', 'type':'float', 'limits':(0.625E6, 167E6), 'default':0, 'step':1E6,
                        'siPrefix':True, 'suffix':'Hz', 'set':partial(self.pll.pll_outfreq_set, outnum=0), 'get':partial(self.pll.pll_outfreq_get, outnum=0), 'psync':False},
                ]},
                {'name':'CLK-N13 (FGPA Pin N13)', 'key':'pll1', 'type':'group', 'children':[
                    {'name':'CLK-N13 Enabled', 'key':'pll1enabled', 'type':'bool', 'default':False, 'set':partial(self.pll.pll_outenable_set, outnum=1), 'get':partial(self.pll.pll_outenable_get, outnum=1), 'psync':False},
                    {'name':'CLK-N13 Source', 'key':'pll1source', 'type':'list', 'values':['PLL1'], 'value':'PLL1'},
                    {'name':'CLK-N13 Slew Rate', 'key':'pll1slew', 'type':'list', 'values':['+3nS', '+2nS', '+1nS', '+0nS'], 'default':'+0nS', 'set':partial(self.pll.pll_outslew_set, outnum=1), 'get':partial(self.pll.pll_outslew_get, outnum=1), 'psync':False},
                    {'name':'PLL1 Frequency', 'key':'pll1freq', 'type':'float', 'limits':(0.625E6, 167E6), 'default':0, 'step':1E6,
                        'siPrefix':True, 'suffix':'Hz', 'set':partial(self.pll.pll_outfreq_set, outnum=1), 'get':partial(self.pll.pll_outfreq_get, outnum=1), 'psync':False},
                ]},
                {'name':'CLK-E12 (FGPA Pin E12)', 'key':'pll2', 'type':'group', 'children':[
                    {'name':'CLK-E12 Enabled', 'key':'pll2enabled', 'type':'bool', 'default':False, 'set':partial(self.pll.pll_outenable_set, outnum=2), 'get':partial(self.pll.pll_outenable_get, outnum=2), 'psync':False},
                    {'name':'CLK-E12 Source', 'key':'pll2source', 'type':'list', 'values':['PLL2'], 'value':'PLL2'},
                    {'name':'CLK-E12 Slew Rate', 'key':'pll2slew', 'type':'list', 'values':['+0nS', '+1nS', '+2nS', '+3nS'], 'default':'+0nS', 'set':partial(self.pll.pll_outslew_set, outnum=2), 'get':partial(self.pll.pll_outslew_get, outnum=2), 'psync':False},
                    {'name':'PLL2 Frequency', 'key':'pll2freq', 'type':'float', 'limits':(0.625E6, 167E6), 'default':0, 'step':1E6,
                        'siPrefix':True, 'suffix':'Hz', 'set':partial(self.pll.pll_outfreq_set, outnum=2), 'get':partial(self.pll.pll_outfreq_get, outnum=2), 'psync':False},
                ]},
                {'name':'Save as Default (stored in EEPROM)', 'type':'action', 'action':lambda _ : self.pll.pll_writedefaults()},
            ]},
            {'name':'Disable CLKUSB For Capture', 'key':'clkusbautooff', 'type':'bool', 'value':True},
            {'name':'Time CLKUSB Disabled for', 'key':'clksleeptime', 'type':'int', 'range':(1, 50000), 'value':50, 'suffix':'mS'},
            {'name':'CLKUSB Manual Setting', 'key':'clkusboff', 'type':'bool', 'value':True, 'action':self.usb_clk_setenabled_action},
            {'name':'Send Trigger', 'type':'action', 'action':self.usb_trigger_toggle},
            {'name':'VCC-INT', 'key':'vccint', 'type':'float', 'default':1.00, 'range':(0.6, 1.10), 'suffix':' V', 'decimals':3, 'set':self.vccint_set, 'get':self.vccint_get, 'step':0.01},
            {'name':'FPGA Bitstream', 'type':'group', 'children':[
                    {'name':'Bitstream File', 'key':'fpgabsfile', 'type':'file', 'value':"", "filter":'*.bit'},
                    {'name':'Program FPGA', 'type':'action', 'action':self.gui_programfpga},
            ]},
        ])
class CWLiteUSB(Parameterized):
    _name = "ChipWisperer-Lite USB"

    def __init__(self):
        self._cwusb = NAEUSB()

        # Connect required modules up here
        self.fpga = FPGA(self._cwusb)
        self.xmega = XMEGAPDI(self._cwusb)
        self.avr = AVRISP(self._cwusb)
        self.usart = USART(self._cwusb)

        self.getParams().addChildren([{
            'name':
            "CW-Lite XMEGA Programmer",
            'tip':
            "Open XMEGA Programmer (ChipWhisperer-Lite Only)",
            'type':
            "menu",
            "action":
            lambda _: self.getCwliteXMEGA().show()
        }, {
            'name':
            "CW-Lite AVR Programmer",
            'tip':
            "Open AVR Programmer (ChipWhisperer-Lite Only)",
            'type':
            "menu",
            "action":
            lambda _: self.getCwliteAVR().show()
        }])

    def con(self, idProduct):
        return self._cwusb.con(idProduct=idProduct)

    # def __del__(self):
    #     print "here"

    def dis(self):
        if self.params is not None:
            self.getParams().delete()
        self.params = None
        # gc.collect()
        # print sys.getrefcount(self)
        # print gc.get_referrers(self)

    def usbdev(self):
        return self._cwusb

    def getCwliteXMEGA(self):
        if not hasattr(self, 'cwliteXMEGA'):
            self.cwliteXMEGA = XMEGAProgrammerDialog()
            self.cwliteXMEGA.setUSBInterface(self.xmega)
        return self.cwliteXMEGA

    def getCwliteAVR(self):
        if not hasattr(self, 'cwliteAVR'):
            self.cwliteAVR = AVRProgrammerDialog()
            self.cwliteAVR.setUSBInterface(self.avr)
        return self.cwliteAVR
class CWLiteUSB(Parameterized):
    _name = "ChipWisperer-Lite USB"

    def __init__(self):
        self._cwusb = NAEUSB()

        # Connect required modules up here
        self.fpga = FPGA(self._cwusb)
        self.xmega = XMEGAPDI(self._cwusb)
        self.avr = AVRISP(self._cwusb)
        self.usart = USART(self._cwusb)

        self.getParams().addChildren([
            {'name':"CW-Lite XMEGA Programmer", 'tip':"Open XMEGA Programmer (ChipWhisperer-Lite Only)", 'type':"menu", "action":lambda _:self.getCwliteXMEGA().show()},
            {'name':"CW-Lite AVR Programmer", 'tip':"Open AVR Programmer (ChipWhisperer-Lite Only)", 'type':"menu", "action":lambda _:self.getCwliteAVR().show()}
        ])

    def con(self):
        self._cwusb.con()

    # def __del__(self):
    #     print "here"

    def dis(self):
        self.getParams().delete()
        self.params = None
        # gc.collect()
        # print sys.getrefcount(self)
        # print gc.get_referrers(self)

    def usbdev(self):
        return self._cwusb

    def getCwliteXMEGA(self):
        if not hasattr(self, 'cwliteXMEGA'):
            self.cwliteXMEGA = XMEGAProgrammerDialog()
            self.cwliteXMEGA.setUSBInterface(self.xmega)
        return self.cwliteXMEGA

    def getCwliteAVR(self):
        if not hasattr(self, 'cwliteAVR'):
            self.cwliteAVR = AVRProgrammerDialog()
            self.cwliteAVR.setUSBInterface(self.avr)
        return self.cwliteAVR
Ejemplo n.º 10
0
    def __init__(self):
        TargetTemplate.__init__(self)
        self._naeusb = NAEUSB()
        self.pll = PLLCDCE906(self._naeusb, ref_freq=12.0E6)
        self.fpga = FPGA(self._naeusb)

        self.hw = None
        self.oa = None

        self._woffset_sam3U = 0x000
        self.default_verilog_defines = 'cw305_defines.v'
        self.default_verilog_defines_full_path = '../../hardware/victims/cw305_artixtarget/fpga/common/' + self.default_verilog_defines
        self.registers = 12  # number of registers we expect to find
        self.bytecount_size = 7  # pBYTECNT_SIZE in Verilog

        self._clksleeptime = 1
        self._clkusbautooff = True
        self.last_key = bytearray([0] * 16)
        self.target_name = 'AES'
    def __init__(self):
        self._cwusb = NAEUSB()

        # Connect required modules up here
        self.fpga = FPGA(self._cwusb)
        self.xmega = XMEGAPDI(self._cwusb)
        self.avr = AVRISP(self._cwusb)
        self.usart = USART(self._cwusb)

        self.getParams().addChildren([
            {'name':"CW-Lite XMEGA Programmer", 'tip':"Open XMEGA Programmer (ChipWhisperer-Lite Only)", 'type':"menu", "action":lambda _:self.getCwliteXMEGA().show()},
            {'name':"CW-Lite AVR Programmer", 'tip':"Open AVR Programmer (ChipWhisperer-Lite Only)", 'type':"menu", "action":lambda _:self.getCwliteAVR().show()}
        ])
Ejemplo n.º 12
0
    def __init__(self):
        ScopeTemplate.__init__(self)
        self._is_connected = False

        self._cwusb = NAEUSB()
        self.ser = self._cwusb
        self.scopetype = self
        self.dev = self

        self.xmega = XMEGAPDI(self._cwusb)
        self.avr = AVRISP(self._cwusb)
        self.usart = USART(self._cwusb)
        self.serialstm32f = STM32FSerial(cwserial=self.usart)
        self.serialstm32f.scope = self
        self.io = GPIOSettings(self._cwusb)
        self.adc = ADCSettings(self._cwusb)
        self.glitch = GlitchSettings(self._cwusb)
        self._timeout = 2

        self._lasttrace = None

        self.disable_newattr()
Ejemplo n.º 13
0
    def __init__(self):
        self._cwusb = NAEUSB()

        # Connect required modules up here
        self.fpga = FPGA(self._cwusb)
        self.xmega = XMEGAPDI(self._cwusb)
        self.avr = AVRISP(self._cwusb)
        self.usart = USART(self._cwusb)
        self.serialstm32f = STM32FSerial(cwserial=self.usart,
                                         cwapi=CWCoreAPI.getInstance())

        self.getParams().addChildren([{
            'name':
            "CW-Lite XMEGA Programmer",
            'tip':
            "Open XMEGA Programmer (ChipWhisperer-Lite Only)",
            'type':
            "menu",
            "action":
            lambda _: self.getCwliteXMEGA().show()
        }, {
            'name':
            "CW-Lite AVR Programmer",
            'tip':
            "Open AVR Programmer (ChipWhisperer-Lite Only)",
            'type':
            "menu",
            "action":
            lambda _: self.getCwliteAVR().show()
        }, {
            'name':
            'Serial STM32F Programmer',
            'tip':
            "Open STM32F Programmer (Serial/ChipWhisperer)",
            'type':
            "menu",
            "action":
            lambda _: self.getSerialSTM32F().show()
        }])
Ejemplo n.º 14
0
    def __init__(self, *args, **kwargs):
        # maybe later can hijack cw305 stuff, but for now don't
        pass
        import chipwhisperer as cw
        self._naeusb = NAEUSB()
        self.pll = PLLCDCE906(self._naeusb, ref_freq=12.0E6)
        self.fpga = FPGA(self._naeusb)

        self.hw = None
        self.oa = None

        self._woffset_sam3U = 0x000
        self.default_verilog_defines = 'cw305_defines.v'
        self.default_verilog_defines_full_path = os.path.dirname(
            cw.__file__
        ) + '/../../hardware/victims/cw305_artixtarget/fpga/common/' + self.default_verilog_defines
        self.registers = 12  # number of registers we expect to find
        self.bytecount_size = 7  # pBYTECNT_SIZE in Verilog

        self._clksleeptime = 1
        self._clkusbautooff = True
        self.last_key = bytearray([0] * 16)
        self.target_name = 'AES'
Ejemplo n.º 15
0
class CWLiteUSB(object):
    _name = "ChipWisperer-Lite USB"

    def __init__(self):
        self._cwusb = NAEUSB()

        # Connect required modules up here
        self.fpga = FPGA(self._cwusb)
        self.xmega = XMEGAPDI(self._cwusb)
        self.avr = AVRISP(self._cwusb)
        self.usart = USART(self._cwusb)
        self.serialstm32f = STM32FSerial(cwserial=self.usart, cwapi=None)

    def get_possible_devices(self, idProduct):
        return self._cwusb.get_possible_devices(idProduct=idProduct)

    def con(self, *args, **kwargs):
        return self._cwusb.con(*args, **kwargs)

    def dis(self):
        pass

    def usbdev(self):
        return self._cwusb
Ejemplo n.º 16
0
    def __init__(self, parentParam=None):
        TargetTemplate.__init__(self, parentParam)
        self._naeusb = NAEUSB()
        self.pll = PLLCDCE906(self._naeusb, ref_freq = 12.0E6, parent=self)
        self.fpga = FPGA(self._naeusb)

        self.hw = None
        # self._fpgabs = QSettings().value("cw305-bitstream", '')
        self.oa = None

        self._woffset = 0x400

        self.params.addChildren([
            {'name':'PLL Settings', 'key':'pll', 'type':'group', 'children':[
                {'name':'Enabled', 'key':'pllenabled', 'type':'bool', 'default':False, 'set':self.pll.pll_enable_set, 'get':self.pll.pll_enable_get, 'psync':False},
                {'name':'CLK-SMA (X6)', 'key':'pll0', 'type':'group', 'children':[
                    {'name':'CLK-SMA Enabled', 'key':'pll0enabled', 'type':'bool', 'default':False, 'set':partial(self.pll.pll_outenable_set, outnum=0), 'get':partial(self.pll.pll_outenable_get, outnum=0), 'psync':False},
                    {'name':'CLK-SMA Source', 'key':'pll0source', 'type':'list', 'values':['PLL0', 'PLL1', 'PLL2'], 'default':'PLL0', 'set':partial(self.pll.pll_outsource_set, outnum=0), 'get':partial(self.pll.pll_outsource_get, outnum=0), 'psync':False},
                    {'name':'CLK-SMA Slew Rate', 'key':'pll0slew', 'type':'list', 'values':['+3nS', '+2nS', '+1nS', '+0nS'], 'default':'+0nS', 'set':partial(self.pll.pll_outslew_set, outnum=0), 'get':partial(self.pll.pll_outslew_get, outnum=0), 'psync':False},
                    {'name':'PLL0 Frequency', 'key':'pll0freq', 'type':'float', 'limits':(0.625E6, 167E6), 'default':0, 'step':1E6,
                        'siPrefix':True, 'suffix':'Hz', 'set':partial(self.pll.pll_outfreq_set, outnum=0), 'get':partial(self.pll.pll_outfreq_get, outnum=0), 'psync':False},
                ]},
                {'name':'CLK-N13 (FGPA Pin N13)', 'key':'pll1', 'type':'group', 'children':[
                    {'name':'CLK-N13 Enabled', 'key':'pll1enabled', 'type':'bool', 'default':False, 'set':partial(self.pll.pll_outenable_set, outnum=1), 'get':partial(self.pll.pll_outenable_get, outnum=1), 'psync':False},
                    {'name':'CLK-N13 Source', 'key':'pll1source', 'type':'list', 'values':['PLL1'], 'value':'PLL1'},
                    {'name':'CLK-N13 Slew Rate', 'key':'pll1slew', 'type':'list', 'values':['+3nS', '+2nS', '+1nS', '+0nS'], 'default':'+0nS', 'set':partial(self.pll.pll_outslew_set, outnum=1), 'get':partial(self.pll.pll_outslew_get, outnum=1), 'psync':False},
                    {'name':'PLL1 Frequency', 'key':'pll1freq', 'type':'float', 'limits':(0.625E6, 167E6), 'default':0, 'step':1E6,
                        'siPrefix':True, 'suffix':'Hz', 'set':partial(self.pll.pll_outfreq_set, outnum=1), 'get':partial(self.pll.pll_outfreq_get, outnum=1), 'psync':False},
                ]},
                {'name':'CLK-E12 (FGPA Pin E12)', 'key':'pll2', 'type':'group', 'children':[
                    {'name':'CLK-E12 Enabled', 'key':'pll2enabled', 'type':'bool', 'default':False, 'set':partial(self.pll.pll_outenable_set, outnum=2), 'get':partial(self.pll.pll_outenable_get, outnum=2), 'psync':False},
                    {'name':'CLK-E12 Source', 'key':'pll2source', 'type':'list', 'values':['PLL2'], 'value':'PLL2'},
                    {'name':'CLK-E12 Slew Rate', 'key':'pll2slew', 'type':'list', 'values':['+0nS', '+1nS', '+2nS', '+3nS'], 'default':'+0nS', 'set':partial(self.pll.pll_outslew_set, outnum=2), 'get':partial(self.pll.pll_outslew_get, outnum=2), 'psync':False},
                    {'name':'PLL2 Frequency', 'key':'pll2freq', 'type':'float', 'limits':(0.625E6, 167E6), 'default':0, 'step':1E6,
                        'siPrefix':True, 'suffix':'Hz', 'set':partial(self.pll.pll_outfreq_set, outnum=2), 'get':partial(self.pll.pll_outfreq_get, outnum=2), 'psync':False},
                ]},
                {'name':'Save as Default (stored in EEPROM)', 'type':'action', 'action':lambda _ : self.pll.pll_writedefaults()},
            ]},
            {'name':'Disable CLKUSB For Capture', 'key':'clkusbautooff', 'type':'bool', 'value':True},
            {'name':'Time CLKUSB Disabled for', 'key':'clksleeptime', 'type':'int', 'range':(1, 50000), 'value':50, 'suffix':'mS'},
            {'name':'CLKUSB Manual Setting', 'key':'clkusboff', 'type':'bool', 'value':True, 'action':self.usb_clk_setenabled_action},
            {'name':'Send Trigger', 'type':'action', 'action':self.usb_trigger_toggle},
            {'name':'VCC-INT', 'key':'vccint', 'type':'float', 'default':1.00, 'range':(0.6, 1.10), 'suffix':' V', 'decimals':3, 'set':self.vccint_set, 'get':self.vccint_get},
            {'name':'FPGA Bitstream', 'type':'group', 'children':[
                    {'name':'Bitstream File', 'key':'fpgabsfile', 'type':'file', 'value':"", "filter":'*.bit'},
                    {'name':'Program FPGA', 'type':'action', 'action':self.gui_programfpga},
            ]},
        ])
Ejemplo n.º 17
0
class CW305(TargetTemplate):
    """CW305 target object.

    This class contains the public API for the CW305 hardware.
    To connect to the CW305, the easiest method is::

        import chipwhisperer as cw
        scope = cw.scope()

        # scope can also be None here, unlike with the default SimpleSerial
        target = cw.target(scope,
                targets.CW305, bsfile=<valid FPGA bitstream file>)

    As of CW5.3, you can also specify the following::

        # can also be '35t'
        target = cw.target(scope, fpga_id='100t')

    To automatically program with the example AES bitstream

    If you're using the reference designs, typical configuration
    requires you to set the FPGA VCC-INT voltage and enable and 
    set the clock via the PLL. You'll probably also want to
    disable the USB clock during encryption to reduce noise::

        target.vccint_set(1.0) #set VCC-INT to 1V
        
        target.pll.pll_enable_set(True) #Enable PLL chip
        target.pll.pll_outenable_set(False, 0) # Disable unused PLL0
        target.pll.pll_outenable_set(True, 1)  # Enable PLL 
        target.pll.pll_outenable_set(False, 2) # Disable unused PLL2

        # optional, but reduces power trace noise
        target.clkusbautooff = True
        target.clksleeptime = 1 # 1ms typically good for sleep


    Don't forget to clock the ChipWhisperer ADC off the FPGA instead
    of the internal clock::

        scope.clock.adc_src = "extclk_x4"
        scope.clock.reset_adc() # make sure the DCM is locked

    Note that connecting to the CW305 includes programming the CW305 FPGA,
    if it isn't already.

    For more help about CW305 settings, try help() on this CW305 submodule:

       * target.pll
    """

    _name = "ChipWhisperer CW305 (Artix-7)"
    BATCHRUN_START = 0x1
    BATCHRUN_RANDOM_KEY = 0x2
    BATCHRUN_RANDOM_PT = 0x4

    def __init__(self):
        TargetTemplate.__init__(self)
        self._naeusb = NAEUSB()
        self.pll = PLLCDCE906(self._naeusb, ref_freq=12.0E6)
        self.fpga = FPGA(self._naeusb)

        self.hw = None
        self.oa = None

        self._woffset_sam3U = 0x000
        self.default_verilog_defines = 'cw305_defines.v'
        self.default_verilog_defines_full_path = '../../hardware/victims/cw305_artixtarget/fpga/common/' + self.default_verilog_defines
        self.registers = 12  # number of registers we expect to find
        self.bytecount_size = 7  # pBYTECNT_SIZE in Verilog

        self._clksleeptime = 1
        self._clkusbautooff = True
        self.last_key = bytearray([0] * 16)
        self.target_name = 'AES'

    def _getNAEUSB(self):
        return self._naeusb

    def slurp_defines(self, defines_files=None):
        """ Parse Verilog defines file so we can access register and bit
        definitions by name and avoid 'magic numbers'.
        Args:
            defines_files (list): list of Verilog define files to parse
        """
        self.verilog_define_matches = 0
        if type(defines_files) != list:
            logging.error(
                'defines_files must be provided as a list (even it it contains a single element)'
            )
        for i, defines_file in enumerate(defines_files):
            if type(defines_file) == io.BytesIO:
                defines = io.TextIOWrapper(defines_file)
            else:
                if not os.path.isfile(defines_file):
                    logging.error(
                        'Cannot find %s. Please specify the location of %s on your filesystem.'
                        % (defines_files, self.default_verilog_defines))
                defines = open(defines_file, 'r')
            define_regex_base = re.compile(r'`define')
            define_regex_reg = re.compile(r'`define\s+?REG_')
            define_regex_radix = re.compile(
                r'`define\s+?(\w+).+?\'([bdh])([0-9a-fA-F]+)')
            define_regex_noradix = re.compile(r'`define\s+?(\w+?)\s+?(\d+?)')
            block_offset = 0
            for define in defines:
                if define_regex_base.search(define):
                    reg = define_regex_reg.search(define)
                    match = define_regex_radix.search(define)
                    if match:
                        self.verilog_define_matches += 1
                        if match.group(2) == 'b':
                            radix = 2
                        elif match.group(2) == 'h':
                            radix = 16
                        else:
                            radix = 10
                        setattr(self, match.group(1),
                                int(match.group(3), radix) + block_offset)
                    else:
                        match = define_regex_noradix.search(define)
                        if match:
                            self.verilog_define_matches += 1
                            setattr(self, match.group(1),
                                    int(match.group(2), 10) + block_offset)
                        else:
                            logging.warning("Couldn't parse line: %s", define)
            defines.close()
        # make sure everything is cool:
        if self.verilog_define_matches != self.registers:
            logging.warning(
                "Trouble parsing Verilog defines files (%s): didn't find the right number of defines; expected %d, got %d.\n"
                % (defines_file, self.registers, self.verilog_define_matches) +
                "Ensure that the Verilog defines files above are the same that were used to build the bitfile."
            )

    def get_fpga_buildtime(self):
        """Returns date and time when FPGA bitfile was generated.
        """
        raw = self.fpga_read(self.REG_BUILDTIME, 4)
        # definitions: Xilinx XAPP1232
        day = raw[3] >> 3
        month = ((raw[3] & 0x7) << 1) + (raw[2] >> 7)
        year = ((raw[2] >> 1) & 0x3f) + 2000
        hour = ((raw[2] & 0x1) << 4) + (raw[1] >> 4)
        minute = ((raw[1] & 0xf) << 2) + (raw[0] >> 6)
        return "FPGA build time: {}/{}/{}, {}:{}".format(
            month, day, year, hour, minute)

    def fpga_write(self, addr, data):
        """Write to an address on the FPGA

        Args:
            addr (int): Address to write to
            data (list): Data to write to addr

        """
        addr = addr << self.bytecount_size
        return self._naeusb.cmdWriteMem(addr, data)

    def fpga_read(self, addr, readlen):
        """Read from an address on the FPGA

        Args:
            addr (int): Address to read from
            readlen (int): Length of data to read

        Returns:
            Requested data as a list
        """
        addr = addr << self.bytecount_size
        data = self._naeusb.cmdReadMem(addr, readlen)
        return data

    def usb_clk_setenabled(self, status):
        """ Turn on or off the Data Clock to the FPGA """
        if status:
            self._naeusb.sendCtrl(CW305_USB.REQ_SYSCFG, CW305_USB.SYSCFG_CLKON)
        else:
            self._naeusb.sendCtrl(CW305_USB.REQ_SYSCFG,
                                  CW305_USB.SYSCFG_CLKOFF)

    def usb_trigger_toggle(self, _=None):
        """ Toggle the trigger line high then low """
        self._naeusb.sendCtrl(CW305_USB.REQ_SYSCFG, CW305_USB.SYSCFG_TOGGLE)

    def vccint_set(self, vccint=1.0):
        """ Set the VCC-INT for the FPGA """

        # print "vccint = " + str(vccint)

        if (vccint < 0.6) or (vccint > 1.15):
            raise ValueError("VCC-Int out of range 0.6V-1.1V")

        # Convert to mV
        vccint = int(vccint * 1000)
        vccsetting = [vccint & 0xff, (vccint >> 8) & 0xff, 0]

        # calculate checksum
        vccsetting[2] = vccsetting[0] ^ vccsetting[1] ^ CW305_USB.VCCINT_XORKEY

        self._naeusb.sendCtrl(CW305_USB.REQ_VCCINT, 0, vccsetting)

        resp = self._naeusb.readCtrl(CW305_USB.REQ_VCCINT, dlen=3)
        if resp[0] != 2:
            raise IOError("VCC-INT Write Error, response = %d" % resp[0])

    def vccint_get(self):
        """ Get the last set value for VCC-INT """

        resp = self._naeusb.readCtrl(CW305_USB.REQ_VCCINT, dlen=3)
        return float(resp[1] | (resp[2] << 8)) / 1000.0

    def _con(self,
             scope=None,
             bsfile=None,
             force=False,
             fpga_id=None,
             defines_files=None,
             slurp=True):
        """Connect to CW305 board, and download bitstream.

        If the target has already been programmed it skips reprogramming
        unless forced.

        Args:
            scope (ScopeTemplate): An instance of a scope object.
            bsfile (path): The path to the bitstream file to program the FPGA with.
            force (bool): Whether or not to force reprogramming.
            fpga_id (string): '100t', '35t', or None. If bsfile is None and fpga_id specified,
                              program with AES firmware for fpga_id
            defines_files (list, optional): path to cw305_defines.v
            slurp (bool, optional): Whether or not to slurp the Verilog defines.
        """

        from datetime import datetime
        self._naeusb.con(idProduct=[0xC305])
        if not fpga_id is None:
            if fpga_id not in ('100t', '35t'):
                raise ValueError(f"Invalid fpga {fpga_id}")
        self._fpga_id = fpga_id
        if self.fpga.isFPGAProgrammed() == False or force:
            if bsfile is None:
                if not fpga_id is None:
                    from chipwhisperer.hardware.firmware.cw305 import getsome
                    if self.target_name == 'AES':
                        bsdata = getsome(f"AES_{fpga_id}.bit")
                    elif self.target_name == 'Cryptech ecdsa256-v1 pmul':
                        bsdata = getsome(f"ECDSA256v1_pmul_{fpga_id}.bit")
                    starttime = datetime.now()
                    status = self.fpga.FPGAProgram(bsdata,
                                                   exceptOnDoneFailure=False)
                    stoptime = datetime.now()
                    if status:
                        logging.info('FPGA Config OK, time: %s' %
                                     str(stoptime - starttime))
                    else:
                        logging.warning(
                            'FPGA Done pin failed to go high, check bitstream is for target device.'
                        )
                else:
                    print("No FPGA Bitstream file specified.")
            elif not os.path.isfile(bsfile):
                print(("FPGA Bitstream not configured or '%s' not a file." %
                       str(bsfile)))
            else:
                starttime = datetime.now()
                status = self.fpga.FPGAProgram(open(bsfile, "rb"),
                                               exceptOnDoneFailure=False)
                stoptime = datetime.now()
                if status:
                    logging.info('FPGA Config OK, time: %s' %
                                 str(stoptime - starttime))
                else:
                    logging.warning(
                        'FPGA Done pin failed to go high, check bitstream is for target device.'
                    )

        self.usb_clk_setenabled(True)
        self.pll.cdce906init()

        if defines_files is None:
            if fpga_id is None:
                verilog_defines = [self.default_verilog_defines_full_path]
            else:
                from chipwhisperer.hardware.firmware.cw305 import getsome
                verilog_defines = [getsome(self.default_verilog_defines)]
        else:
            verilog_defines = defines_files
        if slurp:
            self.slurp_defines(verilog_defines)

    def _dis(self):
        if self._naeusb:
            self._naeusb.close()

    def checkEncryptionKey(self, key):
        """Validate encryption key"""
        return key

    def loadEncryptionKey(self, key):
        """Write encryption key to FPGA"""
        self.key = key
        key = key[::-1]
        self.fpga_write(self.REG_CRYPT_KEY, key)

    def loadInput(self, inputtext):
        """Write input to FPGA"""
        self.input = inputtext
        text = inputtext[::-1]
        self.fpga_write(self.REG_CRYPT_TEXTIN, text)

    def is_done(self):
        """Check if FPGA is done"""
        result = self.fpga_read(self.REG_CRYPT_GO, 1)[0]
        if result == 0x01:
            return False
        else:
            self.fpga_write(self.REG_USER_LED, [0])
            return True

    isDone = camel_case_deprecated(is_done)

    def readOutput(self):
        """"Read output from FPGA"""
        data = self.fpga_read(self.REG_CRYPT_CIPHEROUT, 16)
        data = data[::-1]
        #self.newInputData.emit(util.list2hexstr(data))
        return data

    @property
    def latest_fw(self):
        cw_type = self._getCWType()
        if cw_type == "cwlite":
            from chipwhisperer.hardware.firmware.cwlite import fwver
        elif cw_type == "cw1200":
            from chipwhisperer.hardware.firmware.cw1200 import fwver

        ret = OrderedDict()
        return {"major": fwver[0], "minor": fwver[1]}

    @property
    def fw_version(self):
        a = self._naeusb.readFwVersion()
        return {"major": a[0], "minor": a[1], "debug": a[2]}

    @property
    def clkusbautooff(self):
        """ If set, the USB clock is automatically disabled on capture.

        The USB clock is re-enabled after self.clksleeptime milliseconds.

        Reads/Writes to the FPGA will not be possible until after
        the USB clock is reenabled, meaning :code:`usb_trigger_toggle()`
        must be used to trigger the FPGA to perform an encryption.

        :Getter: Gets whether to turn off the USB clock on capture

        :Setter: Sets whether to turn off the USB clock on capture
        """
        return self._clkusbautooff

    @clkusbautooff.setter
    def clkusbautooff(self, state):
        self._clkusbautooff = state

    @property
    def clksleeptime(self):
        """ Time (in milliseconds) that the USB clock is disabled for upon
        capture, if self.clkusbautooff is set.
        """
        return self._clksleeptime

    @clksleeptime.setter
    def clksleeptime(self, value):
        self._clksleeptime = value

    def go(self):
        """Disable USB clock (if requested), perform encryption, re-enable clock"""
        if self.clkusbautooff:
            self.usb_clk_setenabled(False)

        self.fpga_write(self.REG_USER_LED, [0x01])

        time.sleep(0.001)
        self.usb_trigger_toggle()
        # it's also possible to 'go' via register write but that won't take if
        # the USB clock was turned off:
        #self.fpga_write(self.REG_CRYPT_GO, [1])

        if self.clkusbautooff:
            time.sleep(self.clksleeptime / 1000.0)
            self.usb_clk_setenabled(True)

    def simpleserial_read(self, cmd, pay_len, end='\n', timeout=250, ack=True):
        """Read data from target

        Mimics simpleserial protocol of serial based targets

        Args:
            cmd (str): Command to ues. Only accepts 'r' for now.
            pay_len: Unused
            end: Unused
            timeout: Unused
            ack: Unused

        Returns: Value from Crypto output register

        .. versionadded:: 5.1
            Added simpleserial_read to CW305
        """
        if cmd == "r":
            return self.readOutput()
        else:
            raise ValueError("Unknown command {}".format(cmd))

    def simpleserial_write(self, cmd, data, end=None):
        """Write data to target.

        Mimics simpleserial protocol of serial based targets.

        Args:
            cmd (str): Command to use. Target supports 'p' (write plaintext),
                and 'k' (write key).
            data (bytearray): Data to write to target
            end: Unused

        Raises:
            ValueError: Unknown command

        .. versionadded:: 5.1
            Added simpleserial_write to CW305
        """
        if cmd == 'p':
            self.loadInput(data)
            self.go()
        elif cmd == 'k':
            self.loadEncryptionKey(data)
        else:
            raise ValueError("Unknown command {}".format(cmd))

    def set_key(self, key, ack=False, timeout=250):
        """Checks if key is different from the last one sent. If so, send it.

        Args:
            key (bytearray):  key to send
            ack: Unused
            timeout: Unused

        .. versionadded:: 5.1
            Added set_key to CW305
        """
        if self.last_key != key:
            self.last_key = key
            self.simpleserial_write('k', key)

    def batchRun(self,
                 batchsize=1024,
                 random_key=True,
                 random_pt=True,
                 seed=None):
        """
            Run multiple encryptions on random data

            Args:
                batchsize (int): The number of encryption to run (default 1024).
                random_key (bool): True if the key is random (default False).
                random_pt (bool): True if the plaintext are random (default True).
                seed (int): random int32 for the PRG.
        """
        if seed is None:
            seed = random.randint(0, 2**32)

        data = []
        data.extend(
            packuint32(1 | (random_key << 1) | (random_pt << 2)
                       | (batchsize << 16)))
        data.extend(packuint32(seed))
        self.sam3u_write(0, data)

        # generate the inputs
        if random_key:
            key = [[0 for x in range(16)] for y in range(batchsize)]
        else:
            key = None

        if random_pt:
            pt = [[0 for x in range(16)] for y in range(batchsize)]
        else:
            pt = None

        for b in range(batchsize):
            if random_key:
                for j in range(16):
                    key[b][15 - j] = seed >> 24
                    seed += ((seed * seed) & 0xffffffff) | 0x5
                    seed &= 0xffffffff
            if random_pt:
                for j in range(16):
                    pt[b][15 - j] = seed >> 24
                    seed += ((seed * seed) & 0xffffffff) | 0x5
                    seed &= 0xffffffff
        return key, pt

    def sam3u_write(self, addr, data):
        """Write to an address on the FPGA

        Args:
            addr (int): Address to write to
            data (list): Data to write to addr

        Raises:
            IOError: User attempted to write to a read-only location
        """
        if addr < self._woffset_sam3U:
            raise IOError("Write to read-only location: 0x%04x" % addr)
        if len(data) > (256 + addr):
            raise IOError("Write will overflow at location: 0x%04x" % (256))

        return self._naeusb.cmdWriteSam3U(addr, data)

    @fw_ver_required(0, 30)
    def spi_mode(self, enable=True, timeout=200, bsfile=None):
        """Enter programming mode for the onboard SPI chip
        
        Reprograms the FPGA with the appropriate bitstream and 
        returns an object with which to program the CW305 SPI chip
        (see documentation on the returned object for more info)

        Args:
            enable (bool): Enable the SPI interface before returning it. Defaults to True
            timeout (int): USB timeout in ms. Defaults to 200.
            bsfile (string): If not None, program with a bitstream pointed to by bsfile.
                             If None, program with SPI passthrough bitstream for the chip
                             specified during connection (or cw.target()) 

        Returns:
            A FPGASPI object which can be used to erase/program/verify/read the SPI
            chip on the CW305.
        """
        from datetime import datetime
        if self._fpga_id is None and bsfile is None:
            logging.warning(
                "CW305 requires passthrough bitstream to program SPI chip, but file/chip not specified"
            )
        else:
            bsdata = None
            if self._fpga_id:
                from chipwhisperer.hardware.firmware.cw305 import getsome
                bsdata = getsome(f"SPI_flash_{self._fpga_id}.bit")
            else:
                bsdata = open(bsfile, "rb")
            starttime = datetime.now()
            status = self.fpga.FPGAProgram(bsdata, exceptOnDoneFailure=False)
            stoptime = datetime.now()
            if status:
                logging.info('FPGA Config OK, time: %s' %
                             str(stoptime - starttime))
            else:
                logging.warning(
                    'FPGA Done pin failed to go high, check bitstream is for target device.'
                )

        spi = FPGASPI(self._naeusb, timeout)
        spi.enable_interface(enable)
        return spi

    @fw_ver_required(0, 40)
    def gpio_mode(self, timeout=200):
        """Allow arbitrary GPIO access on SAM3U
        
        Allows low-level IO access to SAM3U GPIO, and also SPI transfers.
        (see documentation on the returned object for more info)

        Args:
            timeout (int): USB timeout in ms. Defaults to 200.

        Returns:
            A FPGAIO object which can be used to access IO on the CW305.
        """
        io = FPGAIO(self._naeusb, timeout)
        return io
Ejemplo n.º 18
0
class CWLiteUSB(Parameterized):
    _name = "ChipWisperer-Lite USB"

    def __init__(self):
        self._cwusb = NAEUSB()

        # Connect required modules up here
        self.fpga = FPGA(self._cwusb)
        self.xmega = XMEGAPDI(self._cwusb)
        self.avr = AVRISP(self._cwusb)
        self.usart = USART(self._cwusb)
        self.serialstm32f = STM32FSerial(cwserial=self.usart,
                                         cwapi=CWCoreAPI.getInstance())

        self.getParams().addChildren([{
            'name':
            "CW-Lite XMEGA Programmer",
            'tip':
            "Open XMEGA Programmer (ChipWhisperer-Lite Only)",
            'type':
            "menu",
            "action":
            lambda _: self.getCwliteXMEGA().show()
        }, {
            'name':
            "CW-Lite AVR Programmer",
            'tip':
            "Open AVR Programmer (ChipWhisperer-Lite Only)",
            'type':
            "menu",
            "action":
            lambda _: self.getCwliteAVR().show()
        }, {
            'name':
            'Serial STM32F Programmer',
            'tip':
            "Open STM32F Programmer (Serial/ChipWhisperer)",
            'type':
            "menu",
            "action":
            lambda _: self.getSerialSTM32F().show()
        }])

    def get_possible_devices(self, idProduct):
        return self._cwusb.get_possible_devices(idProduct=idProduct)

    def con(self, *args, **kwargs):
        return self._cwusb.con(*args, **kwargs)

    # def __del__(self):
    #     print "here"

    def dis(self):
        if self.params is not None:
            self.getParams().delete()
        self.params = None
        # gc.collect()
        # print sys.getrefcount(self)
        # print gc.get_referrers(self)

    def usbdev(self):
        return self._cwusb

    def getCwliteXMEGA(self):
        if not hasattr(self, 'cwliteXMEGA'):
            self.cwliteXMEGA = XMEGAProgrammerDialog()
        return self.cwliteXMEGA

    def getCwliteAVR(self):
        if not hasattr(self, 'cwliteAVR'):
            self.cwliteAVR = AVRProgrammerDialog()
        return self.cwliteAVR

    def getSerialSTM32F(self):
        if not hasattr(self, 'serialSTM32F'):
            self.serialSTM32F = STM32FProgrammerDialog()
        return self.serialSTM32F
Ejemplo n.º 19
0
class CWNano(ScopeTemplate, Plugin, util.DisableNewAttr):
    """CWNano scope object.

    This class contains the public API for the CWNano hardware. It includes
    specific settings for each of these devices.

    To connect to one of these devices, the easiest method is

    This code will automatically detect an attached ChipWhisperer device and
    connect to it.

    For more help about scope settings, try help() on each of the ChipWhisperer
    scope submodules:
        scope.adc
        scope.io
        scope.glitch
    """

    _name = "ChipWhisperer Nano"

    REQ_ARM = 0x29
    REQ_SAMPLES = 0x2A

    def __init__(self):
        ScopeTemplate.__init__(self)
        self._is_connected = False

        self.params.init()

        self._cwusb = NAEUSB()
        self.ser = self._cwusb
        self.scopetype = self
        self.dev = self

        self.xmega = XMEGAPDI(self._cwusb)
        self.avr = AVRISP(self._cwusb)
        self.usart = USART(self._cwusb)
        self.serialstm32f = STM32FSerial(cwserial=self.usart)
        self.serialstm32f.scope = self
        self.io = GPIOSettings(self._cwusb)
        self.adc = ADCSettings(self._cwusb)
        self.glitch = GlitchSettings(self._cwusb)
        self._timeout = 2

        self._lasttrace = None

        self.getParams().addChildren([
            {'name':"CW-Lite XMEGA Programmer", 'tip':"Open XMEGA Programmer (ChipWhisperer-Lite Only)", 'type':"menu", "action":lambda _:self.getCwliteXMEGA().show()},
            {'name':"CW-Lite AVR Programmer", 'tip':"Open AVR Programmer (ChipWhisperer-Lite Only)", 'type':"menu", "action":lambda _:self.getCwliteAVR().show()},
            {'name':'Serial STM32F Programmer', 'tip':"Open STM32F Programmer (Serial/ChipWhisperer)", 'type':"menu", "action":lambda _:self.getSerialSTM32F().show()}
        ])

        self.disable_newattr()

    def getCurrentScope(self):
        return self

    def _con(self):
        self._cwusb.con(idProduct=[0xACE0])
        self.disable_newattr()
        self._is_connected = True
        return True

    def _dis(self):
        self.enable_newattr()
        self._is_connected = False
        return True

    def arm(self):
        """Arm the ADC, the trigger will be GPIO4 rising edge (fixed trigger)."""
        if self.connectStatus.value() is False:
            raise Warning("Scope \"" + self.getName() + "\" is not connected. Connect it first...")

        self._cwusb.sendCtrl(self.REQ_ARM, 1)


    def capture(self):
        """Raises IOError if unknown failure, returns 'True' if timeout, 'False' if no timeout"""

        starttime = datetime.datetime.now()
        while self._cwusb.readCtrl(self.REQ_ARM, dlen=1)[0] == 0:
            # Wait for a moment before re-running the loop
            time.sleep(0.05)
            diff = datetime.datetime.now() - starttime

            # If we've timed out, don't wait any longer for a trigger
            if (diff.total_seconds() > self._timeout):
                logging.warning('Timeout in cwnano capture()')
                return True

        self._lasttrace = self._cwusb.cmdReadMem(0, self.adc.samples)

        self._lasttrace = np.array(self._lasttrace) / 256.0 - 0.5

        self.newDataReceived(0, self._lasttrace, 0, self.adc.clk_freq)

        return False


    def getLastTrace(self):
        """Return the last trace captured with this scope.
        """
        return self._lasttrace


    def _dict_repr(self):
        dict = OrderedDict()
        dict['io']    = self.io._dict_repr()
        dict['adc']   = self.adc._dict_repr()
        dict['glitch'] = self.glitch._dict_repr()
        return dict

    def __repr__(self):
        # Add some extra information about ChipWhisperer type here
        if self._is_connected:
            ret = "ChipWhisperer Nano Device\n"
            return ret + dict_to_str(self._dict_repr())
        else:
            ret = "ChipWhisperer Nano device (disconnected)"
            return ret

    def __str__(self):
        return self.__repr__()

    def get_possible_devices(self, idProduct):
        return self._cwusb.get_possible_devices(idProduct=idProduct)

    def usbdev(self):
        return self._cwusb

    def getCwliteXMEGA(self):
        if not hasattr(self, 'cwliteXMEGA'):
            self.enable_newattr()
            self.cwliteXMEGA = XMEGAProgrammerDialog()
            self.disable_newattr()
        return self.cwliteXMEGA

    def getCwliteAVR(self):
        if not hasattr(self, 'cwliteAVR'):
            self.enable_newattr()
            self.cwliteAVR = AVRProgrammerDialog()
            self.disable_newattr()
        return self.cwliteAVR

    def getSerialSTM32F(self):
        if not hasattr(self, 'serialSTM32F'):
            self.enable_newattr()
            self.serialSTM32F = STM32FProgrammerDialog()
            self.disable_newattr()
        return self.serialSTM32F
Ejemplo n.º 20
0
class CW305(TargetTemplate):
    """CW305 target object.

    This class contains the public API for the CW305 hardware.
    To connect to the CW305, the easiest method is::

        import chipwhisperer as cw
        scope = cw.scope()

        # scope can also be None here, unlike with the default SimpleSerial
        target = cw.target(scope,
                targets.CW305, bsfile=<valid FPGA bitstream file>)

    As of CW5.3, you can also specify the following::

        # can also be '35t'
        target = cw.target(scope, fpga_id='100t')

    To automatically program with the example AES bitstream

    If you're using the reference designs, typical configuration
    requires you to set the FPGA VCC-INT voltage and enable and 
    set the clock via the PLL. You'll probably also want to
    disable the USB clock during encryption to reduce noise::

        target.vccint_set(1.0) #set VCC-INT to 1V
        
        target.pll.pll_enable_set(True) #Enable PLL chip
        target.pll.pll_outenable_set(False, 0) # Disable unused PLL0
        target.pll.pll_outenable_set(True, 1)  # Enable PLL 
        target.pll.pll_outenable_set(False, 2) # Disable unused PLL2

        # optional, but reduces power trace noise
        target.clkusbautooff = True
        target.clksleeptime = 1 # 1ms typically good for sleep


    Don't forget to clock the ChipWhisperer ADC off the FPGA instead
    of the internal clock::

        scope.clock.adc_src = "extclk_x4"
        scope.clock.reset_adc() # make sure the DCM is locked

    Note that connecting to the CW305 includes programming the CW305 FPGA,
    if it isn't already.

    For more help about CW305 settings, try help() on this CW305 submodule:

       * target.pll
    """

    _name = "ChipWhisperer CW305 (Artix-7)"
    BATCHRUN_START = 0x1
    BATCHRUN_RANDOM_KEY = 0x2
    BATCHRUN_RANDOM_PT = 0x4

    def __init__(self):
        TargetTemplate.__init__(self)
        self._naeusb = NAEUSB()
        self.pll = PLLCDCE906(self._naeusb, ref_freq=12.0E6)
        self.fpga = FPGA(self._naeusb)

        self.hw = None
        self.oa = None

        self._woffset = 0x400
        self._woffset_sam3U = 0x000

        self._clksleeptime = 1
        self._clkusbautooff = True
        self.last_key = bytearray([0] * 16)

    def _getNAEUSB(self):
        return self._naeusb

    def fpga_write(self, addr, data):
        """Write to an address on the FPGA

        Args:
            addr (int): Address to write to
            data (list): Data to write to addr

        Raises:
            IOError: User attempted to write to a read-only location
        """
        if addr < self._woffset:
            raise IOError("Write to read-only location: 0x%04x" % addr)

        return self._naeusb.cmdWriteMem(addr, data)

    def fpga_read(self, addr, readlen):
        """Read from an address on the FPGA

        Args:
            addr (int): Address to read from
            readlen (int): Length of data to read

        Returns:
            Requested data as a list
        """
        if addr > self._woffset:
            logging.info(
                'Read from write address, confirm this is not an error')

        data = self._naeusb.cmdReadMem(addr, readlen)
        return data

    def usb_clk_setenabled(self, status):
        """ Turn on or off the Data Clock to the FPGA """
        if status:
            self._naeusb.sendCtrl(CW305_USB.REQ_SYSCFG, CW305_USB.SYSCFG_CLKON)
        else:
            self._naeusb.sendCtrl(CW305_USB.REQ_SYSCFG,
                                  CW305_USB.SYSCFG_CLKOFF)

    def usb_trigger_toggle(self, _=None):
        """ Toggle the trigger line high then low """
        self._naeusb.sendCtrl(CW305_USB.REQ_SYSCFG, CW305_USB.SYSCFG_TOGGLE)

    def vccint_set(self, vccint=1.0):
        """ Set the VCC-INT for the FPGA """

        # print "vccint = " + str(vccint)

        if (vccint < 0.6) or (vccint > 1.15):
            raise ValueError("VCC-Int out of range 0.6V-1.1V")

        # Convert to mV
        vccint = int(vccint * 1000)
        vccsetting = [vccint & 0xff, (vccint >> 8) & 0xff, 0]

        # calculate checksum
        vccsetting[2] = vccsetting[0] ^ vccsetting[1] ^ CW305_USB.VCCINT_XORKEY

        self._naeusb.sendCtrl(CW305_USB.REQ_VCCINT, 0, vccsetting)

        resp = self._naeusb.readCtrl(CW305_USB.REQ_VCCINT, dlen=3)
        if resp[0] != 2:
            raise IOError("VCC-INT Write Error, response = %d" % resp[0])

    def vccint_get(self):
        """ Get the last set value for VCC-INT """

        resp = self._naeusb.readCtrl(CW305_USB.REQ_VCCINT, dlen=3)
        return float(resp[1] | (resp[2] << 8)) / 1000.0

    def _con(self, scope=None, bsfile=None, force=False, fpga_id=None):
        """Connect to CW305 board, and download bitstream.

        If the target has already been programmed it skips reprogramming
        unless forced.

        Args:
            scope (ScopeTemplate): An instance of a scope object.
            bsfile (path): The path to the bitstream file to program the FPGA with.
            force (bool): Whether or not to force reprogramming.
            fpga_id (string): '100t', '35t', or None. If bsfile is None and fpga_id specified,
                              program with AES firmware for fpga_id
        """

        from datetime import datetime
        self._naeusb.con(idProduct=[0xC305])
        if not fpga_id is None:
            if fpga_id not in ('100t', '35t'):
                raise ValueError(f"Invalid fpga {fpga_id}")
        self._fpga_id = fpga_id
        if self.fpga.isFPGAProgrammed() == False or force:
            if bsfile is None:
                if not fpga_id is None:
                    from chipwhisperer.hardware.firmware.cw305 import getsome
                    bsdata = getsome(f"AES_{fpga_id}.bit")
                    starttime = datetime.now()
                    status = self.fpga.FPGAProgram(bsdata,
                                                   exceptOnDoneFailure=False)
                    stoptime = datetime.now()
                    if status:
                        logging.info('FPGA Config OK, time: %s' %
                                     str(stoptime - starttime))
                    else:
                        logging.warning(
                            'FPGA Done pin failed to go high, check bitstream is for target device.'
                        )
                else:
                    print("No FPGA Bitstream file specified.")
            elif not os.path.isfile(bsfile):
                print(("FPGA Bitstream not configured or '%s' not a file." %
                       str(bsfile)))
            else:
                starttime = datetime.now()
                status = self.fpga.FPGAProgram(open(bsfile, "rb"),
                                               exceptOnDoneFailure=False)
                stoptime = datetime.now()
                if status:
                    logging.info('FPGA Config OK, time: %s' %
                                 str(stoptime - starttime))
                else:
                    logging.warning(
                        'FPGA Done pin failed to go high, check bitstream is for target device.'
                    )
        self.usb_clk_setenabled(True)
        self.fpga_write(0x100 + self._woffset, [0])
        self.pll.cdce906init()

    def _dis(self):
        if self._naeusb:
            self._naeusb.close()

    def checkEncryptionKey(self, key):
        """Validate encryption key"""
        return key

    def loadEncryptionKey(self, key):
        """Write encryption key to FPGA"""
        self.key = key
        key = key[::-1]
        self.fpga_write(0x100 + self._woffset, key)

    def loadInput(self, inputtext):
        """Write input to FPGA"""
        self.input = inputtext
        text = inputtext[::-1]
        self.fpga_write(0x200 + self._woffset, text)

    def is_done(self):
        """Check if FPGA is done"""
        result = self.fpga_read(0x50, 1)[0]

        if result == 0x00:
            return False
        else:
            # Clear trigger
            self.fpga_write(0x40 + self._woffset, [0])
            # LED Off
            self.fpga_write(0x10 + self._woffset, [0])
            return True

    isDone = camel_case_deprecated(is_done)

    def readOutput(self):
        """"Read output from FPGA"""
        data = self.fpga_read(0x200, 16)
        data = data[::-1]
        #self.newInputData.emit(util.list2hexstr(data))
        return data

    @property
    def latest_fw(self):
        cw_type = self._getCWType()
        if cw_type == "cwlite":
            from chipwhisperer.hardware.firmware.cwlite import fwver
        elif cw_type == "cw1200":
            from chipwhisperer.hardware.firmware.cw1200 import fwver

        ret = OrderedDict()
        return {"major": fwver[0], "minor": fwver[1]}

    @property
    def fw_version(self):
        a = self._naeusb.readFwVersion()
        return {"major": a[0], "minor": a[1], "debug": a[2]}

    @property
    def clkusbautooff(self):
        """ If set, the USB clock is automatically disabled on capture.

        The USB clock is re-enabled after self.clksleeptime milliseconds.

        Reads/Writes to the FPGA will not be possible until after
        the USB clock is reenabled, meaning :code:`usb_trigger_toggle()`
        must be used to trigger the FPGA to perform an encryption.

        :Getter: Gets whether to turn off the USB clock on capture

        :Setter: Sets whether to turn off the USB clock on capture
        """
        return self._clkusbautooff

    @clkusbautooff.setter
    def clkusbautooff(self, state):
        self._clkusbautooff = state

    @property
    def clksleeptime(self):
        """ Time (in milliseconds) that the USB clock is disabled for upon
        capture, if self.clkusbautooff is set.
        """
        return self._clksleeptime

    @clksleeptime.setter
    def clksleeptime(self, value):
        self._clksleeptime = value

    def go(self):
        """Disable USB clock (if requested), perform encryption, re-enable clock"""
        if self.clkusbautooff:
            self.usb_clk_setenabled(False)

        #LED On
        self.fpga_write(0x10 + self._woffset, [0x01])

        time.sleep(0.001)
        self.usb_trigger_toggle()
        # self.FPGAWrite(0x100, [1])
        # self.FPGAWrite(0x100, [0])

        if self.clkusbautooff:
            time.sleep(self.clksleeptime / 1000.0)
            self.usb_clk_setenabled(True)

    def simpleserial_read(self, cmd, pay_len, end='\n', timeout=250, ack=True):
        """Read data from target

        Mimics simpleserial protocol of serial based targets

        Args:
            cmd (str): Command to ues. Only accepts 'r' for now.
            pay_len: Unused
            end: Unused
            timeout: Unused
            ack: Unused

        Returns: Value from Crypto output register

        .. versionadded:: 5.1
            Added simpleserial_read to CW305
        """
        if cmd == "r":
            return self.readOutput()
        else:
            raise ValueError("Unknown command {}".format(cmd))

    def simpleserial_write(self, cmd, data, end=None):
        """Write data to target.

        Mimics simpleserial protocol of serial based targets.

        Args:
            cmd (str): Command to use. Target supports 'p' (write plaintext),
                and 'k' (write key).
            data (bytearray): Data to write to target
            end: Unused

        Raises:
            ValueError: Unknown command

        .. versionadded:: 5.1
            Added simpleserial_write to CW305
        """
        if cmd == 'p':
            self.loadInput(data)
            self.go()
        elif cmd == 'k':
            self.loadEncryptionKey(data)
        else:
            raise ValueError("Unknown command {}".format(cmd))

    def set_key(self, key, ack=False, timeout=250):
        """Checks if key is different from the last one sent. If so, send it.

        Args:
            key (bytearray):  key to send
            ack: Unused
            timeout: Unused

        .. versionadded:: 5.1
            Added set_key to CW305
        """
        if self.last_key != key:
            self.last_key = key
            self.simpleserial_write('k', key)

    def batchRun(self,
                 batchsize=1024,
                 random_key=True,
                 random_pt=True,
                 seed=None):
        """
            Run multiple encryptions on random data

            Args:
                batchsize (int): The number of encryption to run (default 1024).
                random_key (bool): True if the key is random (default False).
                random_pt (bool): True if the plaintext are random (default True).
                seed (int): random int32 for the PRG.
        """
        if seed is None:
            seed = random.randint(0, 2**32)

        data = []
        data.extend(
            packuint32(1 | (random_key << 1) | (random_pt << 2)
                       | (batchsize << 16)))
        data.extend(packuint32(seed))
        self.sam3u_write(0, data)

        # generate the inputs
        if random_key:
            key = [[0 for x in range(16)] for y in range(batchsize)]
        else:
            key = None

        if random_pt:
            pt = [[0 for x in range(16)] for y in range(batchsize)]
        else:
            pt = None

        for b in range(batchsize):
            if random_key:
                for j in range(16):
                    key[b][15 - j] = seed >> 24
                    seed += ((seed * seed) & 0xffffffff) | 0x5
                    seed &= 0xffffffff
            if random_pt:
                for j in range(16):
                    pt[b][15 - j] = seed >> 24
                    seed += ((seed * seed) & 0xffffffff) | 0x5
                    seed &= 0xffffffff
        return key, pt

    def sam3u_write(self, addr, data):
        """Write to an address on the FPGA

        Args:
            addr (int): Address to write to
            data (list): Data to write to addr

        Raises:
            IOError: User attempted to write to a read-only location
        """
        if addr < self._woffset_sam3U:
            raise IOError("Write to read-only location: 0x%04x" % addr)
        if len(data) > (256 + addr):
            raise IOError("Write will overflow at location: 0x%04x" % (256))

        return self._naeusb.cmdWriteSam3U(addr, data)

    @fw_ver_required(0, 30)
    def spi_mode(self, enable=True, timeout=200, bsfile=None):
        """Enter programming mode for the onboard SPI chip
        
        Reprograms the FPGA with the appropriate bitstream and 
        returns an object with which to program the CW305 SPI chip
        (see documentation on the returned object for more info)

        Args:
            enable (bool): Enable the SPI interface before returning it. Defaults to True
            timeout (int): USB timeout in ms. Defaults to 200.
            bsfile (string): If not None, program with a bitstream pointed to by bsfile.
                             If None, program with SPI passthrough bitstream for the chip
                             specified during connection (or cw.target()) 

        Returns:
            A FPGASPI object which can be used to erase/program/verify/read the SPI
            chip on the CW305.
        """
        from datetime import datetime
        if self._fpga_id is None and bsfile is None:
            logging.warning(
                "CW305 requires passthrough bitstream to program SPI chip, but file/chip not specified"
            )
        else:
            bsdata = None
            if self._fpga_id:
                from chipwhisperer.hardware.firmware.cw305 import getsome
                bsdata = getsome(f"SPI_flash_{self._fpga_id}.bit")
            else:
                bsdata = open(bsfile, "rb")
            starttime = datetime.now()
            status = self.fpga.FPGAProgram(bsdata, exceptOnDoneFailure=False)
            stoptime = datetime.now()
            if status:
                logging.info('FPGA Config OK, time: %s' %
                             str(stoptime - starttime))
            else:
                logging.warning(
                    'FPGA Done pin failed to go high, check bitstream is for target device.'
                )

        spi = FPGASPI(self._naeusb, timeout)
        spi.enable_interface(enable)
        return spi
Ejemplo n.º 21
0
class TraceWhisperer():
    """ Trace interface object.

    This class contains the public API for the Arm Coresight trace sniffing
    hardware, which may exist on either the CW305 or the CW610 (PhyWhisperer)
    platform.

    To connect, the easiest method is::

        (a) CW305 (DesignStart) case:
        import chipwhisperer as cw
        from chipwhisperer.capture.trace.TraceWhisperer import TraceWhisperer
        scope = cw.scope()
        target = cw.target(scope, targets.CW305, bsfile=<valid FPGA bitstream file>)
        trace = TraceWhisperer(target, scope)

        (b) CW610 (PhyWhisperer) case:
        import chipwhisperer as cw
        from chipwhisperer.capture.trace.TraceWhisperer import TraceWhisperer
        scope = cw.scope()
        target = cw.target(scope)
        trace = TraceWhisperer(target)

    """

    _name = "TraceWhisperer"

    # must be in sync with firmware:
    regs = {
        'DWT_CTRL': '00',
        'DWT_COMP0': '01',
        'DWT_COMP1': '02',
        'ETM_CR': '03',
        'ETM_TESSEICR': '04',
        'ETM_TEEVR': '05',
        'ETM_TECR1': '06',
        'ETM_TRACEIDR': '07',
        'TPI_ACPR': '08',
        'TPI_SPPR': '09',
        'TPI_FFCR': '0a',
        'TPI_CSPSR': '0b',
        'ITM_TCR': '0c'
    }

    rule_length = [0] * 8

    longsync = [255, 255, 255, 127]
    shortsync = [255, 127]

    def __init__(self,
                 target,
                 scope,
                 defines_files=None,
                 bs='',
                 force_bitfile=False):
        """
        Args:
            target: SimpleSerial target
            scope: CW scope
            naeusb: NewAE USB interface
            platform (string): CW305 or CW610 (PhyWhisperer)
            defines_files (list of 2 strings): path to defines_trace.v and defines_pw.v
        """
        super().__init__()
        self._trace_port_width = 4
        self._base_target_clock = 7.384e6
        self._base_baud = 38400
        self._usb_clock = 96e6
        self._uart_clock = self._usb_clock * 2
        self.expected_verilog_defines = 107
        self.swo_mode = False
        self.board_rev = 4
        self._scope = scope
        # Detect whether we exist on CW305 or CW610 based on the target we're given:
        if target._name == 'Simple Serial':
            self.platform = 'CW610'
            self._ss = target
            self._naeusb = NAEUSB()
            self._naeusb.con(idProduct=[0xC610])
            # we're using the CW NAEUSB, which has no knowledge of PW firmware, so let's manually
            # check the FW version here:
            fw_latest = [1, 1]
            if self._naeusb.readFwVersion()[0] < fw_latest[0]:
                logging.warning(
                    'Your PhyWhisperer firmware is outdated - latest is %d.%d'
                    % (fw_latest[0], fw_latest[1]) +
                    '. Suggested to update firmware, as you may experience errors.'
                )

            self._fpga = FPGA(self._naeusb)
            if not self._fpga.isFPGAProgrammed() or force_bitfile:
                if not bs:
                    bs = pkg_resources.resource_filename(
                        'chipwhisperer',
                        'hardware/firmware/tracewhisperer_top.bit')
                self._fpga.FPGAProgram(open(bs, 'rb'),
                                       exceptOnDoneFailure=False)
        else:
            self.platform = 'CW305'
            self._ss = cw.target(scope)
            self._naeusb = target._naeusb

        self.slurp_defines(defines_files)
        self._set_defaults()

    def _set_defaults(self):
        """ Set some registers which for various reasons don't reset to what we want them to.
        """
        self.fpga_write(self.REG_CAPTURE_WHILE_TRIG, [1])
        # TODO- temporary for development:
        self.fpga_write(self.REG_REVERSE_TRACEDATA, [0])
        #self.set_reg('TPI_ACPR', '00000000')

    def reset_fpga(self):
        """ Reset FPGA registers to defaults, use liberally to clear incorrect states.
            On the CW305, this resets the full FPGA, including the Arm core.
        """
        self.fpga_write(self.REG_RESET_REG, [1])
        self.fpga_write(self.REG_RESET_REG, [0])
        self._set_defaults()

    def slurp_defines(self, defines_files=None):
        """ Parse Verilog defines file so we can access register and bit
        definitions by name and avoid 'magic numbers'.
        """
        self.verilog_define_matches = 0
        if not defines_files:
            defines_files = [
                pkg_resources.resource_filename(
                    'chipwhisperer', 'capture/trace/defines/defines_trace.v'),
                pkg_resources.resource_filename(
                    'chipwhisperer', 'capture/trace/defines/defines_pw.v')
            ]
        for i, defines_file in enumerate(defines_files):
            defines = open(defines_file, 'r')
            define_regex_base = re.compile(r'`define')
            define_regex_reg = re.compile(r'`define\s+?REG_')
            define_regex_radix = re.compile(
                r'`define\s+?(\w+).+?\'([bdh])([0-9a-fA-F]+)')
            define_regex_noradix = re.compile(r'`define\s+?(\w+?)\s+?(\d+?)')
            for define in defines:
                if define_regex_base.search(define):
                    reg = define_regex_reg.search(define)
                    match = define_regex_radix.search(define)
                    if reg:
                        if i == 0:
                            block_offset = self.TRACE_REG_SELECT << 6
                        else:
                            block_offset = self.MAIN_REG_SELECT << 6
                    else:
                        block_offset = 0
                    if match:
                        self.verilog_define_matches += 1
                        if match.group(2) == 'b':
                            radix = 2
                        elif match.group(2) == 'h':
                            radix = 16
                        else:
                            radix = 10
                        setattr(self, match.group(1),
                                int(match.group(3), radix) + block_offset)
                    else:
                        match = define_regex_noradix.search(define)
                        if match:
                            self.verilog_define_matches += 1
                            setattr(self, match.group(1),
                                    int(match.group(2), 10) + block_offset)
                        else:
                            logging.warning("Couldn't parse line: %s", define)
            defines.close()
        # make sure everything is cool:
        assert self.verilog_define_matches == self.expected_verilog_defines, "Trouble parsing Verilog defines file (%s): didn't find the right number of defines; expected %d, got %d" % (
            defines_file, self.expected_verilog_defines,
            self.verilog_define_matches)

    def set_trace_mode(self, mode, swo_div=8, acpr=0):
        """Set trace or SWO mode. SWO mode is only available on CW610 platform.
        For SWO mode, we also adjust the target clock to match the SWO parameters.
        Args:
            mode (string): 'trace' or 'swo'
            swo_div (int): number of 96 MHz clock cycles per SWO bit (SWO mode only)
            acpr (int): value for TPI.ACPR register (SWO mode only)
        """
        if mode == 'trace':
            self.swo_mode = False
            self.set_reg('TPI_SPPR', '00000000')
            self.fpga_write(self.REG_SWO_ENABLE, [0])
        elif mode == 'swo':
            if self.platform == 'CW305':
                raise ValueError('CW305 does not support SWO mode')
            self.swo_mode = True
            self.set_reg('TPI_SPPR', '00000002')
            self.set_reg('TPI_ACPR', '%08x' % acpr)
            self.fpga_write(
                self.REG_SWO_BITRATE_DIV, [swo_div - 1]
            )  # not a typo: hardware requires -1; doing this is easier than fixing the hardware
            self.fpga_write(self.REG_SWO_ENABLE, [1])
            # Next we set the target clock and update CW baud rate accordingly:
            new_target_clock = int(self._uart_clock / (swo_div * (acpr + 1)))
            self._scope.clock.clkgen_freq = new_target_clock
            self._ss.baud = int(self._base_baud *
                                (new_target_clock / self._base_target_clock))
            self.swo_target_clock_ratio = self._usb_clock / new_target_clock
            logging.info(
                "Ensure target is in SWD mode, e.g. using jtag_to_swd().")
        else:
            logging.error('Invalid mode %s: specify "trace" or "swo"', mode)

    def set_capture_mode(self, mode, counts=0):
        """Determine the duration of the trace capture.
        Args:
            mode (string): 'while_trig' or 'count_cycles' or 'count_writes'
            counts (int): number of cycles (mode == 'count_cycles') or writes (mode == 'count_writes') to capture for
                          (0 = capture until full)
        """
        if mode == 'while_trig':
            self.fpga_write(self.REG_CAPTURE_WHILE_TRIG, [1])
        elif mode == 'count_cycles':
            self.fpga_write(self.REG_CAPTURE_WHILE_TRIG, [0])
            self.fpga_write(self.REG_COUNT_WRITES, [0])
            self.fpga_write(self.REG_CAPTURE_LEN,
                            int.to_bytes(counts, length=4, byteorder='little'))
        elif mode == 'count_writes':
            self.fpga_write(self.REG_CAPTURE_WHILE_TRIG, [0])
            self.fpga_write(self.REG_COUNT_WRITES, [1])
            self.fpga_write(self.REG_CAPTURE_LEN,
                            int.to_bytes(counts, length=4, byteorder='little'))
        else:
            logging.error('Invalid mode %s')

    def set_board_rev(self, rev):
        """For development only - the rev3 board has different pin assignments. 
        The board revision must be set correctly both here and in the FPGA. This convenience
        function ensures both are set properly.
        Args: 
            rev (int): 3 or 4
        """
        assert rev in [3, 4]
        self.board_rev = rev
        self.fpga_write(self.REG_BOARD_REV, [rev])

    def jtag_to_swd(self):
        """Switch to SWD mode by driving the JTAG-to-SWD sequence on TMS/TCK.
        (reference: https://developer.arm.com/documentation/ka001179/1-0/)
        Args: none
        """
        if self.board_rev == 3:
            self.tms_bit = 0
            self.tck_bit = 2
        elif self.board_rev == 4:
            self.tms_bit = 0
            self.tck_bit = 1
        self.fpga_write(self.REG_USERIO_PWDRIVEN,
                        [(1 << self.tms_bit) + (1 << self.tck_bit)])
        self.fpga_write(self.REG_USERIO_DATA, [1 << self.tms_bit])
        self._line_reset()
        self._send_tms_byte(0x9e)
        self._send_tms_byte(0xe7)
        self._line_reset()
        self.fpga_write(self.REG_USERIO_DATA, [1 << self.tms_bit])
        self.fpga_write(self.REG_USERIO_PWDRIVEN, [0])

    def _send_tms_byte(self, data):
        """Bit-bang 8 bits of data on TMS/TCK (LSB first).
        Args: 
            data (int): 8 bits data to send.
        """
        for i in range(8):
            bit = (data & 2**i) >> i
            self.fpga_write(self.REG_USERIO_DATA, [bit << self.tms_bit])
            self.fpga_write(self.REG_USERIO_DATA,
                            [(1 << self.tck_bit) + (bit << self.tms_bit)])

    def _line_reset(self, num_bytes=8):
        """Bit-bang a line reset on TMS/TCK.
        Args: none
        """
        for i in range(num_bytes):
            self._send_tms_byte(0xff)

    def check_clocks(self):
        """Check that PLLs are locked.
        Args: none
        """
        locks = self.fpga_read(self.REG_MMCM_LOCKED, 1)[0]
        assert (locks & 2) == 2, 'Trigger/UART clock not locked!'
        if not self.swo_mode and self.platform == 'CW610':
            assert (locks & 1) == 1, 'Trace clock not locked!'

    def simpleserial_write(self, cmd, data, printresult=False):
        """Convenience function to send a simpleserial command to the simpleserial target,
        and optionally fetch and print the result.
        """
        self._ss.simpleserial_write(cmd, data)
        if printresult:
            time.sleep(0.6)  # ECC is slow!
            print(self._ss.read().split('\n')[0])

    def set_reg(self, reg, data, printresult=False):
        """Set a Cortex debug register
        Args:
            reg (string): Register to write. See self.regs for available registers.
            data (string): 8-character hex string, value to write to
                           specified register (e.g. '1000F004')
        """
        if reg in self.regs:
            data = self.regs[reg] + data
            self._ss.simpleserial_write('s', util.hexStrToByteArray(data))
            time.sleep(0.1)
            if printresult:
                print(self._ss.read().split('\n')[0])
        else:
            logging.error('Register %s does not exist.', reg)

    def get_reg(self, reg):
        """Reads a Cortex debug register
        Args:
            reg (string): Register to read. See self.regs for available registers.
        """
        if reg in self.regs:
            data = self.regs[reg] + '00000000'
            self._ss.simpleserial_write('g', util.hexStrToByteArray(data))
            time.sleep(0.1)
            return self._ss.read().split('\n')[0][1:]
        else:
            logging.error('Register %s does not exist.', reg)

    def set_pattern_match(self, index, pattern, mask=[0xff] * 8):
        """Sets pattern match and mask parameters

        Args:
            index: match index [0-7]
            pattern: list of 8-bit integers, pattern match value
            mask: list of 8-bit integers, pattern mask value

        """
        self.fpga_write(self.REG_TRACE_PATTERN0 + index, pattern)
        self.fpga_write(self.REG_TRACE_MASK0 + index, mask)
        # count trailing zeros in the mask, as these determine how much time elapses from
        # the start of receiving a trace packet, until the match is determined -- so that the
        # recorded timestamp can be rolled back to when the trace packet began
        trailing_zeros = 0
        for m in mask[::-1]:
            if not m:
                trailing_zeros += 1
        self.rule_length[index] = 8 - trailing_zeros

    def arm_trace(self):
        """Arms trace sniffer for capture; also checks sync status.
        """
        self.fpga_write(self.REG_ARM, [1])
        self.synced()

    def synced(self):
        """Checks that trace trigger module is synchronized.
        """
        assert self.fpga_read(self.REG_SYNCHRONIZED,
                              1)[0] == 1, 'Not synchronized!'

    def resync(self):
        """Force trace sniffer to resynchronize (using sync frames that are
        continously emitted on the parallel trace port). Failure could be from
        absence of a trace clock, or mis-sampling of trace data due to
        setup/hold violations (clock edge too close to data edge).
        """
        self.fpga_write(self.REG_TRACE_RESET_SYNC, [1])
        self.synced()

    def is_done(self):
        """Calls SimpleSerial target's is_done().
        """
        return self._ss.is_done()

    def fpga_write(self, addr, data):
        """Write to an FPGA register.

        Args:
            addr (int): Address to write to
            data (list): Data to write to addr
        """
        # on CW305, change word address to byte address (CW610 uses addressing differently)
        if self.platform == 'CW305':
            addr = addr << 7
        return self._naeusb.cmdWriteMem(addr, data)

    def fpga_read(self, addr, readlen=4):
        """Read from an FPGA register.

        Args:
            addr (int): Address to read from
            readlen (int): Length of data to read

        Returns:
            Requested data as a list
        """
        # on CW305, change word address to byte address (CW610 uses addressing differently)
        if self.platform == 'CW305':
            addr = addr << 7
        data = self._naeusb.cmdReadMem(addr, readlen)
        return data

    def check_fifo_errors(self, underflow=0, overflow=0):
        """Check whether an underflow or overflow occured on the capture FIFO.
        
        Args:
            underflow (int, optional): expected status, 0 or 1
            overflow (int, optional): expected status, 0 or 1
        """
        status = self.fpga_read(self.REG_SNIFF_FIFO_STAT, 1)[0]
        fifo_underflow = (status & 2) >> 1
        fifo_overflow = (status & 16) >> 4
        assert fifo_underflow == underflow
        assert fifo_overflow == overflow

    def fifo_empty(self):
        """Returns True if the capture FIFO is empty, False otherwise.
        """
        if self.fpga_read(self.REG_SNIFF_FIFO_STAT, 1)[0] & 1:
            return True
        else:
            return False

    def get_fpga_buildtime(self):
        """Returns date and time when FPGA bitfile was generated.
        """
        raw = self.fpga_read(addr=self.REG_BUILDTIME, readlen=4)
        # definitions: Xilinx XAPP1232
        day = raw[3] >> 3
        month = ((raw[3] & 0x7) << 1) + (raw[2] >> 7)
        year = ((raw[2] >> 1) & 0x3f) + 2000
        hour = ((raw[2] & 0x1) << 4) + (raw[1] >> 4)
        minute = ((raw[1] & 0xf) << 2) + (raw[0] >> 6)
        return "FPGA build time: {}/{}/{}, {}:{}".format(
            month, day, year, hour, minute)

    def get_fw_buildtime(self):
        """Returns date and time when target FW was compiled.
        """
        self._ss.simpleserial_write('i', b'')
        time.sleep(0.1)
        return self._ss.read().split('\n')[0]

    def get_target_name(self):
        """Returns project-specific 'name' embedded in target bitfile
        """
        nameb = self.fpga_read(self.REG_NAME, 8)
        names = ''
        for i in nameb:
            names += hex(i)[2:]
        return bytearray.fromhex(names).decode()

    def test_itm(self, port=1):
        """Print test string via ITM using specified port number.

        Args:
            port (int): ITM port number to use.

        """
        self._ss.simpleserial_write('t', bytearray([port]))
        time.sleep(0.1)
        print(self._ss.read().split('\n')[0])

    def read_capture_data(self):
        """Read captured trace data.
        
        Returns: List of captured entries. Each list element is itself a 3-element list,
        containing the 3 bytes that make up a capture entry. Can be parsed by get_rule_match_times()
        or get_raw_trace_packets(). See defines_trace.v for definition of the FIFO
        data fields.

        """
        data = []
        starttime = time.time()

        # first check for FIFO to not be empty:
        assert self.fifo_empty() == False, 'FIFO is empty'

        # then check that no underflows or overflows occurred during capture:
        self.check_fifo_errors()

        while not self.fifo_empty():
            data.append(self.fpga_read(self.REG_SNIFF_FIFO_RD, 4)[1:4])

        if len(data):  # maybe we only got empty reads
            if data[-1][2] & 2**self.FE_FIFO_STAT_UNDERFLOW:
                logging.warning("Capture FIFO underflowed!")

        return data

    def print_raw_data(self, rawdata):
        """Prints collected raw data in hexadecimal. Raw data includes data
        type, timestamp, and payload. See defines_trace.v for bitfield
        definitions.
        """
        for e in rawdata:
            entry = 0
            entry += (e[2] & 0x3) << 16
            entry += e[1] << 8
            entry += e[0]
            print('%05x' % entry)

    def get_rule_match_times(self, rawdata, rawtimes=False, verbose=False):
        """Split raw capture data into data events and times, stat events and times.

        Args:
            rawdata: raw capture data, list of lists, e.g. obtained from read_capture_data()
            rawtimes:
                True: return reported times (obtained at the *end* of the pattern match)
                False: roll back times to the *start* of the pattern match
            verbose: print timestamped rules
        Returns:
            list of [time, rule index] tuples
        """

        times = []
        timecounter = 0
        lasttime = 0
        lastadjust = 0
        for raw in rawdata:
            command = raw[2] & 0x3
            if command == self.FE_FIFO_CMD_DATA:
                timecounter += raw[0]
                data = raw[1]
                rule = int(math.log2(data))
                if rawtimes:
                    adjust = 0
                else:
                    adjust = self.rule_length[rule] * self._cycles_per_byte()
                timecounter = timecounter - adjust + lastadjust
                delta = timecounter - lasttime
                lasttime = timecounter
                lastadjust = adjust
                if verbose:
                    print("%8d rule # %d, delta = %d" %
                          (timecounter, rule, delta))
                times.append([timecounter, rule])
            elif command == self.FE_FIFO_CMD_TIME:
                timecounter += raw[0] + (raw[1] << 8)
            elif command == self.FE_FIFO_CMD_STAT:
                raise ValueError(
                    "Unexpected STAT command, not supported by this method; maybe try get_raw_trace_packets() instead?"
                )
            elif command == self.FE_FIFO_CMD_STRM:
                pass
        return times

    def _cycles_per_byte(self):
        """Returns number of clock cycles needed to send one byte of trace
        data over the trace or SWO port.
        """
        if self.swo_mode:
            return 8
        else:
            return 8 / self._trace_port_width

    def get_raw_trace_packets(self, rawdata, removesyncs=True, verbose=False):
        """Split raw capture data into pseudo-frames, optionally suppressing
        sync frames (and using those sync frames as marker which is separating
        pseudo-frames). It's the best we can do without actually parsing the
        trace packets, which is best left to other tools!

        Args:
            rawdata: raw capture data, list of lists, e.g. obtained from read_capture_data()
            verbose: print timestamped packets
        Returns:
            list of pseudo-frames
        """

        pseudoframes = []
        pseudoframe = []
        timecounter = 0
        lasttime = 0
        for raw in rawdata:
            command = raw[2] & 0x3
            if command == self.FE_FIFO_CMD_STAT:
                timecounter += raw[0]
                data = raw[1]
                if not len(pseudoframe):
                    starttime = timecounter
                pseudoframe.append(data)

                if removesyncs:
                    if pseudoframe[-len(self.longsync):] == self.longsync:
                        pseudoframe = pseudoframe[:-len(self.longsync)]
                        sync_removed = True
                        #print('Removed long')
                    elif pseudoframe[-len(self.shortsync):] == self.shortsync:
                        pseudoframe = pseudoframe[:-len(self.shortsync)]
                        sync_removed = True
                        #print('Removed short')
                    else:
                        sync_removed = False
                else:
                    sync_removed = False

                if sync_removed and len(pseudoframe):
                    pseudoframes.append([starttime, pseudoframe])
                    if verbose:
                        print("Pseudoframe: ", end='')
                        for b in pseudoframe:
                            print('%02x ' % b, end='')
                        print()
                    pseudoframe = []

                delta = timecounter - lasttime
                lasttime = timecounter

            elif command == self.FE_FIFO_CMD_TIME:
                timecounter += raw[0] + (raw[1] << 8)
            elif command == self.FE_FIFO_CMD_DATA:
                raise ValueError(
                    "Unexpected DATA command, not supported by this method; maybe try get_rule_match_times() instead?"
                )
            elif command == self.FE_FIFO_CMD_STRM:
                pass

        if not removesyncs:
            pseudoframes.append([starttime, pseudoframe])

        return pseudoframes

    def use_soft_trigger(self):
        """ Use target-generated trigger to initiate trace capture.
        """
        self.fpga_write(self.REG_SOFT_TRIG_ENABLE, [1])
        self.fpga_write(self.REG_SOFT_TRIG_PASSTHRU, [1])
        self.fpga_write(self.REG_PATTERN_TRIG_ENABLE, [0])

    def use_trace_trigger(self, rule=0):
        """ Use matching trace data to initiate trace capture.
        Args:
            rule (int): rule number to use
        """
        self.fpga_write(self.REG_SOFT_TRIG_ENABLE, [0])
        self.fpga_write(self.REG_SOFT_TRIG_PASSTHRU, [0])
        self.fpga_write(self.REG_PATTERN_TRIG_ENABLE, [2**rule])
        self.fpga_write(self.REG_TRIGGER_ENABLE, [1])
        # these can be customized but let's start you off with simple default values:
        self.fpga_write(self.REG_NUM_TRIGGERS, [1])
        self.fpga_write(self.REG_TRIGGER_WIDTH, [16])

    def set_isync_matches(self, addr0=0, addr1=0, match=None):
        """ Set exact PC address matching rules.
        Args:
            addr0 (int): Matching address 0 (DWT_COMP0)
            addr1 (int): Matching address 0 (DWT_COMP1)
            match:
                None: disable PC address match packets
                0: enable addr0 matching only
                1: enable addr1 matching only
                "both": enable both addr0 and addr1 matching
        """
        self.set_reg('DWT_COMP0', '%08x' % addr0)
        self.set_reg('DWT_COMP1', '%08x' % addr1)
        if match == None:
            self.set_reg('ETM_TEEVR', '00000000')
        elif match == 0:
            self.set_reg('ETM_TEEVR', '00000020')
        elif match == 1:
            self.set_reg('ETM_TEEVR', '00000021')
        elif match == 'both':
            self.set_reg('ETM_TEEVR', '000150a0')

    def set_periodic_pc_sampling(self,
                                 enable=1,
                                 cyctap=0,
                                 postinit=1,
                                 postreset=0):
        """ Set periodic PC sampling parameters. Enabling PC sampling through
        this method will start PC sampling *after* the target triggers, thereby
        ensuring that the resulting trace data can be parsed without trouble.
        Alternatively, you can set the DWT_CTRL register directly.
        Args:
            enable (int): enable or disable periodic PC sampling
            cyctap (int): DWT_CTRL.CYCTAP bit
            postinit (int): DWT_CTRL.POSTINIT bits
            postreset (int): DWT_CTRL.POSTRESET bits
        """
        self.simpleserial_write('c',
                                bytearray(
                                    [enable, cyctap, postinit, postreset]),
                                printresult=False)

    def write_raw_capture(self, raw, filename='raw.bin', presyncs=8):
        """Writes raw trace data to a file (which can be read by orbuculum).
        Prepends a number of sync frames to facilitate parsing.
        Args:
            raw (array): raw trace data as obtained from
                get_raw_trace_packets()
            filename (string): output file
            presyncs (int): number of long syncronization frames which are
                prepended to the collected trace data.
        """
        binout = open(filename, "wb")
        for i in range(presyncs):
            binout.write(bytes(self.longsync))
        for frame in raw:
            binout.write(bytes(frame[1]))
        binout.close()
Ejemplo n.º 22
0
class CWNano(ScopeTemplate, util.DisableNewAttr):
    """CWNano scope object.

    This class contains the public API for the CWNano hardware. It includes
    specific settings for each of these devices.

    To connect to one of these devices, the easiest method is::

        import chipwhisperer as cw
        scope = cw.scope(type=scopes.CWNano)

    Some sane default settings can be set using::

        scope.default_setup()

    For more help about scope settings, try help() on each of the ChipWhisperer
    scope submodules (scope.adc, scope.io, scope.glitch):

      * :attr:`scope.adc <.CWNano.adc>`
      * :attr:`scope.io <.CWNano.io>`
      * :attr:`scope.glitch <.CWNano.glitch>`
      * :meth:`scope.default_setup <.CWNano.default_setup>`
      * :meth:`scope.con <.CWNano.con>`
      * :meth:`scope.dis <.CWNano.dis>`
      * :meth:`scope.get_last_trace <.CWNano.get_last_trace>`
      * :meth:`scope.arm <.CWNano.arm>`
      * :meth:`scope.capture <.CWNano.capture>`
    """

    _name = "ChipWhisperer Nano"

    REQ_ARM = 0x29
    REQ_SAMPLES = 0x2A

    def __init__(self):
        ScopeTemplate.__init__(self)
        self._is_connected = False


        self._cwusb = NAEUSB()
        self.ser = self._cwusb
        self.scopetype = self
        self.dev = self

        self.xmega = XMEGAPDI(self._cwusb)
        self.avr = AVRISP(self._cwusb)
        self.usart = USART(self._cwusb)
        self.serialstm32f = STM32FSerial(cwserial=self.usart)
        self.serialstm32f.scope = self
        self.io = GPIOSettings(self._cwusb)
        self.adc = ADCSettings(self._cwusb)
        self.glitch = GlitchSettings(self._cwusb)
        self._timeout = 2

        self._lasttrace = None

        self.disable_newattr()

    def default_setup(self):
        """ Sets up sane capture defaults for this scope

          * 7.5MHz ADC clock
          * 7.5MHz output clock
          * 5000 capture samples
          * tio1 = serial rx
          * tio2 = serial tx
          * glitch module off

        .. versionadded:: 5.1
            Added default setup for CWNano
        """
        self.adc.clk_freq = 7.5E6
        self.io.clkout = 7.5E6
        self.adc.samples = 5000
        self.io.tio1 = "serial_rx"
        self.io.tio2 = "serial_tx"
        self.glitch.repeat = 0

    def getCurrentScope(self):
        return self

    def _getNAEUSB(self):
        return self._cwusb

    @property
    def sn(self):
        return self._cwusb.snum

    @property
    def latest_fw(self):
        from chipwhisperer.hardware.firmware.cwnano import fwver
        return {"major": fwver[0], "minor": fwver[1]}

    @property
    def fw_version(self):
        a = self._cwusb.readFwVersion()
        return {"major": a[0], "minor": a[1], "debug": a[2]}

    def _con(self, sn=None):
        try:
            possible_sn = self._cwusb.get_possible_devices(idProduct=[0xACE0])
            serial_numbers = []
            if len(possible_sn) > 1:
                if sn is None:
                    for d in possible_sn:
                        serial_numbers.append("sn = {} ({})".format(str(d['sn']), str(d['product'])))
                    raise Warning("Multiple ChipWhisperers detected. Please specify device from the following list using cw.scope(sn=<SN>): \n{}".format(serial_numbers))
            else:
                sn = None
            found_id = self._cwusb.con(idProduct=[0xACE0], serial_number=sn)
        except (IOError, ValueError):
            raise Warning("Could not connect to cwnano. It may have been disconnected, is in an error state, or is being used by another tool.")
        self.disable_newattr()
        self._is_connected = True
        return True

    def _dis(self):
        self.enable_newattr()
        self.usbdev().close()
        self._is_connected = False
        return True

    def arm(self):
        """Arm the ADC, the trigger will be GPIO4 rising edge (fixed trigger)."""
        with DelayedKeyboardInterrupt():
            if self.connectStatus is False:
                raise Warning("Scope \"" + self.getName() + "\" is not connected. Connect it first...")

            self._cwusb.sendCtrl(self.REQ_ARM, 1)


    def capture(self):
        """Raises IOError if unknown failure, returns 'True' if timeout, 'False' if no timeout"""

        with DelayedKeyboardInterrupt():
            starttime = datetime.datetime.now()
            while self._cwusb.readCtrl(self.REQ_ARM, dlen=1)[0] == 0:
                # Wait for a moment before re-running the loop
                time.sleep(0.001)
                diff = datetime.datetime.now() - starttime

                # If we've timed out, don't wait any longer for a trigger
                if (diff.total_seconds() > self._timeout):
                    logging.warning('Timeout in cwnano capture()')
                    return True

            self._lasttrace = self._cwusb.cmdReadMem(0, self.adc.samples)

            # can just keep rerunning this until it works I think
            i = 0
            while len(self._lasttrace) < self.adc.samples:
                logging.debug("couldn't read ADC data from Nano, retrying...")

                self._lasttrace = self._cwusb.cmdReadMem(0, self.adc.samples)
                i+= 1
                if i > 20:
                    logging.warning("Couldn't read trace data back from Nano")
                    return True
            self._lasttrace = np.array(self._lasttrace) / 256.0 - 0.5

            #self.newDataReceived(0, self._lasttrace, 0, self.adc.clk_freq)

            return False


    def get_last_trace(self):
        """Return the last trace captured with this scope.
        """
        return self._lasttrace

    getLastTrace = camel_case_deprecated(get_last_trace)


    def _dict_repr(self):
        dict = OrderedDict()
        dict['fw_version'] = self.fw_version
        dict['io']    = self.io._dict_repr()
        dict['adc']   = self.adc._dict_repr()
        dict['glitch'] = self.glitch._dict_repr()
        return dict

    def __repr__(self):
        # Add some extra information about ChipWhisperer type here
        if self._is_connected:
            ret = "ChipWhisperer Nano Device\n"
            return ret + dict_to_str(self._dict_repr())
        else:
            ret = "ChipWhisperer Nano device (disconnected)"
            return ret

    def __str__(self):
        return self.__repr__()

    def get_possible_devices(self, idProduct):
        return self._cwusb.get_possible_devices(idProduct=idProduct)

    def usbdev(self):
        return self._cwusb
Ejemplo n.º 23
0
class CW305(TargetTemplate):
    _name = "ChipWhisperer CW305 (Artix-7)"

    def __init__(self, parentParam=None):
        TargetTemplate.__init__(self, parentParam)
        self._naeusb = NAEUSB()
        self.pll = PLLCDCE906(self._naeusb, ref_freq = 12.0E6, parent=self)
        self.fpga = FPGA(self._naeusb)

        self.hw = None
        # self._fpgabs = QSettings().value("cw305-bitstream", '')
        self.oa = None

        self._woffset = 0x400

        self.params.addChildren([
            {'name':'PLL Settings', 'key':'pll', 'type':'group', 'children':[
                {'name':'Enabled', 'key':'pllenabled', 'type':'bool', 'default':False, 'set':self.pll.pll_enable_set, 'get':self.pll.pll_enable_get, 'psync':False},
                {'name':'CLK-SMA (X6)', 'key':'pll0', 'type':'group', 'children':[
                    {'name':'CLK-SMA Enabled', 'key':'pll0enabled', 'type':'bool', 'default':False, 'set':partial(self.pll.pll_outenable_set, outnum=0), 'get':partial(self.pll.pll_outenable_get, outnum=0), 'psync':False},
                    {'name':'CLK-SMA Source', 'key':'pll0source', 'type':'list', 'values':['PLL0', 'PLL1', 'PLL2'], 'default':'PLL0', 'set':partial(self.pll.pll_outsource_set, outnum=0), 'get':partial(self.pll.pll_outsource_get, outnum=0), 'psync':False},
                    {'name':'CLK-SMA Slew Rate', 'key':'pll0slew', 'type':'list', 'values':['+3nS', '+2nS', '+1nS', '+0nS'], 'default':'+0nS', 'set':partial(self.pll.pll_outslew_set, outnum=0), 'get':partial(self.pll.pll_outslew_get, outnum=0), 'psync':False},
                    {'name':'PLL0 Frequency', 'key':'pll0freq', 'type':'float', 'limits':(0.625E6, 167E6), 'default':0, 'step':1E6,
                        'siPrefix':True, 'suffix':'Hz', 'set':partial(self.pll.pll_outfreq_set, outnum=0), 'get':partial(self.pll.pll_outfreq_get, outnum=0), 'psync':False},
                ]},
                {'name':'CLK-N13 (FGPA Pin N13)', 'key':'pll1', 'type':'group', 'children':[
                    {'name':'CLK-N13 Enabled', 'key':'pll1enabled', 'type':'bool', 'default':False, 'set':partial(self.pll.pll_outenable_set, outnum=1), 'get':partial(self.pll.pll_outenable_get, outnum=1), 'psync':False},
                    {'name':'CLK-N13 Source', 'key':'pll1source', 'type':'list', 'values':['PLL1'], 'value':'PLL1'},
                    {'name':'CLK-N13 Slew Rate', 'key':'pll1slew', 'type':'list', 'values':['+3nS', '+2nS', '+1nS', '+0nS'], 'default':'+0nS', 'set':partial(self.pll.pll_outslew_set, outnum=1), 'get':partial(self.pll.pll_outslew_get, outnum=1), 'psync':False},
                    {'name':'PLL1 Frequency', 'key':'pll1freq', 'type':'float', 'limits':(0.625E6, 167E6), 'default':0, 'step':1E6,
                        'siPrefix':True, 'suffix':'Hz', 'set':partial(self.pll.pll_outfreq_set, outnum=1), 'get':partial(self.pll.pll_outfreq_get, outnum=1), 'psync':False},
                ]},
                {'name':'CLK-E12 (FGPA Pin E12)', 'key':'pll2', 'type':'group', 'children':[
                    {'name':'CLK-E12 Enabled', 'key':'pll2enabled', 'type':'bool', 'default':False, 'set':partial(self.pll.pll_outenable_set, outnum=2), 'get':partial(self.pll.pll_outenable_get, outnum=2), 'psync':False},
                    {'name':'CLK-E12 Source', 'key':'pll2source', 'type':'list', 'values':['PLL2'], 'value':'PLL2'},
                    {'name':'CLK-E12 Slew Rate', 'key':'pll2slew', 'type':'list', 'values':['+0nS', '+1nS', '+2nS', '+3nS'], 'default':'+0nS', 'set':partial(self.pll.pll_outslew_set, outnum=2), 'get':partial(self.pll.pll_outslew_get, outnum=2), 'psync':False},
                    {'name':'PLL2 Frequency', 'key':'pll2freq', 'type':'float', 'limits':(0.625E6, 167E6), 'default':0, 'step':1E6,
                        'siPrefix':True, 'suffix':'Hz', 'set':partial(self.pll.pll_outfreq_set, outnum=2), 'get':partial(self.pll.pll_outfreq_get, outnum=2), 'psync':False},
                ]},
                {'name':'Save as Default (stored in EEPROM)', 'type':'action', 'action':lambda _ : self.pll.pll_writedefaults()},
            ]},
            {'name':'Disable CLKUSB For Capture', 'key':'clkusbautooff', 'type':'bool', 'value':True},
            {'name':'Time CLKUSB Disabled for', 'key':'clksleeptime', 'type':'int', 'range':(1, 50000), 'value':50, 'suffix':'mS'},
            {'name':'CLKUSB Manual Setting', 'key':'clkusboff', 'type':'bool', 'value':True, 'action':self.usb_clk_setenabled_action},
            {'name':'Send Trigger', 'type':'action', 'action':self.usb_trigger_toggle},
            {'name':'VCC-INT', 'key':'vccint', 'type':'float', 'default':1.00, 'range':(0.6, 1.10), 'suffix':' V', 'decimals':3, 'set':self.vccint_set, 'get':self.vccint_get},
            {'name':'FPGA Bitstream', 'type':'group', 'children':[
                    {'name':'Bitstream File', 'key':'fpgabsfile', 'type':'file', 'value':"", "filter":'*.bit'},
                    {'name':'Program FPGA', 'type':'action', 'action':self.gui_programfpga},
            ]},
        ])

    def fpga_write(self, addr, data):
        """ Write to specified address """

        if addr < self._woffset:
            raise IOError("Write to read-only location: 0x%04x"%addr)

        return self._naeusb.cmdWriteMem(addr, data)
        
    def fpga_read(self, addr, readlen):
        """ Read from address """

        if addr > self._woffset:
            print "NOTE: Read from write address, confirm this is not an error"

        data = self._naeusb.cmdReadMem(addr, readlen)
        return data

    def usb_clk_setenabled_action(self, p):
        self.usb_clk_setenabled(p.getValue())

    def usb_clk_setenabled(self, status):
        """ Turn on or off the Data Clock to the FPGA """
        if status:
            self._naeusb.sendCtrl(CW305_USB.REQ_SYSCFG, CW305_USB.SYSCFG_CLKON)
        else:
            self._naeusb.sendCtrl(CW305_USB.REQ_SYSCFG, CW305_USB.SYSCFG_CLKOFF)

    def usb_trigger_toggle(self, _=None):
        """ Toggle the trigger line high then low """
        self._naeusb.sendCtrl(CW305_USB.REQ_SYSCFG, CW305_USB.SYSCFG_TOGGLE)
        
    @setupSetParam("VCC-INT")
    def vccint_set(self, vccint=1.0):
        """ Set the VCC-INT for the FPGA """

        # print "vccint = " + str(vccint)

        if (vccint < 0.6) or (vccint > 1.15):
            raise ValueError("VCC-Int out of range 0.6V-1.1V")
        
        # Convert to mV
        vccint = int(vccint * 1000)
        vccsetting = [vccint & 0xff, (vccint >> 8) & 0xff, 0]

        # calculate checksum
        vccsetting[2] = vccsetting[0] ^ vccsetting[1] ^ CW305_USB.VCCINT_XORKEY

        self._naeusb.sendCtrl(CW305_USB.REQ_VCCINT, 0, vccsetting)

        resp = self._naeusb.readCtrl(CW305_USB.REQ_VCCINT, dlen=3)
        if resp[0] != 2:
            raise IOError("VCC-INT Write Error, response = %d" % resp[0])

    def vccint_get(self):
        """ Get the last set value for VCC-INT """

        resp = self._naeusb.readCtrl(CW305_USB.REQ_VCCINT, dlen=3)
        return float(resp[1] | (resp[2] << 8)) / 1000.0

    def gui_programfpga(self, _=None):
        bsfile = self.params.getChild(['FPGA Bitstream',"fpgabsfile"]).getValue()
        if not os.path.isfile(bsfile):
            raise Warning("FPGA Bitstream not configured or %s not a file." % str(bsfile))
        starttime = datetime.now()
        self.fpga.FPGAProgram(open(bsfile, "rb"))
        stoptime = datetime.now()
        print "FPGA Config time: %s" % str(stoptime - starttime)

    def con(self, scope = None, bsfile=None, force = False):
        """Connect to CW305 board, download bitstream"""

        self._naeusb.con(idProduct=0xC305)
        if self.fpga.isFPGAProgrammed() == False or force:
            bsfile = self.params.getChild(['FPGA Bitstream',"fpgabsfile"]).getValue()
            if not os.path.isfile(bsfile):
                print("FPGA Bitstream not configured or %s not a file." % str(bsfile))
            else:
                from datetime import datetime
                starttime = datetime.now()
                self.fpga.FPGAProgram(open(bsfile, "rb"))
                stoptime = datetime.now()
                print "FPGA Config time: %s" % str(stoptime - starttime)
        self.usb_clk_setenabled(True)
        self.fpga_write(0x100+self._woffset, [0])
        self.params.refreshAllParameters()
        self.pll.cdce906init()
        self.connectStatus.setValue(True)

    def checkEncryptionKey(self, key):
        """Validate encryption key"""
        return key 

    def loadEncryptionKey(self, key):
        """Write encryption key to FPGA"""
        self.key = key
        key = key[::-1]
        self.fpga_write(0x100+self._woffset, key)

    def loadInput(self, inputtext):
        """Write input to FPGA"""
        self.input = inputtext
        text = inputtext[::-1]
        self.fpga_write(0x200+self._woffset, text)

    def isDone(self):
        """Check if FPGA is done"""
        result = self.fpga_read(0x50, 1)[0]

        if result == 0x00:
            return False
        else:
            # Clear trigger
            self.fpga_write(0x40+self._woffset, [0])
            # LED Off
            self.fpga_write(0x10+self._woffset, [0])
            return True
        
    def readOutput(self):
        """"Read output from FPGA"""
        data = self.fpga_read(0x200, 16)
        data = data[::-1]
        return data

    def go(self):
        """Disable USB clock (if requested), perform encryption, re-enable clock"""
        if self.findParam('clkusbautooff').getValue():
            self.usb_clk_setenabled(False)
            
        #LED On
        self.fpga_write(0x10+self._woffset, [0x01])
            

        time.sleep(0.01)
        self.usb_trigger_toggle()
        # self.FPGAWrite(0x100, [1])
        # self.FPGAWrite(0x100, [0])

        if self.findParam('clkusbautooff').getValue():
            time.sleep(self.findParam('clksleeptime').getValue() / 1000.0)
            self.usb_clk_setenabled(True)
Ejemplo n.º 24
0
class CW310(CW305):
    def __init__(self, *args, **kwargs):
        # maybe later can hijack cw305 stuff, but for now don't
        pass
        import chipwhisperer as cw
        self._naeusb = NAEUSB()
        self.pll = PLLCDCE906(self._naeusb, ref_freq=12.0E6)
        self.fpga = FPGA(self._naeusb)

        self.hw = None
        self.oa = None

        self._woffset_sam3U = 0x000
        self.default_verilog_defines = 'cw305_defines.v'
        self.default_verilog_defines_full_path = os.path.dirname(
            cw.__file__
        ) + '/../../hardware/victims/cw305_artixtarget/fpga/common/' + self.default_verilog_defines
        self.registers = 12  # number of registers we expect to find
        self.bytecount_size = 7  # pBYTECNT_SIZE in Verilog

        self._clksleeptime = 1
        self._clkusbautooff = True
        self.last_key = bytearray([0] * 16)
        self.target_name = 'AES'

    def _con(self,
             scope=None,
             bsfile=None,
             force=False,
             fpga_id=None,
             defines_files=None,
             slurp=True):
        # add more stuff later
        self._naeusb.con(idProduct=[0xC310])
        # self.pll.cdce906init()

        if defines_files is None:
            if fpga_id is None:
                verilog_defines = [self.default_verilog_defines_full_path]
            else:
                from chipwhisperer.hardware.firmware.cw305 import getsome
                verilog_defines = [getsome(self.default_verilog_defines)]
        else:
            verilog_defines = defines_files
        if slurp:
            self.slurp_defines(verilog_defines)

        if bsfile:
            status = self.fpga.FPGAProgram(open(bsfile, "rb"))

    def usb_set_voltage(self, pdo_num, voltage):
        if pdo_num not in [2, 3]:
            raise ValueError("pdo_num must be 2 or 3, {}".format(pdo_num))
        if (voltage > 20 or voltage < 5):
            raise ValueError(
                "Voltage must be between 5 and 20, {}".format(voltage))
        self._naeusb.sendCtrl(0x40, 0, [0x28, 0x89 + (pdo_num - 2) * (0x04)])
        snk_pdo = self._naeusb.readCtrl(0x41, 0, 4)
        voltage *= 20
        voltage = int(voltage)

        snk_pdo[1] &= ~0xFC
        snk_pdo[2] &= ~0x0F
        print(snk_pdo)
        snk_pdo[1] |= ((voltage << 2) & 0xFC)
        snk_pdo[2] |= ((voltage >> 6) & 0x0F)
        print(voltage)
        print(snk_pdo)
        self._naeusb.sendCtrl(0x41, 0, snk_pdo)

    def usb_set_current(self, pdo_num, current):
        if pdo_num not in [2, 3]:
            raise ValueError("pdo_num must be 2 or 3, {}".format(pdo_num))
        if (current > 5 or current < 0.5):
            raise ValueError(
                "Voltage must be between 0.5 and 20, {}".format(voltage))
        snk_pdo = self._naeusb.readCtrl(0x41, 0, 4)
        current *= 100
        current = int(current)

        snk_pdo[0] &= ~0xFF
        snk_pdo[1] &= ~0x03
        print(snk_pdo)
        snk_pdo[0] |= (current & 0xFF)
        snk_pdo[1] |= ((current >> 8) & 0x03)
        print(current)
        print(snk_pdo)
        self._naeusb.sendCtrl(0x41, 0, snk_pdo)

    def usb_negotiate_pdo(self):
        #soft reset
        self._naeusb.sendCtrl(0x40, 0, [0x28, 0x51])
        self._naeusb.sendCtrl(0x41, 0, [0x0D])

        #send reset on pdo bus
        self._naeusb.sendCtrl(0x40, 0, [0x28, 0x1A])
        self._naeusb.sendCtrl(0x41, 0, [0x26])

    def _dis(self):
        if self._naeusb:
            self._naeusb.close()
Ejemplo n.º 25
0
class CW305(TargetTemplate):
    _name = "ChipWhisperer CW305 (Artix-7)"

    def __init__(self):
        TargetTemplate.__init__(self)
        self._naeusb = NAEUSB()
        self.pll = PLLCDCE906(self._naeusb, ref_freq=12.0E6, parent=self)
        self.fpga = FPGA(self._naeusb)

        self.hw = None
        # self._fpgabs = QSettings().value("cw305-bitstream", '')
        self.oa = None

        self._woffset = 0x400

        self.params.addChildren([
            {
                'name':
                'PLL Settings',
                'key':
                'pll',
                'type':
                'group',
                'children': [
                    {
                        'name': 'Enabled',
                        'key': 'pllenabled',
                        'type': 'bool',
                        'default': False,
                        'set': self.pll.pll_enable_set,
                        'get': self.pll.pll_enable_get,
                        'psync': False
                    },
                    {
                        'name':
                        'CLK-SMA (X6)',
                        'key':
                        'pll0',
                        'type':
                        'group',
                        'children': [
                            {
                                'name':
                                'CLK-SMA Enabled',
                                'key':
                                'pll0enabled',
                                'type':
                                'bool',
                                'default':
                                False,
                                'set':
                                partial(self.pll.pll_outenable_set, outnum=0),
                                'get':
                                partial(self.pll.pll_outenable_get, outnum=0),
                                'psync':
                                False
                            },
                            {
                                'name':
                                'CLK-SMA Source',
                                'key':
                                'pll0source',
                                'type':
                                'list',
                                'values': ['PLL0', 'PLL1', 'PLL2'],
                                'default':
                                'PLL0',
                                'set':
                                partial(self.pll.pll_outsource_set, outnum=0),
                                'get':
                                partial(self.pll.pll_outsource_get, outnum=0),
                                'psync':
                                False
                            },
                            {
                                'name': 'CLK-SMA Slew Rate',
                                'key': 'pll0slew',
                                'type': 'list',
                                'values': ['+3nS', '+2nS', '+1nS', '+0nS'],
                                'default': '+0nS',
                                'set': partial(self.pll.pll_outslew_set,
                                               outnum=0),
                                'get': partial(self.pll.pll_outslew_get,
                                               outnum=0),
                                'psync': False
                            },
                            {
                                'name': 'PLL0 Frequency',
                                'key': 'pll0freq',
                                'type': 'float',
                                'limits': (0.625E6, 167E6),
                                'default': 0,
                                'step': 1E6,
                                'siPrefix': True,
                                'suffix': 'Hz',
                                'set': partial(self.pll.pll_outfreq_set,
                                               outnum=0),
                                'get': partial(self.pll.pll_outfreq_get,
                                               outnum=0),
                                'psync': False
                            },
                        ]
                    },
                    {
                        'name':
                        'CLK-N13 (FGPA Pin N13)',
                        'key':
                        'pll1',
                        'type':
                        'group',
                        'children': [
                            {
                                'name':
                                'CLK-N13 Enabled',
                                'key':
                                'pll1enabled',
                                'type':
                                'bool',
                                'default':
                                False,
                                'set':
                                partial(self.pll.pll_outenable_set, outnum=1),
                                'get':
                                partial(self.pll.pll_outenable_get, outnum=1),
                                'psync':
                                False
                            },
                            {
                                'name': 'CLK-N13 Source',
                                'key': 'pll1source',
                                'type': 'list',
                                'values': ['PLL1'],
                                'value': 'PLL1'
                            },
                            {
                                'name': 'CLK-N13 Slew Rate',
                                'key': 'pll1slew',
                                'type': 'list',
                                'values': ['+3nS', '+2nS', '+1nS', '+0nS'],
                                'default': '+0nS',
                                'set': partial(self.pll.pll_outslew_set,
                                               outnum=1),
                                'get': partial(self.pll.pll_outslew_get,
                                               outnum=1),
                                'psync': False
                            },
                            {
                                'name': 'PLL1 Frequency',
                                'key': 'pll1freq',
                                'type': 'float',
                                'limits': (0.625E6, 167E6),
                                'default': 0,
                                'step': 1E6,
                                'siPrefix': True,
                                'suffix': 'Hz',
                                'set': partial(self.pll.pll_outfreq_set,
                                               outnum=1),
                                'get': partial(self.pll.pll_outfreq_get,
                                               outnum=1),
                                'psync': False
                            },
                        ]
                    },
                    {
                        'name':
                        'CLK-E12 (FGPA Pin E12)',
                        'key':
                        'pll2',
                        'type':
                        'group',
                        'children': [
                            {
                                'name':
                                'CLK-E12 Enabled',
                                'key':
                                'pll2enabled',
                                'type':
                                'bool',
                                'default':
                                False,
                                'set':
                                partial(self.pll.pll_outenable_set, outnum=2),
                                'get':
                                partial(self.pll.pll_outenable_get, outnum=2),
                                'psync':
                                False
                            },
                            {
                                'name': 'CLK-E12 Source',
                                'key': 'pll2source',
                                'type': 'list',
                                'values': ['PLL2'],
                                'value': 'PLL2'
                            },
                            {
                                'name': 'CLK-E12 Slew Rate',
                                'key': 'pll2slew',
                                'type': 'list',
                                'values': ['+0nS', '+1nS', '+2nS', '+3nS'],
                                'default': '+0nS',
                                'set': partial(self.pll.pll_outslew_set,
                                               outnum=2),
                                'get': partial(self.pll.pll_outslew_get,
                                               outnum=2),
                                'psync': False
                            },
                            {
                                'name': 'PLL2 Frequency',
                                'key': 'pll2freq',
                                'type': 'float',
                                'limits': (0.625E6, 167E6),
                                'default': 0,
                                'step': 1E6,
                                'siPrefix': True,
                                'suffix': 'Hz',
                                'set': partial(self.pll.pll_outfreq_set,
                                               outnum=2),
                                'get': partial(self.pll.pll_outfreq_get,
                                               outnum=2),
                                'psync': False
                            },
                        ]
                    },
                    {
                        'name': 'Save as Default (stored in EEPROM)',
                        'type': 'action',
                        'action': lambda _: self.pll.pll_writedefaults()
                    },
                ]
            },
            {
                'name': 'Disable CLKUSB For Capture',
                'key': 'clkusbautooff',
                'type': 'bool',
                'value': True
            },
            {
                'name': 'Time CLKUSB Disabled for',
                'key': 'clksleeptime',
                'type': 'int',
                'range': (1, 50000),
                'value': 50,
                'suffix': 'mS'
            },
            {
                'name': 'CLKUSB Manual Setting',
                'key': 'clkusboff',
                'type': 'bool',
                'value': True,
                'action': self.usb_clk_setenabled_action
            },
            {
                'name': 'Send Trigger',
                'type': 'action',
                'action': self.usb_trigger_toggle
            },
            {
                'name': 'VCC-INT',
                'key': 'vccint',
                'type': 'float',
                'default': 1.00,
                'range': (0.6, 1.10),
                'suffix': ' V',
                'decimals': 3,
                'set': self.vccint_set,
                'get': self.vccint_get
            },
            {
                'name':
                'FPGA Bitstream',
                'type':
                'group',
                'children': [
                    {
                        'name': 'Bitstream File',
                        'key': 'fpgabsfile',
                        'type': 'file',
                        'value': "",
                        "filter": '*.bit'
                    },
                    {
                        'name': 'Program FPGA',
                        'type': 'action',
                        'action': self.gui_programfpga
                    },
                ]
            },
        ])

    def fpga_write(self, addr, data):
        """ Write to specified address """

        if addr < self._woffset:
            raise IOError("Write to read-only location: 0x%04x" % addr)

        return self._naeusb.cmdWriteMem(addr, data)

    def fpga_read(self, addr, readlen):
        """ Read from address """

        if addr > self._woffset:
            logging.info(
                'Read from write address, confirm this is not an error')

        data = self._naeusb.cmdReadMem(addr, readlen)
        return data

    def usb_clk_setenabled_action(self, p):
        self.usb_clk_setenabled(p.getValue())

    def usb_clk_setenabled(self, status):
        """ Turn on or off the Data Clock to the FPGA """
        if status:
            self._naeusb.sendCtrl(CW305_USB.REQ_SYSCFG, CW305_USB.SYSCFG_CLKON)
        else:
            self._naeusb.sendCtrl(CW305_USB.REQ_SYSCFG,
                                  CW305_USB.SYSCFG_CLKOFF)

    def usb_trigger_toggle(self, _=None):
        """ Toggle the trigger line high then low """
        self._naeusb.sendCtrl(CW305_USB.REQ_SYSCFG, CW305_USB.SYSCFG_TOGGLE)

    @setupSetParam("VCC-INT")
    def vccint_set(self, vccint=1.0):
        """ Set the VCC-INT for the FPGA """

        # print "vccint = " + str(vccint)

        if (vccint < 0.6) or (vccint > 1.15):
            raise ValueError("VCC-Int out of range 0.6V-1.1V")

        # Convert to mV
        vccint = int(vccint * 1000)
        vccsetting = [vccint & 0xff, (vccint >> 8) & 0xff, 0]

        # calculate checksum
        vccsetting[2] = vccsetting[0] ^ vccsetting[1] ^ CW305_USB.VCCINT_XORKEY

        self._naeusb.sendCtrl(CW305_USB.REQ_VCCINT, 0, vccsetting)

        resp = self._naeusb.readCtrl(CW305_USB.REQ_VCCINT, dlen=3)
        if resp[0] != 2:
            raise IOError("VCC-INT Write Error, response = %d" % resp[0])

    def vccint_get(self):
        """ Get the last set value for VCC-INT """

        resp = self._naeusb.readCtrl(CW305_USB.REQ_VCCINT, dlen=3)
        return float(resp[1] | (resp[2] << 8)) / 1000.0

    def gui_programfpga(self, _=None):
        bsfile = self.params.getChild(['FPGA Bitstream',
                                       "fpgabsfile"]).getValue()
        if not os.path.isfile(bsfile):
            raise Warning("FPGA Bitstream not configured or %s not a file." %
                          str(bsfile))
        starttime = datetime.now()
        result = self.fpga.FPGAProgram(open(bsfile, "rb"),
                                       exceptOnDoneFailure=False)
        stoptime = datetime.now()

        if result:
            logging.info('FPGA Config OK, time: %s' %
                         str(stoptime - starttime))
        else:
            logging.warning(
                'FPGA Config failed: DONE pin did not go high. Check bitstream is for target device.'
            )

    def _con(self, scope=None, bsfile=None, force=False):
        """Connect to CW305 board, download bitstream"""

        self._naeusb.con(idProduct=[0xC305])
        if self.fpga.isFPGAProgrammed() == False or force:
            if bsfile is None:
                bsfile = self.params.getChild(['FPGA Bitstream',
                                               "fpgabsfile"]).getValue()
            if not os.path.isfile(bsfile):
                print("FPGA Bitstream not configured or '%s' not a file." %
                      str(bsfile))
            else:
                from datetime import datetime
                starttime = datetime.now()
                status = self.fpga.FPGAProgram(open(bsfile, "rb"),
                                               exceptOnDoneFailure=False)
                stoptime = datetime.now()
                if status:
                    logging.info('FPGA Config OK, time: %s' %
                                 str(stoptime - starttime))
                else:
                    logging.warning(
                        'FPGA Done pin failed to go high, check bitstream is for target device.'
                    )
        self.usb_clk_setenabled(True)
        self.fpga_write(0x100 + self._woffset, [0])
        self.params.refreshAllParameters()
        self.pll.cdce906init()

    def _dis(self):
        if self._naeusb:
            self._naeusb.close()

    def checkEncryptionKey(self, key):
        """Validate encryption key"""
        return key

    def loadEncryptionKey(self, key):
        """Write encryption key to FPGA"""
        self.key = key
        key = key[::-1]
        self.fpga_write(0x100 + self._woffset, key)

    def loadInput(self, inputtext):
        """Write input to FPGA"""
        self.input = inputtext
        text = inputtext[::-1]
        self.fpga_write(0x200 + self._woffset, text)

    def isDone(self):
        """Check if FPGA is done"""
        result = self.fpga_read(0x50, 1)[0]

        if result == 0x00:
            return False
        else:
            # Clear trigger
            self.fpga_write(0x40 + self._woffset, [0])
            # LED Off
            self.fpga_write(0x10 + self._woffset, [0])
            return True

    def readOutput(self):
        """"Read output from FPGA"""
        data = self.fpga_read(0x200, 16)
        data = data[::-1]
        self.newInputData.emit(util.list2hexstr(data))
        return data

    def go(self):
        """Disable USB clock (if requested), perform encryption, re-enable clock"""
        if self.findParam('clkusbautooff').getValue():
            self.usb_clk_setenabled(False)

        #LED On
        self.fpga_write(0x10 + self._woffset, [0x01])

        time.sleep(0.01)
        self.usb_trigger_toggle()
        # self.FPGAWrite(0x100, [1])
        # self.FPGAWrite(0x100, [0])

        if self.findParam('clkusbautooff').getValue():
            time.sleep(self.findParam('clksleeptime').getValue() / 1000.0)
            self.usb_clk_setenabled(True)