Hello.
I’m trying to collect waveforms using a chipwhisperer Husky and a chipshiserer cw308 UFO board(STM32F303)
, but I’m getting the ‘FiFO is empty’ issue.
I referred to GitHub - newaetech/tracewhisperer and,
If using SWO, three pins must be connected:
- SWDIO/TMS to D0 pin
- SWCLK/TCLK to D1 pin
- SWO/TDO to D2 pin
and uploaded the HEX file targeting AES, and executed the code below.
When sending 16byte plain text to target.simpleserial_write(‘p’, text) and getting the value with r = target.simpleserial_read(‘r’, 16),
we see that it outputs the value without any problem, but when we use
raw = scope.trace.read_capture_data()
we see that
assert self.fifo_empty() == False, ‘FIFO is empty’
AssertionError: FIFO is empty
occurs.
I wonder if there is a problem with the pin connections and how to fix it.
Which notebook are you running? Are there any errors or warnings prior to this one? More context is needed to diagnose the problem.
The SWO ↔ Dx jumpers are only needed if using TraceWhisperer.
Thank you for your response.
I am getting “AssertionError: FIFO is empty” in the code below in
raw = scope.trace.read_capture_data().
I’m not getting any errors elsewhere, let me know if you need any more information.
import chipwhisperer as cw
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
matplotlib.use("qt5agg")
import time
def enable_trace(_scope, _trace, _target):
_trace.target = _target
_trace.enabled = True
_trace.clock.fe_clock_src = 'target_clock'
assert _trace.clock.fe_clock_alive, "Hmm, the clock you chose doesn't seem to be active."
_trace.trace_mode = 'SWO'
_trace.jtag_to_swd() # switch target into SWO mode
acpr = 0
trigger_freq_mul = 8
_trace.clock.swo_clock_freq = _scope.clock.clkgen_freq * trigger_freq_mul
_trace.target_registers.TPI_ACPR = acpr
_trace.swo_div = trigger_freq_mul * (acpr + 1)
assert _trace.clock.swo_clock_locked, "Trigger/UART clock not locked"
assert _scope.userio.status & 0x4, "SWO line not high"
# Disable sync frames for SWO
_trace.target_registers.DWT_CTRL = 0x40000021
# Trigger _trace capture from target FW
_trace.capture.trigger_source = 'firmware trigger'
_trace.capture.raw = False
# match on any PC match (isync) _trace packet:
_trace.set_pattern_match(0, [3, 8, 32])
# enable matching rule:
_trace.capture.rules_enabled = [0]
_trace.capture.trigger_source = 'firmware trigger'
_trace.capture.mode = 'while_trig'
# Enable or disable periodic PC sampling:
_trace.set_periodic_pc_sampling(enable=0)
pass
def set_target_pc(addr0: int, addr1: int, match):
assert match in [0, 1, None, 'both']
assert addr0 >= 0 and addr1 >= 0
scope.trace.set_isync_matches(addr0=addr0, addr1=addr1, match=None)
pass
scope = cw.scope()
scope.default_setup()
target = cw.target(scope)
# scope.adc.stream_mode = False
scope.clock.adc_mul = 1
scope.gain.db = 20
scope.adc.samples = 30000
#%%
firmware_path =r"C:\Users\lemon\Desktop\psj-cw\demo-trace-aes\DEMO-ARM-Trace-AES-CW308_STM32F3.hex"
cw.program_target(scope, cw.programmers.STM32FProgrammer, firmware_path)
#%%
target.flush()
target.read(100)
target.get_simpleserial_commands()
target.write("k00112233445566778899AABBCCDDEEFF\n")
print(target.read(100))
target.write("K\n")
print(target.read(100))
#%%
# Single
scope.arm()
target.write("p00112233445566778899AABBCCDDEEFF\n")
resp = target.read(100)
print(resp)
scope.capture(poll_done=True)
trace = scope.get_last_trace(as_int=True)
print(f"Samples: {scope.adc.trig_count}")
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(trace, linewidth=0.5)
fig.tight_layout()
fig.show()
#%%
enable_trace(scope, scope.trace, target)
#%%
set_target_pc(addr0=0x8000bd8, addr1=0x8000cf4, match=1)
scope.gain.db = 15
#%%
# Single measurement
text = bytearray.fromhex("00112233445566778899AABBCCDDEEFF")
scope.trace.arm_trace()
scope.arm()
target.simpleserial_write("p", text)
scope.capture(poll_done=True)
time.sleep(0.1)
t = scope.get_last_trace(as_int=True)
r = target.simpleserial_read("r", 16)
raw = scope.trace.read_capture_data()
times = scope.trace.get_rule_match_times(raw, rawtimes=False, verbose=True)
print(scope.trace.capture.matched_pattern_data)
print(scope.trace.capture.matched_pattern_counts)
print(scope.trace.capture)
ttt = [i[0] * scope.clock.adc_mul for i in times]
fig = plt.figure()
ax: plt.Axes = fig.add_subplot(111)
ax.plot(t, linewidth=0.5)
ax.vlines(ttt, ymin=-0, ymax=4000, color='red')
fig.tight_layout()
fig.show()
print(scope.adc.trig_count)
The error means that no trace data was collected. Unfortunately there is a long list of possible reasons for this. The first thing I would check is whether there is any activity at all on your target’s SWO line (with a scope or logic analyzer).
Have you run our example notebook successfully?
The other thing that pops to mind is that if you’re using your own firmware on the target (not the firmware we use in our example), this paragraph from the notebook could be your issue:
"Arm processors which support JTAG and SWD come out of reset in JTAG mode. In order to get trace data out of the SWO pin, we need to switch it over to SWD mode.
The jtag_to_swd()
call below runs a special sequence on the TMS and TCK pins to do this switchover. However, different processors (such as the STM32) may have additional requirements to enable the SWO pin. The simpleserial-trace
firmware handles this for the STM32. Other targets may have their own requirements."