#include "stm32l4xx_hal_rng.h"
RNG_HandleTypeDef hrng;
uint32_t randomNumber;
void setup() {
Serial.begin(9600);
delay(3000);
__HAL_RCC_RNG_CLK_ENABLE();
hrng.Instance = RNG;
HAL_RNG_Init(&hrng);
}
void loop() {
// put your main code here, to run repeatedly:
HAL_RNG_GenerateRandomNumber(&hrng, (uint32_t *)randomNumber);
Serial.println(randomNumber, DEC);
}
https://github.com/stm32duino/Arduino_C … conf.h#L83
I’m not sure of the reason for this. I’m not sure if the RNG code its self declares any static stucts that would take RAM, or whether other init functions are needed to be performed to use the RNG etc (probably not)
Anyway, At the moment your only option is to change that file and rebuild the static library after changing that header to enable the features you want.
I will post a github issue about it.
How do you eat an elephant?
One bite at a time.
I think you are one of the first people to actively use the Nucleo L476, so you are somewhat on the bleeding edge with this.
I have a Nucleo L476 (which ST sent me) and I did do some quick tests e.g. SPI and I2C connectivity and I found some issues with the CPU clock rate and also the SPI clock speed, but I did not try using any HAL functions.
I don’t know if the company who STM contracted to write the code (Wi6Labs), actively monitor the issues in github, but I’ve already emailed them today, in relation to some less than optimal code (wastes precious RAM on the F1 and does the same on the L4 – but it doesn’t matter so much on the L4 because its got a lot of RAM), so hopefully Wi6Labs will look at all the open issues in the L4 and perhaps STM will get back to me.
BTW. Did you install via boards manager package or by cloning or download from github ?
Also, its amazing what sleeping on it will do, sometimes.
This code generates truly random numbers. My problem, as has been so far, was that I wasn’t setting up the peripheral to a clock properly.
RNG_HandleTypeDef hrng;
uint32_t randomNumber;
void setup() {
Serial.begin(9600);
delay(3000);
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RNG;
PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_PLL;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
__HAL_RCC_RNG_CLK_ENABLE();
hrng.Instance = RNG;
HAL_RNG_Init(&hrng);
int i;
for (i=1; i<25; i++) {
HAL_RNG_GenerateRandomNumber(&hrng, &randomNumber);
Serial.println(randomNumber);
}
}
void loop() {
// put your main code here, to run repeatedly:
}
Though I am not quite sure whether we should enable absolutely everything.
Also, its amazing what sleeping on it will do, sometimes.
This code generates truly random numbers. My problem, as has been so far, was that I wasn’t setting up the peripheral to a clock properly.
RNG_HandleTypeDef hrng;
uint32_t randomNumber;
void setup() {
Serial.begin(9600);
delay(3000);
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RNG;
PeriphClkInitStruct.RngClockSelection = RCC_RNGCLKSOURCE_PLL;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
__HAL_RCC_RNG_CLK_ENABLE();
hrng.Instance = RNG;
HAL_RNG_Init(&hrng);
int i;
for (i=1; i<25; i++) {
HAL_RNG_GenerateRandomNumber(&hrng, &randomNumber);
Serial.println(randomNumber);
}
}
void loop() {
// put your main code here, to run repeatedly:
}
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE |RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLM = 6;
RCC_OscInitStruct.PLL.PLLN = 20;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLP = 7;
RCC_OscInitStruct.PLL.PLLQ = 4;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
/* Initialization Error */
while(1);
}
HAL_RCCEx_EnableMSIPLLMode();
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
/* Initialization Error */
while(1);
}
}
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE |RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLM = 6;
RCC_OscInitStruct.PLL.PLLN = 20;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLP = 7;
RCC_OscInitStruct.PLL.PLLQ = 4;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
/* Initialization Error */
while(1);
}
HAL_RCCEx_EnableMSIPLLMode();
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
/* Initialization Error */
while(1);
}
}
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE |RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11;
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
RCC_OscInitStruct.PLL.PLLM = 6;
RCC_OscInitStruct.PLL.PLLN = 20;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLP = 7;
RCC_OscInitStruct.PLL.PLLQ = 4;
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
/* Initialization Error */
while(1);
}
HAL_RCCEx_EnableMSIPLLMode();
/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
/* Initialization Error */
while(1);
}
}
Thanks for the detailed explanation.
As the Nucleo is permanently powered from USB , I dont think current consumption would be an issue, but it would be if we made a generic variant.
Perhaps the way forward is for the OP to make a RNG library and call the PLL code from its begin function.
( I was going to say, do the RNG PLL setup in the constructor, but as we know, the order in which global constructors are called is not defined)
Thanks for the detailed explanation.
As the Nucleo is permanently powered from USB , I dont think current consumption would be an issue, but it would be if we made a generic variant.
Perhaps the way forward is for the OP to make a RNG library and call the PLL code from its begin function.
( I was going to say, do the RNG PLL setup in the constructor, but as we know, the order in which global constructors are called is not defined)
We’ll need to refactor the L4 code like we did for the F1, because in the L4 repo the SystemClock_Config is currently not in variant.cpp
We’ll need to refactor the L4 code like we did for the F1, because in the L4 repo the SystemClock_Config is currently not in variant.cpp
1. We don’t want different file structures in different cores as it makes it hard to maintain. (See @danieleff’s posting)
2. I know of at least one user who is using the Arduino IDE for rapid prototyping for a low power project which will probably use one of the L4 series (and he he is using the Nucleo L476 at the moment)
Ultimately he intends to produce a commercial product, but there is technically nothing to stop him using the Arduino IDE’s compiled binaries in a commercial product if he wants to.
1. We don’t want different file structures in different cores as it makes it hard to maintain. (See @danieleff’s posting)
2. I know of at least one user who is using the Arduino IDE for rapid prototyping for a low power project which will probably use one of the L4 series (and he he is using the Nucleo L476 at the moment)
Ultimately he intends to produce a commercial product, but there is technically nothing to stop him using the Arduino IDE’s compiled binaries in a commercial product if he wants to.
People want better support for the F4 and F7 as well as support for the F0, but modifying libmaple to work across all those MCU’s would be a big job, and no one has the time or energy to do it.
I was hoping that STM’s official core would address this, but I’d rather not put Wi6Labs offside at the moment, as AFIK they are supposed to fix bugs in their code (though I don’t know if their dev contract with STM has ended or not and whether this still applies)
I know there is talk about creating a core based on LibOpenCM3 or some new variation of that, but I don’t see it happening in the near future.
In the mean time Avik De, still carries on his Koduino old Standard Peripheral Library based core, but in his boards.txt file it only appears to support two different F3 variants and one F4 – (even though there appears to be variant folders for a wider variety of MCU versions)
So as long as people are interested in developing and improving the HAL core, I’m happy to manage it, and it may eventually end up being usable ![]()
People want better support for the F4 and F7 as well as support for the F0, but modifying libmaple to work across all those MCU’s would be a big job, and no one has the time or energy to do it.
I was hoping that STM’s official core would address this, but I’d rather not put Wi6Labs offside at the moment, as AFIK they are supposed to fix bugs in their code (though I don’t know if their dev contract with STM has ended or not and whether this still applies)
I know there is talk about creating a core based on LibOpenCM3 or some new variation of that, but I don’t see it happening in the near future.
In the mean time Avik De, still carries on his Koduino old Standard Peripheral Library based core, but in his boards.txt file it only appears to support two different F3 variants and one F4 – (even though there appears to be variant folders for a wider variety of MCU versions)
So as long as people are interested in developing and improving the HAL core, I’m happy to manage it, and it may eventually end up being usable ![]()
do libraries such as tone and servo do the right thing?

