ChipWhisperer Husky - Armed Light and Glitch Light Not Illuminating

Hey all. I’m pretty new to this so forgive me for asking some pretty amateurish questions.

I’m currently working on a Renesas RH850 and attempting to replicate some of the work done by Willem Melching here: https://twitter.com/PD0WM/status/1653023711224647682

I’ve adapted his code for my target as I have a slightly different RH850 family member. However I’ve noticed that despite calling scope.arm() my Husky does not illuminate the “Armed” light. And I can see from printing scope that I am generating triggers on my given UART message, however my “Glitch” light does not illuminate.

When I add a statement such as:

trace = cw.capture_trace(scope, target, None)

to my code, both the “Armed” light will illuminate until the “Glitch” light briefly illuminates and then both lights will go out until the next call to scope.arm().

Based on this information is it safe to say that while my scope is triggering my Glitch is not actually being executed?

Correct. It’s hard to determine the issue without knowing more about your code and setup.

The only way I can think of that scope.arm() would fail to arm the scope and turn on the Armed LED is if you don’t have an ADC clock - this is easy to determine as the red ADC LED would be solid on. You can also query scope.clock.adc_locked.

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.

As a general update to this, I’ve also found that by setting the following I can have the Scope Arm, but it does not appear to trigger now as I can see from print(scope). Here were the changes:

scope.gain.db = 40
scope.clock.adc_mul = 1

If you run the while True: loop just once, then does the scope arm and trigger as expected?

If so, all you are missing is manually disarming the scope prior to re-arming it.

If you use cw.capture_trace() or scope.capture(), then this is done for you

Just add scope.sc.arm(False) prior to your scope.arm() call.

Thank you, I actually can’t believe I missed this. I was too busy looking at other aspects to miss that I had actually even commented out a scope.capture() which earlier I was having issues with. Thank you again for the help!

1 Like