Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions examples/stm32wb/stm32wb55xx_nucleo.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,12 @@ whal_Spi g_whalSpi = {
.clk = &(whal_Stm32wbRcc_Clk) {WHAL_STM32WB55_SPI1_CLOCK},
},
};

whal_Rng g_whalRng = {
WHAL_STM32WB55_RNG_DEVICE,

.cfg = &(whal_Stm32wbRng_Cfg) {
.clkCtrl = &g_whalClock,
.clk = &(whal_Stm32wbRcc_Clk) {WHAL_STM32WB55_RNG_CLOCK},
},
};
3 changes: 3 additions & 0 deletions examples/stm32wb/stm32wb55xx_nucleo.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,7 @@ extern whal_Flash g_whalFlash;
/* SPI controller instance. */
extern whal_Spi g_whalSpi;

/* RNG instance. */
extern whal_Rng g_whalRng;

#endif /* STM32WB55XX_NUCLEO_H */
27 changes: 27 additions & 0 deletions src/clock/stm32wb_rcc.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
/* Clock Control Register - oscillator enables and status */
#define ST_RCC_CR_REG 0x000
#define ST_RCC_CR_MSIRANGE WHAL_MASK_RANGE(7, 4) /* MSI frequency range */
#define ST_RCC_CR_HSION_MASK WHAL_MASK(8) /* HSI enable */
#define ST_RCC_CR_PLLON_MASK WHAL_MASK(24) /* PLL enable */

/* Clock Configuration Register - clock source and prescaler selection */
Expand Down Expand Up @@ -73,6 +74,11 @@
#define ST_RCC_APB1ENR2_LPUART1EN WHAL_MASK(0) /* LPUART1 clock enable */
#define ST_RCC_APB1ENR2_LPTIM2EN WHAL_MASK(5) /* LPTIM2 clock enable */

/* Clock Recovery RC Register - HSI48 oscillator control */
#define ST_RCC_CRRCR_REG 0x098
#define ST_RCC_CRRCR_HSI48ON_MASK WHAL_MASK(0) /* HSI48 oscillator enable */
#define ST_RCC_CRRCR_HSI48RDY_MASK WHAL_MASK(1) /* HSI48 oscillator ready */

whal_Error whal_Stm32wbRccPll_Init(whal_Clock *clkDev)
{
whal_Error err;
Expand Down Expand Up @@ -303,6 +309,27 @@ whal_Error whal_Stm32wbRccMsi_GetRate(whal_Clock *clkDev, size_t *rateOut)

return WHAL_SUCCESS;
}

whal_Error whal_Stm32wbRcc_Ext_EnableHsi48(whal_Clock *clkDev, uint8_t enable)
{
if (!clkDev) {
return WHAL_EINVAL;
}

whal_Reg_Update(clkDev->regmap.base, ST_RCC_CRRCR_REG, ST_RCC_CRRCR_HSI48ON_MASK,
whal_SetBits(ST_RCC_CRRCR_HSI48ON_MASK, enable));

if (enable) {
size_t rdy;
do {
whal_Reg_Get(clkDev->regmap.base, ST_RCC_CRRCR_REG,
ST_RCC_CRRCR_HSI48RDY_MASK, &rdy);
} while (!rdy);
}

return WHAL_SUCCESS;
}

const whal_ClockDriver whal_Stm32wbRccPll_Driver = {
.Init = whal_Stm32wbRccPll_Init,
.Deinit = whal_Stm32wbRccPll_Deinit,
Expand Down
30 changes: 30 additions & 0 deletions src/rng/rng.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <stdint.h>
#include <wolfHAL/rng/rng.h>
#include <wolfHAL/error.h>

inline whal_Error whal_Rng_Init(whal_Rng *rngDev)
{
if (!rngDev || !rngDev->driver || !rngDev->driver->Init) {
return WHAL_EINVAL;
}

return rngDev->driver->Init(rngDev);
}

inline whal_Error whal_Rng_Deinit(whal_Rng *rngDev)
{
if (!rngDev || !rngDev->driver || !rngDev->driver->Deinit) {
return WHAL_EINVAL;
}

return rngDev->driver->Deinit(rngDev);
}

inline whal_Error whal_Rng_Generate(whal_Rng *rngDev, uint8_t *rngData, size_t rngDataSz)
{
if (!rngDev || !rngDev->driver || !rngDev->driver->Generate || !rngData) {
return WHAL_EINVAL;
}

return rngDev->driver->Generate(rngDev, rngData, rngDataSz);
}
124 changes: 124 additions & 0 deletions src/rng/stm32wb_rng.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#include <stdint.h>
#include <wolfHAL/rng/stm32wb_rng.h>
#include <wolfHAL/rng/rng.h>
#include <wolfHAL/clock/clock.h>
#include <wolfHAL/error.h>
#include <wolfHAL/regmap.h>
#include <wolfHAL/bitops.h>

/*
* STM32WB RNG Register Definitions
*
* The RNG peripheral uses an analog noise source to produce 32-bit
* random values. One value is available at a time in DR, signaled
* by the DRDY flag in SR.
*/

/* Control Register */
#define SRNG_CR_REG 0x00
#define SRNG_CR_RNGEN WHAL_MASK(2) /* RNG enable */
#define SRNG_CR_CED WHAL_MASK(5) /* Clock error detection disable */

/* Status Register */
#define SRNG_SR_REG 0x04
#define SRNG_SR_DRDY WHAL_MASK(0) /* Data ready */
#define SRNG_SR_CECS WHAL_MASK(1) /* Clock error current status */
#define SRNG_SR_SECS WHAL_MASK(2) /* Seed error current status */
#define SRNG_SR_CEIS WHAL_MASK(5) /* Clock error interrupt status */
#define SRNG_SR_SEIS WHAL_MASK(6) /* Seed error interrupt status */

/* Data Register - 32-bit random value */
#define SRNG_DR_REG 0x08

whal_Error whal_Stm32wbRng_Init(whal_Rng *rngDev)
{
whal_Error err;
whal_Stm32wbRng_Cfg *cfg;

if (!rngDev || !rngDev->cfg) {
return WHAL_EINVAL;
}

cfg = (whal_Stm32wbRng_Cfg *)rngDev->cfg;

err = whal_Clock_Enable(cfg->clkCtrl, cfg->clk);
if (err != WHAL_SUCCESS) {
return err;
}

return WHAL_SUCCESS;
}

whal_Error whal_Stm32wbRng_Deinit(whal_Rng *rngDev)
{
whal_Error err;

if (!rngDev || !rngDev->cfg) {
return WHAL_EINVAL;
}

whal_Stm32wbRng_Cfg *cfg = (whal_Stm32wbRng_Cfg *)rngDev->cfg;

err = whal_Clock_Disable(cfg->clkCtrl, cfg->clk);
if (err) {
return err;
}

return WHAL_SUCCESS;
}

whal_Error whal_Stm32wbRng_Generate(whal_Rng *rngDev, uint8_t *rngData, size_t rngDataSz)
{
if (!rngDev || !rngData) {
return WHAL_EINVAL;
}

whal_Error err = WHAL_SUCCESS;
const whal_Regmap *reg = &rngDev->regmap;
size_t status;
size_t offset = 0;

/* Enable the RNG peripheral */
whal_Reg_Update(reg->base, SRNG_CR_REG, SRNG_CR_RNGEN,
whal_SetBits(SRNG_CR_RNGEN, 1));

while (offset < rngDataSz) {
/* Wait for a random value to be ready */
do {
/* Check for seed or clock error */
whal_Reg_Get(reg->base, SRNG_SR_REG, SRNG_SR_SECS, &status);
if (status) {
err = WHAL_EHARDWARE;
goto exit;
}
whal_Reg_Get(reg->base, SRNG_SR_REG, SRNG_SR_CECS, &status);
if (status) {
err = WHAL_EHARDWARE;
goto exit;
}

whal_Reg_Get(reg->base, SRNG_SR_REG, SRNG_SR_DRDY, &status);
} while (!status);

/* Read 32-bit random value */
uint32_t rnd = *(volatile uint32_t *)(reg->base + SRNG_DR_REG);

/* Copy bytes into output buffer */
for (size_t i = 0; i < 4 && offset < rngDataSz; i++, offset++) {
rngData[offset] = (uint8_t)(rnd >> (i * 8));
}
}

exit:
/* Disable the RNG peripheral */
whal_Reg_Update(reg->base, SRNG_CR_REG, SRNG_CR_RNGEN,
whal_SetBits(SRNG_CR_RNGEN, 0));

return err;
}

const whal_RngDriver whal_Stm32wbRng_Driver = {
.Init = whal_Stm32wbRng_Init,
.Deinit = whal_Stm32wbRng_Deinit,
.Generate = whal_Stm32wbRng_Generate,
};
1 change: 1 addition & 0 deletions tests/sim/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ WHAL_SRC = $(WHAL_DIR)/src/clock/clock.c \
$(WHAL_DIR)/src/flash/flash.c \
$(WHAL_DIR)/src/timer/timer.c \
$(WHAL_DIR)/src/spi/spi.c \
$(WHAL_DIR)/src/rng/rng.c \
$(WHAL_DIR)/src/supply/supply.c

SOURCE = $(TEST_SRC) $(WHAL_SRC)
Expand Down
39 changes: 39 additions & 0 deletions tests/sim/test_dispatch.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <stdint.h>
#include <wolfHAL/wolfHAL.h>
#include <wolfHAL/timer/timer.h>
#include <wolfHAL/rng/rng.h>
#include "../test.h"

/*
Expand Down Expand Up @@ -78,6 +79,16 @@ static const whal_TimerDriver mockTimerDriver = {
.Reset = mockTimerReset,
};

static whal_Error mockRngInit(whal_Rng *d) { (void)d; return WHAL_SUCCESS; }
static whal_Error mockRngDeinit(whal_Rng *d) { (void)d; return WHAL_SUCCESS; }
static whal_Error mockRngGenerate(whal_Rng *d, uint8_t *data, size_t sz) { (void)d; (void)data; (void)sz; return WHAL_SUCCESS; }

static const whal_RngDriver mockRngDriver = {
.Init = mockRngInit,
.Deinit = mockRngDeinit,
.Generate = mockRngGenerate,
};

/* --- Clock dispatch tests --- */

static void test_clock_null_dev(void)
Expand Down Expand Up @@ -222,6 +233,31 @@ static void test_timer_valid_dispatch(void)
WHAL_ASSERT_EQ(whal_Timer_Reset(&dev), WHAL_SUCCESS);
}

/* --- RNG dispatch tests --- */

static void test_rng_null_dev(void)
{
uint8_t buf[1];
WHAL_ASSERT_EQ(whal_Rng_Init(NULL), WHAL_EINVAL);
WHAL_ASSERT_EQ(whal_Rng_Deinit(NULL), WHAL_EINVAL);
WHAL_ASSERT_EQ(whal_Rng_Generate(NULL, buf, 1), WHAL_EINVAL);
}

static void test_rng_null_driver(void)
{
whal_Rng dev = { .driver = NULL };
WHAL_ASSERT_EQ(whal_Rng_Init(&dev), WHAL_EINVAL);
}

static void test_rng_valid_dispatch(void)
{
whal_Rng dev = { .driver = &mockRngDriver };
WHAL_ASSERT_EQ(whal_Rng_Init(&dev), WHAL_SUCCESS);
uint8_t buf[4] = {0};
WHAL_ASSERT_EQ(whal_Rng_Generate(&dev, buf, sizeof(buf)), WHAL_SUCCESS);
WHAL_ASSERT_EQ(whal_Rng_Deinit(&dev), WHAL_SUCCESS);
}

void test_dispatch(void)
{
WHAL_TEST_SUITE_START("dispatch");
Expand All @@ -241,5 +277,8 @@ void test_dispatch(void)
WHAL_TEST(test_timer_null_dev);
WHAL_TEST(test_timer_null_driver);
WHAL_TEST(test_timer_valid_dispatch);
WHAL_TEST(test_rng_null_dev);
WHAL_TEST(test_rng_null_driver);
WHAL_TEST(test_rng_valid_dispatch);
WHAL_TEST_SUITE_END();
}
Binary file modified tests/sim/test_sim
Binary file not shown.
2 changes: 1 addition & 1 deletion tests/stm32wb/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ LDFLAGS = --omagic -static
DEPDIR = .deps/

# Test sources
TEST_SRC = test_main.c test_clock.c test_gpio.c test_flash.c test_timer.c
TEST_SRC = test_main.c test_clock.c test_gpio.c test_flash.c test_timer.c test_rng.c

# Board config and IVT from the example
BOARD_SRC = $(EXAMPLE_DIR)/stm32wb55xx_nucleo.c \
Expand Down
2 changes: 2 additions & 0 deletions tests/stm32wb/test_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ void test_clock(void);
void test_gpio(void);
void test_flash(void);
void test_timer(void);
void test_rng(void);

void main(void)
{
Expand Down Expand Up @@ -84,6 +85,7 @@ void main(void)
test_gpio();
test_flash();
test_timer();
test_rng();

WHAL_TEST_SUMMARY();

Expand Down
68 changes: 68 additions & 0 deletions tests/stm32wb/test_rng.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include <stdint.h>
#include <wolfHAL/wolfHAL.h>
#include <wolfHAL/clock/stm32wb_rcc.h>
#include <wolfHAL/rng/stm32wb_rng.h>
#include <wolfHAL/bitops.h>
#include "stm32wb55xx_nucleo.h"
#include "../test.h"

static void test_rng_init_deinit(void)
{
WHAL_ASSERT_EQ(whal_Rng_Init(&g_whalRng), WHAL_SUCCESS);
WHAL_ASSERT_EQ(whal_Rng_Deinit(&g_whalRng), WHAL_SUCCESS);
}

static void test_rng_generate_nonzero(void)
{
uint8_t buf[16] = {0};
int allZero = 1;

whal_Stm32wbRcc_Ext_EnableHsi48(&g_whalClock, 1);
WHAL_ASSERT_EQ(whal_Rng_Init(&g_whalRng), WHAL_SUCCESS);
WHAL_ASSERT_EQ(whal_Rng_Generate(&g_whalRng, buf, sizeof(buf)), WHAL_SUCCESS);
WHAL_ASSERT_EQ(whal_Rng_Deinit(&g_whalRng), WHAL_SUCCESS);
whal_Stm32wbRcc_Ext_EnableHsi48(&g_whalClock, 0);

for (size_t i = 0; i < sizeof(buf); i++) {
if (buf[i] != 0) {
allZero = 0;
break;
}
}

/* 16 zero bytes from a TRNG is astronomically unlikely */
WHAL_ASSERT_EQ(allZero, 0);
}

static void test_rng_generate_unique(void)
{
uint8_t buf1[16] = {0};
uint8_t buf2[16] = {0};
int same = 1;

whal_Stm32wbRcc_Ext_EnableHsi48(&g_whalClock, 1);
WHAL_ASSERT_EQ(whal_Rng_Init(&g_whalRng), WHAL_SUCCESS);
WHAL_ASSERT_EQ(whal_Rng_Generate(&g_whalRng, buf1, sizeof(buf1)), WHAL_SUCCESS);
WHAL_ASSERT_EQ(whal_Rng_Generate(&g_whalRng, buf2, sizeof(buf2)), WHAL_SUCCESS);
WHAL_ASSERT_EQ(whal_Rng_Deinit(&g_whalRng), WHAL_SUCCESS);
whal_Stm32wbRcc_Ext_EnableHsi48(&g_whalClock, 0);

for (size_t i = 0; i < sizeof(buf1); i++) {
if (buf1[i] != buf2[i]) {
same = 0;
break;
}
}

/* Two consecutive 16-byte outputs should differ */
WHAL_ASSERT_EQ(same, 0);
}

void test_rng(void)
{
WHAL_TEST_SUITE_START("rng");
WHAL_TEST(test_rng_init_deinit);
WHAL_TEST(test_rng_generate_nonzero);
WHAL_TEST(test_rng_generate_unique);
WHAL_TEST_SUITE_END();
}
Loading