今回はSTM32マイコンのRNG(Random Number Generator:乱数生成器)機能を使って物理乱数を生成する方法を紹介します。

STM32マイコンのRNGはアナログ回路のノイズに基づいて真性乱数に近い(乱数品質の良い)32bitの物理乱数を発生させる周辺機能です。
RNGはSTM32 F2, F7, H7, L4, L4+の全機種と、F4, L0の一部機種に搭載されています。
参考:STM32L4-Security-Random Number Generator (RNG)

STM32CubeMXの設定方法

ここではNUCLEO-L476RGを使ったSTM32CubeMXの設定方法を紹介します。
まずRNGを有効にします。

RNGは外部ピンへの入出力を行わないのでシンプルです。

次にクロックの設定をします。

今回はRNGのクロック源はPLLQ:40MHzに設定しました。

RNGの詳細設定ですが、特に設定する項目はありません。

以上です。 RNGは外部ピンへの入出力も複雑な設定項目もないので非常に簡単に設定できます。

HALによるRNGの使い方

MX_RNG_Init()による初期化後、HAL_RNG_GenerateRandomNumber関数を呼びます。

図のようにHAL_RNG_GenerateRandomNumberの第二引数に乱数を入れたい変数のポインタを入れることで乱数を生成できます。 なお、このプログラムでは乱数をprintfで表示後、NVIC_SystemReset関数でソフトウェアリセットかけています。

実際に出力を見てみます。

リセット毎に別の値が出力されており、問題なく乱数が生成できていそうです。

C言語標準のrand関数やメルセンヌ・ツイスタ等の疑似乱数生成器は同一のシード値を与えると必ず同じ乱数列を生成するという特徴があるため問題が生じることがあります。
例えば2つのMCUを用いてWifi通信を行うようなアプリケーションにおいて、もし同時にMCUを起動した場合、MCUの通信タイミングが完全に被るため双方ともに通信の衝突が起こります。CSMA/CAのような衝突回避方式を採用していた場合であっても、そのプロトコル内の「ランダムな時間だけ待つ」のランダムの部分が同一のシード値の疑似乱数生成器を使っている場合は同じ値になってしまうので互いに衝突し続けWifi通信を行えないといった問題が生じることがあります。
このような場合、RNGを使うことで個々のMCUに起動毎にユニークな値を割り付けられるため、この乱数を使ってHAL_Delayなどで個々のMCUを遅延させることで衝突を回避できます。