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 條評論

發布
問題