Capturing traces from STM32F415RGT6

I noticed weird behavior on running the application on STM32F415RGT6 to capture the power traces from it.
The script being used for that

import chipwhisperer as cw
import time
from tqdm import tqdm

scope = cw.scope()
target = cw.target(scope, cw.targets.SimpleSerial2)

time.sleep(0.05)
scope.default_setup()

scope.gain.db = 38

scope.adc.samples = 2000
scope.adc.offset = 0
scope.adc.basic_mode = "rising_edge"

scope.clock.reset_adc()
assert (scope.clock.adc_locked), "ADC failed to lock"

#PLATFORM = 'CW308_STM32F4'
#prog = cw.programmers.STM32FProgrammer
#fw_path = 'simpleserial-aes-{}.hex'.format(PLATFORM)
#cw.program_target(scope, prog, fw_path)

project = cw.create_project("traces/STM32F4_HW_AES.cwp", overwrite=True)

ktp = cw.ktp.Basic()
N = 1000

for i in tqdm(range(N)):
    key, text = ktp.next()
    trace = cw.capture_trace(scope, target, text, key)
    if trace is None:
        continue
    project.traces.append(trace)

print(scope.adc.trig_count)
project.save()

scope.dis()
target.dis()

if this part of the script is not commented, it works fine each time I run the script.

#PLATFORM = 'CW308_STM32F4'
#prog = cw.programmers.STM32FProgrammer
#fw_path = 'simpleserial-aes-{}.hex'.format(PLATFORM)
#cw.program_target(scope, prog, fw_path)

with getting the following log

Detected known STMF32: STM32F40xxx/41xxx
Extended erase (0x44), this can take ten seconds or more
Attempting to program 5283 bytes at 0x8000000
STM32F Programming flash...
STM32F Reading flash...
Verified flash OK, 5283 bytes
100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 1000/1000 [00:10<00:00, 96.94it/s]

1148

In the case, if flashing is commented, I get following log

...
(ChipWhisperer Target WARNING|File SimpleSerial2.py:502) Read timed out:
(ChipWhisperer Target ERROR|File SimpleSerial2.py:285) Device did not ack
(ChipWhisperer Scope WARNING|File _OpenADCInterface.py:730) Timeout in OpenADC capture(), no trigger seen! Trigger forced, data is invalid. Status: 0b
(ChipWhisperer Scope WARNING|File _OpenADCInterface.py:730) Timeout in OpenADC capture(), no trigger seen! Trigger forced, data is invalid. Status: 0a
(ChipWhisperer Scope WARNING|File __init__.py:511) Timeout happened during capture
...

Looks like the bootloader doesn’t load the application from the flash.
I checked the BOOT0 and BOOT1 pins. They are in the state which should run the user application.

Hi,

What voltage are you supplying on the FILTHP/LP pins?

FILTHP/LP pins have 1.37V
SJ2 point at the victim board has 1.33V

The jumper is set (on J14) to power from the VADJ.

You may want to try printing something upon boot, such as the "hello" normally commented out to verify that serial is working.

The steps I did:

  1. Uncommented the code lines to print the β€œhello” message to UART.
  2. Flashed updated application.
  3. Measured TX line by the oscilloscope.

The results:

  1. On flashing (at very beginning), I noticed the short message on the TX line.
  2. The microcontroller sends the encrypted messages via TX line just after flashing.
  3. After power cycle (CW was disabled and then enabled), the TX line as well as RX line were at the low (0) level. There was no the β€˜hello’ message on the oscilloscope.

The thing I noticed is the TX line stays on the high (1) level just after flashing.
Maybe the UART initialization of STM32F415RGT6 misses something, say setting the RX/TX lines at the high level?

I have found the problem. It turns out, clock is passed to the target only after scope.default_setup()
To launch the target, we need to pull down the nRST and then release it.
So, I added lines to reset target

scope.io.nrst = 'low'
time.sleep(0.05)
scope.io.nrst = 'high_z'

with these strings everything works fine.
Thanks for your assistance!

Glad to hear you got it working

1 Like