cancel
Showing results for 
Search instead for 
Did you mean: 

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

elopezpe
Associate II

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 {} }
View more

 

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

2 REPLIES 2
Jocelyn RICARD
ST Employee

Hello @elopezpe ,

please check examples provided in

STM32Cube_FW_WB_V1.21.0\Projects\P-NUCLEO-WB55.Nucleo\Examples\PKA\

This should give you a working reference that allows understanding what is not working in your case.

Best regards

Jocelyn

Hello,

 

Thank you for your answer. I went over the information you sent, but I cannot see where the PKA base address is located. I found a link to a PKA impelmentation in Rust for the micro stm32wlxx (https://docs.rs/stm32wlxx-hal/latest/src/stm32wlxx_hal/pka.rs.html#241-243), and they define base as 0x5800_2000. However, when I go to the documentation of that said micro (https://www.st.com/resource/en/reference_manual/rm0453-stm32wl5x-advanced-armbased-32bit-mcus-with-subghz-radio-solution-stmicroelectronics.pdf), there is no such definition and in the memory map I see that the AHB2 is located at address 0x5800_0000. In the section of the PKA RAM, they say exactly the same as in the section of the STM32WBAxx:

STM32WLxx:

PKA RAM
The PKA RAM is mapped at the offset address of 0x0400 compared to the PKA base
address. Only 32-bit word single accesses are supported, through PKA.AHB interface.
RAM size is 3576 bytes (max word offset: 0x11F4).

STM32WBAxx:

PKA RAM
The PKA RAM is mapped at the offset address of 0x0400 compared to the PKA base
address. Only 32-bit word single accesses are supported, through PKA.AHB interface.
RAM size is 5336 bytes (max word offset: 0x14D0)
Note: PKA RAM cannot be used just after a PKA reset or a product reset, as described in
Section 28.3.3: PKA reset and clocks

 

I have managed to write into the memory, but when reading the result I get something wrong, which does not change before or after computation. So my guess is that I am not writing in the correct memory region. If you could point to where to find this information it would be very much appreciated.

 

Elsa