Power Trace capture using Husky for a STM32F3 on a CW308 UFO

Hi,
I’ve been trying to use the BEEBS benchmarking programs to run on a CW308 with a STM32F3 target board mounted on it, and capture the power trace using a CW Husky. I’ve modified the programs CW, and was able to load the firmware, but I’m unable to capture the power using the capture script. I’m including the files I’ve used for reference. Any help, suggestion, advice would be greatly appreciated.

#Power Capture
#!/usr/bin/env python3

Script to load firmware, run benchmark, and capture traces

import chipwhisperer as cw
import time
import numpy as np
import matplotlib.pyplot as plt

def main():
try:
# Step 1: Connect to the ChipWhisperer Husky
scope = cw.scope()

    print("Connected to ChipWhisperer Husky")
    
    # Step 2: Setup scope parameters for capturing power traces
    scope.gain.gain = 45  
    scope.adc.samples = 5000 
    scope.adc.offset = 0
    scope.adc.basic_mode = "rising_edge"
    scope.clock.clkgen_freq = 7370000  # 7.37 MHz
    scope.clock.adc_src = "clkgen_x1"
    scope.trigger.triggers = "tio4"
    scope.io.tio1 = "serial_rx"
    scope.io.tio2 = "serial_tx"
    scope.io.tio4 = "gpio_high"
    scope.io.hs2 = "clkgen"

    
    
    # # Reset the target
    # scope.io.nrst = 0
    # time.sleep(0.1)
    # scope.io.nrst = 1
    # time.sleep(0.1)

    # Arm the scope
    scope.arm()
    target = cw.target(scope)
    # print(target)

    print("Scope is armed")

    print(f"Current trigger source: {scope.trigger.triggers}")
    print(f"Current IO settings: TIO1={scope.io.tio1}, TIO2={scope.io.tio2}, TIO3={scope.io.tio3}, TIO4={scope.io.tio4}")

    

    # Step 4: Capture the trace while running the benchmark
    target.simpleserial_write('b', bytearray([0]))  # Send 'b' command to run benchmark
    
    print(target)
    
    time.sleep(2)

    trace = scope.get_last_trace()
    if trace is None:
        print("Failed to capture trace")
    else:
        # Display info about the trace
        print(f"Captured trace of length: {len(trace)}")
        
        # Plot the trace
        plt.figure()
        plt.plot(trace)
        plt.title('Power Trace of Bubble Sort Algorithm')
        plt.xlabel('Sample Number')
        plt.ylabel('Power Consumption')
        plt.grid()
        plt.savefig('bubble_sort_trace.png')
        plt.show()
        
        # Save the trace data to a file
        np.save('bubble_sort_trace.npy', trace)
    
    # Disconnect
    scope.dis()
    print("Disconnected from ChipWhisperer")
    
except Exception as e:
    print(f"Error: {e}")
    if 'scope' in locals():
        try:
            scope.dis()
            print("Disconnected from ChipWhisperer due to error")
        except:
            pass

if name == “main”:
main()

support.h

/* Modified support.h for STM32F3 with ChipWhisperer */

#ifndef SUPPORT_H
#define SUPPORT_H

#include <stdint.h>

// Define board repeat factor for benchmark
#define BOARD_REPEAT_FACTOR 4096
#define CALIB_SCALE 0
#define REPEAT_FACTOR ((BOARD_REPEAT_FACTOR) >> (CALIB_SCALE))

// Function declarations for board control
void initialise_board(void);
void start_trigger(void);
void stop_trigger(void);

// The benchmark function declaration
int benchmark(void) attribute ((noinline));

#endif /* SUPPORT_H */

board support.c

/* boardsupport.c for STM32F3 with ChipWhisperer */

#include “support.h”
#include <stdint.h>

// Include HAL for STM32F3
#include “…/…/firmware/mcu/hal/hal.h”

void initialise_board(void)
{
// Initialize any board-specific hardware
// This is handled by ChipWhisperer’s HAL initialization
}

void start_trigger(void)
{
// Set trigger high for power trace capture
trigger_high();
}

void stop_trigger(void)
{
// Set trigger low when operation completes
trigger_low();
}

bubble sort_mod.c

/* Modified bubbleSort_og.c for ChipWhisperer */

#include “support.h”
#include <stdint.h>
#include “…/…/firmware/mcu/hal/hal.h”
#include “…/…/firmware/mcu/simpleserial/simpleserial.h”

/* This scale factor will be changed to equalise the runtime of the
benchmarks. */
#define SCALE_FACTOR (REPEAT_FACTOR >> 4)

#define WORSTCASE 1
#define FALSE 0
#define TRUE 1
#define NUMELEMS 100
#define MAXDIM (NUMELEMS+1)

void Initialize(int Array);
void BubbleSort(int Array);

/* BUBBLESORT BENCHMARK PROGRAM */
int Array[MAXDIM], Seed;
int factor;

void BubbleSort(int Array);
void Initialize(int Array);

int benchmark(void)
{
Initialize(Array);
BubbleSort(Array);
return 0;
}

void Initialize(int Array)
{
int Index, fact;

#ifdef WORSTCASE
factor = -1;
#else
factor = 1;
#endif

fact = factor;
for (Index = 1; Index <= NUMELEMS; Index++)
Array[Index] = Index*fact;
}

void BubbleSort(int Array)
{
int Sorted = FALSE;
int Temp, Index, i;

for (i = 1; i <= NUMELEMS-1; i++)
{
Sorted = TRUE;
for (Index = 1; Index <= NUMELEMS-1; Index++) {
if (Index > NUMELEMS-i)
break;
if (Array[Index] > Array[Index + 1])
{
Temp = Array[Index];
Array[Index] = Array[Index+1];
Array[Index+1] = Temp;
Sorted = FALSE;
}
}

  if (Sorted)
     break;

}
}

// SimpleSerial command to run the benchmark
uint8_t run_benchmark(uint8_t* data, uint8_t len)
{
start_trigger();

// Run the benchmark multiple times for clearer power trace
for (int i = 0; i < SCALE_FACTOR; i++)
    benchmark();

stop_trigger();

// Return success
return 0x00;

}

int main(void)
{
// Initialize ChipWhisperer platform
platform_init();
init_uart();
trigger_setup();

// Setup SimpleSerial communication
simpleserial_init();

// Register the benchmark command ('b') 
simpleserial_addcmd('b', 0, run_benchmark);

// Main loop for SimpleSerial
while(1)
    simpleserial_get();
    
return 0;

}

Makefile

Makefile for Bubble Sort Benchmark

For ChipWhisperer STM32F3 target

Target build name

TARGET = bubbleSort

Target platform

PLATFORM = CW308_STM32F3

Find ChipWhisperer firmware directory

FIRMWAREPATH = …/…/firmware/mcu

Name for simpleserial project

SS_VER = SS_VER_2_1

Source files

SRC += bubbleSort.c
SRC += boardsupport.c

Cryptographic options

CRYPTO_TARGET = NONE
CRYPTO_OPTIONS =

Include SimpleSerial Makefile

include $(FIRMWAREPATH)/simpleserial/Makefile.simpleserial

Include common firmware Makefile

include $(FIRMWAREPATH)/Makefile.inc

An image of the setup is attached

You are sending the ‘b’ command with a one-byte argument:

but here you defined it to accept no argument:

Try instead sending target.simpleserial_write('b', b'')

If you still have issues, ensure that both Husky and your target are using the same baud rate, and use a debugger to see what your target does in response to the ‘b’ command.

Also, try use the code blocks (“</>” icon in the composition panel) consistently for your code blocks, it will make your posts much more readable, and our job much easier :wink:.

Hey,
Thanks for getting back to me so soon. I did try your suggestions, but I still get an empty trace, and I checked the baud rate, and it is at 234000 since I’m using version 2.1, and I set the target baud the same. I’m yet to use a debugger to verify what is going on in response to the ‘b’ command. I’ll update the thread, as soon as I get something.
Thank you again.

That’s not proper SS 2.1 on the firmware side - you’re missing the scmd argument. Look at the documentation here, and compare your implementation with ours here.