cancel
Showing results for 
Search instead for 
Did you mean: 

STM32WBA PKA bare-metal implementation. Troubles loading data into RAM

elopezpe
Associate

Hello all,

I am working on a bare-metal implementation of the PKA engine using the STM32WBA55CG. I have managed to properly initialize both the RNG and the PKA engines, but I cannot seem to load the operands on the RAM. 

I am trying to implement the modular addition, following the datasheet (https://www.st.com/resource/en/reference_manual/rm0493-multiprotocol-wireless-bluetooth-lowenergy-and-ieee802154-stm32wba5xxx-armbased-32bit-mcus-stmicroelectronics.pdf page 863). I am using Rust as programming language. 

I attach the code. The problem is that whenever trying to write the data, using core::ptr::write_volatile, the code just stops and nothing is done.

 

The outputs I have are:

 

#![no_std]
#![no_main]

use stm32wba::stm32wba55::{self, RAMCFG};
use {defmt_rtt as _, panic_probe as _};
use cortex_m_rt::entry;
use cortex_m::asm;
use defmt::info;

// PKA RAM locations - these are already offsets from PKA base address
const PKA_RAM_OFFSET: u32 = 0x400; 
const OPERAND_LENGTH_OFFSET: u32 = 0x408 - 0x400; // Relative to PKA_RAM_OFFSET
const OPERAND_A_OFFSET: u32 = 0xA50 - 0x400;
const OPERAND_B_OFFSET: u32 = 0xC68 - 0x400;
const MODULUS_OFFSET: u32 = 0x1088 - 0x400;
const RESULT_OFFSET: u32 = 0xE78 - 0x400;

const OPERAND_LENGTH: u32 = 64;
const A: u32 = 3;      // First operand
const B: u32 = 11;     // Second operand
const N: u32 = 13;     // Modulus for addition

#[entry]
unsafe fn main() -> ! {
    let p = stm32wba55::Peripherals::take().unwrap();
    let pka = &p.PKA;
    let clock = &p.RCC;
    let rng = &p.RNG;

     // Enable HSI as a stable clock source
     clock.rcc_cr().modify(|_, w| w
        .hseon().set_bit()
        // .hsikeron().set_bit()
    );
    while clock.rcc_cr().read().hserdy().bit_is_clear() {
        asm::nop();
    }

    // Enable RNG clock. Select the source clock
    clock.rcc_ccipr2().write(|w| w.rngsel().b_0x2());
    // Enable RNG clock. Select the AHB clock
    clock.rcc_ahb2enr().modify(|_, w| w.rngen().set_bit());
    while clock.rcc_ahb2enr().read().rngen().bit_is_clear() {
        asm::nop();
    }

    rng.rng_cr().write(|w| w
        .rngen().clear_bit()
        .condrst().set_bit()
        .configlock().clear_bit()
        // .clkdiv().b_0x0()    
        .nistc().clear_bit()   // Hardware default values for NIST compliant RNG
        .ced().clear_bit()     // Clock error detection enabled
    );
    rng.rng_cr().modify(|_, w| w
        .condrst().clear_bit()
    );
    rng.rng_cr().modify(|_, w| w
        .rngen().set_bit()
        .ie().set_bit()
    );
    
    while rng.rng_sr().read().drdy().bit_is_clear() {
        asm::nop();
    }
    // Enable PKA peripheral clock via RCC_AHB2ENR register
    clock.rcc_ahb2enr().modify(|_, w| w.pkaen().set_bit());

    // Reset PKA before enabling (sometimes helps with initialization)
    pka.pka_cr().modify(|_, w| w.en().clear_bit());
    for _ in 0..10 {
        asm::nop();
    }

    // Enable PKA peripheral
    pka.pka_cr().write(|w| w
        .en().set_bit()
        .mode().bits(0x0E)  // Modular addition mode
    );
 
    // Wait for PKA to initialize
    while pka.pka_sr().read().initok().bit_is_clear() {
        asm::nop();
    }

    // PKA RAM base address
    let pka_base = &p.PKA as *const _ as u32;
    let pka_ram_base = pka_base + PKA_RAM_OFFSET;
    
    info!("PKA peripheral base address: {:#08x}", pka_base);
    info!("PKA RAM base address: {:#08x}", pka_ram_base);

    // Access PKA RAM as 32-bit words 
    let pka_ram = pka_ram_base as *mut u32;
    
    // Calculate correct offsets in 32-bit words (divide by 4 instead of 8)
    let length_addr = pka_ram.add((OPERAND_LENGTH_OFFSET / 4) as usize);
    let a_addr = pka_ram.add((OPERAND_A_OFFSET / 4) as usize);
    let b_addr = pka_ram.add((OPERAND_B_OFFSET / 4) as usize);
    let modulus_addr = pka_ram.add((MODULUS_OFFSET / 4) as usize);
    let result_addr = pka_ram.add((RESULT_OFFSET / 4) as usize);

    // Clear any previous error flags
    pka.pka_clrfr().write(|w| w
        .addrerrfc().set_bit()
        .ramerrfc().set_bit()
        .procendfc().set_bit()
    );

    // Write the values - using 32-bit words
    info!("Writing operand length...");
    core::ptr::write_volatile(length_addr, OPERAND_LENGTH);
    
    info!("Writing operand A...");
    core::ptr::write_volatile(a_addr, A);
    core::ptr::write_volatile(a_addr.add(1), 0); // Additional zero word
    
    info!("Writing operand B...");
    core::ptr::write_volatile(b_addr, B);
    core::ptr::write_volatile(b_addr.add(1), 0); // Additional zero word
    
    info!("Writing modulus...");
    core::ptr::write_volatile(modulus_addr, N);
    core::ptr::write_volatile(modulus_addr.add(1), 0); // Additional zero word

    info!("Data loaded");
    info!("ADDRERRF is clear: {}", pka.pka_sr().read().addrerrf().bit_is_clear());

    // Configure PKA operation mode and start
    info!("Starting PKA operation...");
    pka.pka_cr().modify(|_, w| w
        .mode().bits(0x0E)  // Modular addition mode
        .start().set_bit()  // Start the operation
    );

    // Wait for processing to complete - PROCENDF is 1 when done
    info!("Waiting for operation to complete...");
    while pka.pka_sr().read().procendf().bit_is_clear() {
        asm::nop();
    }
    info!("Operation complete!");

    // Read the result
    let result = core::ptr::read_volatile(result_addr);
    info!("Modular Addition: {} + {} (mod {}) = {}", A, B, N, result);
    
    // Clear the completion flag
    pka.pka_clrfr().write(|w| w.procendfc().set_bit());

    loop {}
}

 

INFO HSE ready: true
└─ pka::__cortex_m_rt_main @ src/bin/pka.rs:40
INFO RNG clock enabled: true
└─ pka::__cortex_m_rt_main @ src/bin/pka.rs:49
INFO SEIS bit is 0: true SECS bit is 0: true CEIS bit is 0: true CECS bit is 0: true
└─ pka::__cortex_m_rt_main @ src/bin/pka.rs:73
INFO RNG enabled successfully
└─ pka::__cortex_m_rt_main @ src/bin/pka.rs:84
INFO PKA clock enabled: true
└─ pka::__cortex_m_rt_main @ src/bin/pka.rs:89
INFO PKA enabled: true
└─ pka::__cortex_m_rt_main @ src/bin/pka.rs:104
INFO INITOK bit set: true
└─ pka::__cortex_m_rt_main @ src/bin/pka.rs:107
INFO PKA initialized successfully!
└─ pka::__cortex_m_rt_main @ src/bin/pka.rs:111
INFO PKA RAM base address: 0x2001fe92
└─ pka::__cortex_m_rt_main @ src/bin/pka.rs:118
INFO Writing operand length...
└─ pka::__cortex_m_rt_main @ src/bin/pka.rs:144  

 

And it then stops. I am thinking it might be something off with the memory addresses or how I am trying to access the RAM memory. 

 

Thanks for the help,

 

Elsa

0 REPLIES 0