ITPub博客

首页 > 嵌入式/内核开发 > 嵌入式/内核开发 > 《ESP32-P4开发指南—V1.0》第二十六章 RNG实验

《ESP32-P4开发指南—V1.0》第二十六章 RNG实验

原创 嵌入式/内核开发 作者:正点原子 时间:2025-06-06 09:31:18 0 删除 编辑

第二十六章 RNG实验


       本章将介绍ESP32-P4的硬件随机数发生器。我们使用BOOT按键来获取硬件随机数,并且将获取到的随机数值显示在LCD上。同时,LED0用来指示程序运行状态。

       本章分为如下几个小节:

       26.1 RNG介绍

       26.2 硬件设计

       26.3 程序设计

       26.4 下载验证


        26.1 RNG介绍

       随机数发生器(Random Number Generators),用于生成随机数的程序或软件。

       随机数的特性:产生的后面那个数与前面那个数毫无关系。

       随机数又分为真随机数和伪随机数。真随机数:完全随机,毫无规律;伪随机数:用确定性算法计算出的随机数序列,并非真随机。

       ESP32-P4内置一个真随机数发生器,其生成的32位随机数可作为加密等操作的基础。

       ESP32-P4的随机数发生器可通过物理过程而非算法生成真随机数,所有生成的随机数在特定范围内出现的概率完全一致。

       接下来,介绍一下随机数生成的过程,如下图所示。


图26.1.1 随机数生成过程


       随机数的源,在这里称为噪声源。噪声源为系统中的热噪声和异步时钟。使用随机数生成器时,至少启用其一,否则,生成的是伪随机数。热噪声可以来自SAR ADC。当芯片SAR ADC工作时,就会产生比特流,并通过异或(XOR)逻辑运算作为随机数种子进入随机数生成器。RC_FAST_CLK是一种异步时钟源,它通过引入电路亚稳态来增加RNG熵。

       当有噪声来自SAR ADC时,随机数发生器在一个RC_FAST_CLK时钟周期中被输入1位熵,这是由内部RC振荡器产生的。读取LPSYSREG_RNG_DATA_REG寄存器时可用最大速率1MHz异或以获得最大熵。


        26.2 硬件设计


       26.2.1 例程功能

       使用ESP32-P4的硬件随机数发生器来生成随机数,并显示在LCD屏幕上。按下BOOT可以获取一次随机数。同时程序会自动获取0~9范围内的随机数,显示在LCD屏上。LED0闪烁用于提示程序正在运行。


       26.2.2 硬件资源


       1)LED灯

              LED 0 - IO51


       2)KEY按键

              BOOT - IO35


       3)RGBLCD / MIPILCD(引脚太多,不罗列出来)


       26.2.3 原理图

       RNG属于ESP32-P4的片上资源,因此没有对应的连接原理图。


        26.3 程序设计


       26.3.1 RNG的IDF驱动

       使用RNG相关功能函数,必须先导入以下头文件:

#include "esp_random.h"

       接下来,作者将介绍一些常用的函数,这些函数的描述及其作用如下:


       1,得到随机数函数esp_random

       该函数用于从系统中获取时间,其函数原型如下:

uint32_t esp_random(void);

       无函数形参

       函数返回值:

       返回的是0~uint32_max之间的随机数。


       26.3.2 程序流程图


图26.3.2.1 RNG实验程序流程图


       26.3.3 程序解析

       在17_rng例程中,作者在17_rng\components\BSP路径下新增了1个文件夹RNG,并且需要更改CMakeLists.txt内容,以便在其他文件上调用。


       1. RNG驱动代码

       这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。RNG驱动源码包括两个文件:rng.c和rng.h。

       rng.h用于声明rng_get_random_num等函数,以便在其他文件中调用,具体内容不再赘述。

       下面我们再解析rng.c的程序,主要就是两个获取随机数的函数rng_get_random_num和rng_get_random_range,他们的功能是不一样的,代码如下:

/**
 * @brief     得到随机数
 * @param      无
 * @retval      获取到的随机数(32bit)
 */
uint32_t rng_get_random_num(void)
{
    return esp_random();
}
 
/**
 * @brief      得到某个范围内的随机数
 * @param      min,max: 最小,最大值.
 * @retval      得到的随机数(rval),满足:min<=rval<=max
 */
int rng_get_random_range(int min, int max)
{ 
    return esp_random() % (max - min + 1) + min;
}

       上述两个函数都是调用esp_random函数实现功能的。rng_get_random_num函数用于读取一个32位随机数,而rng_get_random_range函数用于读取一个特定范围内的随机数。


       2. CMakeLists.txt文件

       本例程的功能实现主要依靠RNG驱动。要在main函数中,成功调用RNG文件中的内容,就得需要修改BSP文件夹下的CMakeLists.txt文件,修改如下:

set(src_dirs
            LED
KEY
LCD
            RNG)
 
set(include_dirs
           LED
KEY
LCD
            RNG)
 
set(requires
            driver
            esp_lcd
esp_common)
 
idf_component_register( SRC_DIRS ${src_dirs} INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})
 
component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)


       3. main.c驱动代码

       在main.c里面编写如下代码。

void app_main(void)
{
    esp_err_t ret;
    uint8_t key = 0;
    uint32_t random = 0;
    uint8_t t = 0;
 
    ret = nvs_flash_init();   /* 初始化NVS */
    if(ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ESP_ERROR_CHECK(nvs_flash_init());
    }
 
    led_init();       /* LED初始化 */
    key_init();       /* KEY初始化 */
    lcd_init();       /* LCD屏初始化 */
    lcd_show_string(30, 50,  200, 16, 16, "ESP32-P4", RED);
    lcd_show_string(30, 70,  200, 16, 16, "RNG TEST", RED);
    lcd_show_string(30, 90,  200, 16, 16, "ATOM@ALIENTEK", RED);
    lcd_show_string(30, 110, 200, 16, 16, "BOOT:Get Random Num", RED);
    lcd_show_string(30, 130, 200, 16, 16, "Random Num:", RED);
    lcd_show_string(30, 150, 200, 16, 16, "Random Num[0-9]:", RED);
 
    while(1)
    {
        key = key_scan(0);
 
        if (key == BOOT_PRES)    
        {
            random = rng_get_random_num();      /* 获取随机数 */
            lcd_show_num(118, 130, random, 10, 16, BLUE);
            ESP_LOGI("test", "data:%ld ", random);
        }
 
        if ((t % 20) == 0)         
        {                                
            random = rng_get_random_range(0, 9); /* 取[0,9]区间的随机数 */
            lcd_show_num(158, 150, random, 1, 16, BLUE);
 
            LED0_TOGGLE(); 
        }
 
        vTaskDelay(pdMS_TO_TICKS(10));
        t++;
    }
}

       在app_main函数中,完成所需外设初始化以后,进入到死循环,等待按键按下,如果BOOT按键按下,则调用rng_get_random_num函数,读取随机数值,并将读到的随机数显示在LCD上面。每隔200ms调用rng_get_random_range函数获取一次区间[0,9]的随机数,并实时显示在LCD上。LED0闪烁,以提示程序正在运行。


        26.4 下载验证

       将程序下载到开发板后,可以看到LED0不停闪烁,提示程序已经在运行了。然后我们按下BOOT按键,就可以在LCD上看到获取到的随机数。同时,就算不按BOOT按键,程序也会自动的获取0~9区间的随机数显示在LCD上。实验效果如图26.4.1所示。


图26.4.1 RNG实验程序运行效果图


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70040860/viewspace-3086834/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2024-08-30

  • 博文量
    588
  • 访问量
    784174