Here’s my code below. It is slightly modified from the original in the repository I had linked to.
import time
import struct
import chipwhisperer as cw
def as_hex(s):
return "".join([f"\\x{ord(c):02x}" for c in s])
def make_pkt(data):
pkt = b"\x01"
pkt += struct.pack('!H', len(data))
pkt += data
# Checksum
chk = (256 - sum(pkt[1:])) & 0xff
pkt += bytes([chk, 0x03])
return pkt
scope = cw.scope()
scope.default_setup()
scope.io.tio1 = 'serial_tx'
scope.io.tio2 = 'serial_rx'
scope.io.tio3 = 'gpio_low'
scope.io.glitch_trig_mcx = 'glitch'
scope.clock.clkgen_src = 'system'
scope.clock.clkgen_freq = 100e6
scope.clock.adc_mul = 0
target = cw.target(scope)
target.baud = 9600
target.flush()
scope.trigger.triggers = 'tio1'
scope.trigger.module = 'UART'
scope.gain.db = 12
scope.UARTTrigger.enabled = True
scope.UARTTrigger.baud = 9600
scope.UARTTrigger.set_pattern_match(0, '\x00\x00\x00\x1f\xff\xff\xc5\x03')
scope.UARTTrigger.trigger_source = 0
scope.glitch.enabled = True
scope.glitch.clk_src = "pll"
scope.io.glitch_hp = False
scope.io.glitch_lp = True
scope.io.glitch_trig_mcx = 'glitch'
scope.glitch.output = "enable_only"
scope.glitch.trigger_src = "ext_single"
gc = cw.GlitchController(groups=["success", "reset", "normal"], parameters=["ext_offset", "repeat"])
min_delay = int(100.5e-6 * scope.clock.clkgen_freq)
max_delay = int(101.5e-6 * scope.clock.clkgen_freq)
print(min_delay, max_delay)
gc.set_range("ext_offset", min_delay, max_delay)
gc.set_range("repeat", 5, 50)
gc.set_global_step(1)
gc.display_stats()
gc.glitch_plot(plotdots={"success":"+r", "reset":"xb", "normal":'xg'})
blocks = [(0x0, 0x1fff)]
while True:
for delay, width in gc.glitch_values(clear=False):
scope.glitch.ext_offset = delay
scope.glitch.repeat = width
#Width and offset are not in use on Enable_Only Glitch types
scope.glitch.width = 0
scope.glitch.offset = 0
time.sleep(.1)
scope.arm();
time.sleep(.1)
scope.io.tio3 = 'gpio_high' # Release Reset
time.sleep(.2)
target.read(target.in_waiting()) # Clean all bytes in serial input buffer
try:
target.write(b'\x00' * 10)
assert target.read(1) == '\x00'
target.write(b'\x55')
assert target.read(1) == '\xc1'
target.write(b'\x01\x00\x01\x38\xc7\x03')
assert target.read(6) == '\x81\x00\x01\x38\xc7\x03', "Wrong Resp Device Type 1"
target.write(b'\x81\x00\x01\x38\xc7\x03')
resp = target.read(30)
target.write(b'\x01\x00\x09\x32\x00\x7a\x12\x00\x07\x27\x0e\x00\xfd\x03')
assert target.read(6) == '\x81\x00\x01\x32\xcd\x03', "Wrong Resp Frequency 1"
target.write(b'\x81\x00\x01\x32\xcd\x03')
assert target.read(14) == '\x81\x00\x09\x32\x07\x27\x0e\x00\x03\x93\x87\x00\x6c\x03', "Wrong Resp Frequency 2"
target.write(b'\x01\x00\x05\x34\x00\x00\x25\x8f\x13\x03')
assert target.read(6) == '\x81\x00\x01\x34\xcb\x03', "Wrong Resp Bitrate 1"
# Synchronize!
# print("Synchro 2!")
target.write(b'\x01\x00\x01\x00\xff\x03')
resp = target.read(6)
#print("Synchro 2 response: ", end="")
#print(as_hex(resp))
assert resp == '\x81\x00\x01\x00\xff\x03', "Wrong Resp Synchro"
print("Response From this attempt: ", end="")
target.write(b'\x01\x00\x09\x15\x00\x00\x00\x00\x00\x1f\xff\xff\xc5\x03')
resp = target.read(6)
#trace = cw.capture_trace(scope, target, None)
#Uncommenting the Above line will illuminate Armed light and make Glitch light illuminate on triggers.
if resp == '\x81\x00\x01\x15\xea\x03':
gc.add("success")
print("Success: ", end = "");
print(as_hex(resp))
print("Delay: ", end ="");
print(delay)
print("Width: ", end ="");
print(width)
elif resp == '':
print("Anomaly: ", end="")
print("Delay: ", end ="")
print(delay, end ="")
print(" Width: ", end ="")
print(width)
gc.add("normal")
else:
target.read(1); #Clear buffer of remaining byte
print(as_hex(resp))
gc.add("reset")
continue
except AssertionError as e:
print(delay, width, e)
gc.add("reset")
finally:
#scope.capture();#Currently results in a No Trigger Seen! Error
scope.io.tio3 = 'gpio_low' # Assert reset
time.sleep(.1)
Hopefully the above code comes through in a readable format. If I uncomment the line containing the call to cw.capture_trace() then the Armed light comes on until the Glitch light illuminates, but I don’t believe it’s actually occuring with my UART trigger. For that I also have to set adc_mul to 1.
I do get this error it seems no matter what value I set my clock and adc_mul to(with different values for what the ADC mul gets adjusted to) however I am not sure that it is relevant.:
(ChipWhisperer Scope WARNING|File ChipWhispererHuskyClock.py:364) ADC frequency must be between 1MHz and 300000000.0MHz - ADC mul has been adjusted to 3
(ChipWhisperer Scope WARNING|File ChipWhispererHuskyClock.py:367)
ADC frequency exceeds specification (200 MHz).
This may or may not work, depending on temperature, voltage, and luck.
It may not work reliably.
You can run scope.adc_test() to check whether ADC data is sampled properly by the FPGA,
but this doesn't fully verify that the ADC is working properly.
You can adjust scope.clock.pll._warning_freq if you don't want
to see this message anymore.
I can also confirm that the ADC LED does not illuminate at all during this procedure.