W801/W800/W806 唯一 ID/CPUID/FLASHID

发布于 2022-04-18 19: 01: 17

@TOC

本文使用环境:
主控: W800-KIT (开发板)
兼容: W800 W801 AIR101
开发环境: CDK
SDK: W801/W800 的 SDK (tls 库) , HAL 库没有实现 uniqueid 的适配

==我的联盛德问答社区主页==
我的 CSDN 文章

一, 项目概述

^^^^程序功能: 读取一个 ID 作为识别或者其他用途.

^^^^这篇教程主要是归纳总结, 相对而言比较简单. 本文主要从三个角度去获取 ID: CPUID, FLASHID, uniqueid.
CPUID: 32 位 这 ID 不是我们传统意义上的 ID, 我问过官方, 这是内核 ID, 只要是内核一样, ID 就一样, 不是唯一的.
flashID: 8 字节 不同的 flash 对应的 ID 不一样, 但是目前不清楚是不是一批次都是一个 ID.
uniqueID: 18 字节 这个不是一个独立的 ID, 是将 flash 等参数融合过后的 ID, 据说是唯一的 ID.

二, 工程设计

^^^^本小节将会依次读取三个不同的 ID, 大家可以根据自己的实际情况进行使用.
^^^^三个 ID 共用的结构体:

typedef struct ID_DATA
{
    uint32 CPUID; 
    u8 flash_id[8]; 
    u8 unique_id[18]; 
}ID_DATA; 

上述代码中ID_DATA结构体中包含了三个不同的 ID, cpu, flash 和 unique. 本文下列三个 ID 都采用结构体进行存储.

2. 1, CPUID

^^^^这个 ID 可以从寄存器字节读取, 相同内核的 ID ==应该== 都是一样的. ID 的读取程序是参考的联盛德问答社区中ZYQ 大佬的解答:
在这里插入图片描述
其程序如下:

uint32 GetCpuIdr (void) 
{
    uint32 id = 0; 

    asm volatile (
        "mfcr    %[id],     cr 13,  0 \n\t"
        : [id]"+&r" (id) 
        : 
        : 
        ) ; 
    return id; 
}

^^^^同时 ZYQ 也给出了这个 ID 的一定用途, 如下:
在这里插入图片描述
^^^^这是大佬对我说的话, 大佬说的确实是有道理, 也确实是我考虑不周. 大家可以参考.

2. 2, flashID

^^^^同样以下程序依然采用官方提供的代码, 我只是对代码进行了总结, 将宏定义全部放在了一起, ==如果是 W800 和 W801 的官方 SDK, 就是 tls 库的 demo 可直接粘贴复制下列代码, 直接调用函数即可. 如果是 HAL 库, 宏定义可以删除. ==

//add by zxx start
//flashID
#define CMD_START_Pos                         8U                                          /*!   CMD start position */
#define CMD_START_Msk                          (1UL    CMD_START_Pos)                          /*!   CMD start Mask */
#define RSA_BASE       0x40000000
/**
 * @brief          This function is used to read the flash_id id of the internal flash. 
 *
 * @param[out]      flash_id                 Specified the address to save the flash_id,  the length must be greater than or equals to 8 bytes. 
 *
 * @retval         TLS_FLS_STATUS_OK        if read sucsess
 * @retval         TLS_FLS_STATUS_EIO        if read fail
 *
 * @note           The flash_id's length must be greater than or equals to 8 bytes. 
 */
int readFlashUniqueId (u8 *id, u8 fls_len) 
{
    if  (! id || fls_len  = 8)  {
        printf ("id equal NULL or fls_led not equal 8\r\n") ; 
        return -1; 
    }
    M32 (HR_FLASH_CMD_ADDR)  = 0xBC04B; 
    M32 (HR_FLASH_CMD_START)  = CMD_START_Msk; 
    u32 *id32 = id; 
    for  (u8 i = 0;  i   2;  i++)  {
        id32[i] = M32 (RSA_BASE +  (i + 1)  * 4) ; 
    }
    return 0; 
}
//add by zxx end

2. 3, uniqueID

^^^^读取唯一的 ID 官方库文件有提供代码, 本小节主要涉及函数调用, 仅此而已. 函数在 wm_internal_fls. c 文件中:

/**
 * @brief          This function is used to read the unique id of the internal flash. 
 *
 * @param[out]      uuid                 Specified the address to save the uuid,  the length must be greater than or equals to 18 bytes. 
 *
 * @retval         TLS_FLS_STATUS_OK        if read sucsess
 * @retval         TLS_FLS_STATUS_EIO        if read fail
 *
 * @note           The uuid's length must be greater than or equals to 18 bytes. 
 */
int tls_fls_read_unique_id (unsigned  char *uuid) 
{
    unsigned int value = 0; 
    unsigned int addr_read = 0; 
    int i = 0; 
    int len; 
    unsigned char FLASH_BUF[20]; 
    unsigned char *addr = &FLASH_BUF[0]; 
    int dumy_bytes = 0; 
    int uni_bytes = 0; 
    unsigned char rid; 
    int word; 
    int byte; 
    if  (inside_fls == NULL) 
    {
        return TLS_FLS_STATUS_EPERM; 
    }

    tls_os_sem_acquire (inside_fls- fls_lock,  0) ; 
    memset (uuid,  0xFF,  18) ; 
    rid = readRID () ; 
    switch (rid) 
    {
        case SPIFLASH_MID_GD: 
        case SPIFLASH_MID_PUYA: 
        case SPIFLASH_MID_TSINGTENG: 
            dumy_bytes = 4; 
            uni_bytes = 16; 
            break; 
        case SPIFLASH_MID_WINBOND: 
        case SPIFLASH_MID_FUDANMICRO: 
        case SPIFLASH_MID_BOYA: 
        case SPIFLASH_MID_XMC: 
            dumy_bytes = 4; 
            uni_bytes = 8; 
            break; 
        case SPIFLASH_MID_ESMT: 
        case SPIFLASH_MID_XTX: 
        default: 
            tls_os_sem_release (inside_fls- fls_lock) ; 
            return -1; 
    }
    uuid[0] = rid; 
    uuid[1] =  (unsigned char)  (uni_bytes & 0xFF) ; 
    len = dumy_bytes + uni_bytes; 
    word = len/4; 
    byte = len%4; 
    
    value = 0xC04B| ( (len-1)     16) ; 
    M32 (HR_FLASH_CMD_ADDR)  = value; 
    M32 (HR_FLASH_CMD_START)  = CMD_START_Msk;         

    addr_read = RSA_BASE_ADDRESS; 
    for (i = 0; i   word;  i ++) 
    {
        M32 (addr)  = M32 (addr_read) ;     
        addr += 4; 
        addr_read += 4; 
    }

    if (byte   0) 
    {
        M32 (addr)  = M32 (addr_read) ;     
        addr += 3;                             //point last byte
        while (byte) 
        {
            *addr = 0; 
            addr --; 
            byte --; 
        }
    }
    addr = &FLASH_BUF[0]; 
    memcpy (&uuid[2],  addr + dumy_bytes,  uni_bytes) ; 
    tls_os_sem_release (inside_fls- fls_lock) ; 

    return 0; 
}

上述函数将很多的 ID 进行了组合.
==小疑惑: == 这个函数我觉得还不是很理想, 因为函数内部并未判断传入的参数是否合法, 如果我传个很小的数组? 传个非法地址? 这样数据读出来可能是错的. 当然这是题外话, 大家使用的时候一定要注意. 参数的合法性.

三, 测试

3. 1, 测试代码

^^^^编写测试程序测试是否正确读取 ID. 读取比较简单只提供代码, 自己封装函数即可.

    while (1) 
    {
        ID_DATA id_data; 
        readFlashUniqueId (id_data. flash_id, sizeof (id_data. flash_id) ) ; 
        printf ("flashid:   ") ; 
        for (int i=0; i 8; i++) 
            printf ("%d ", id_data. flash_id[i]) ; 
        printf ("\r\n") ; 
        tls_fls_read_unique_id (id_data. dev_id) ; 
        printf ("uniqueid:   ") ; 
        for (int i=0; i 18; i++) 
            printf ("%d ", id_data. dev_id[i]) ; 
        printf ("\r\n") ; 
        id_data. cpuid = GetCpuIdr () ; 
        printf ("cpuid:   %d\r\n", id_data. cpuid) ; 
        while (1) ; 
    }

3. 2, W800 测试结果

在这里插入图片描述

3. 3, W801 测试结果

第一块 W801:
在这里插入图片描述
第二块 W801:
在这里插入图片描述

3. 4, AIR101 测试结果

在这里插入图片描述

1 条评论

发布
问题