美文网首页物联网loT从业者物联网相关技术研究
CC2640R2F学习笔记(16)——SNV Flash使用

CC2640R2F学习笔记(16)——SNV Flash使用

作者: Leung_ManWah | 来源:发表于2019-04-11 10:48 被阅读2次

    一、背景

    SNV(Simple Non-Volatile,简单的非易挥发),是从内部 flash 末尾划分大约 1~4K大小的一块专用于存储数据的存储空间。一般用于存储协议栈必要的存储数据、用户的应用数据。类似于 STM32 的片内 EEPROM。

    NV(Non-Volatile,非易挥发) 是 16 位 ID,而 SNV 是简化版的 NV 只有 8 位 ID。

    1.1 SNV大小

    两页,共 4K(协议栈已使用一部分)。

    1.2 可用SNV的ID号

    在Bcomdef.h中

    // Device NV Items - Range 0 - 0x1F
    #define BLE_NVID_IRK 0x02              //!< The Device's IRK
    #define BLE_NVID_CSRK 0x03             //!< The Device's CSRK
    #define BLE_NVID_SIGNCOUNTER 0x04      //!< The Device's Sign Counter
    #define BLE_LRU_BOND_LIST 0x05         //!< The Device's order of bond indexes in least recently used order
    
    // Bonding NV Items - Range 0x20 - 0x5F - This allows for 10 bondings
    #define BLE_NVID_GAP_BOND_START 0x20   //!< Start of the GAP Bond Manager's NV IDs
    #define BLE_NVID_GAP_BOND_END 0x5f     //!< End of the GAP Bond Manager's NV IDs Range
    
    // GATT Configuration NV Items - Range 0x70 - 0x79 - This must match the number of Bonding entries
    #define BLE_NVID_GATT_CFG_START 0x70   //!< Start of the GATT Configuration NV IDs
    #define BLE_NVID_GATT_CFG_END 0x79     //!< End of the GATT Configuration NV IDs
    
    // Customer NV Items - Range 0x80 - 0x8F - This must match the number of Bonding entries
    #define BLE_NVID_CUST_START 0x80       //!< Start of the Customer's NV IDs
    #define BLE_NVID_CUST_END 0x8F         //!< End of the Customer's NV IDs
    

    可见 0x80~0x8F 是用户可以用(包含 0x80、0x8F),每个 ID 号最多一次可写入 252 字节。

    注:实际可以写几个 ID 取决于所剩余 SNV 空间,并不是说可以把所有 ID 号都写满 252字节。

    1.3 工程中可选的SNV大小

    可在编译器的预编译处写入三种宏,不同的宏表示不同 SNV 大小:
    ① OSAL_SNV = 0
    0 个可写 SNV 页。工程中不使用 SNV,由于绑定信息时需要 SNV,该操作将导致无法使用绑定功能。
    ② OSAL_SNV = 1
    1 个可写 SNV 页,共 2K。
    ③ OSAL_SNV = 2(默认)
    2 个可写 SNV 页,共 4K。

    注:如果没有在编译器中定义 OSAL_SNV,在协议栈代码中会自动被复制为 2,也就是默认用 4K的 SNV。

    二、注意事项

    1) 仿真时编译器会擦除 flash 全片数据,SNV 数据也会被擦除。
    2) 写 1K 字节到 SNV,怎么写?
    可以每个 ID 写 252 字节,一共需要 4 个 ID(1000/252=3.96)。
    3) 为什么有些工程使用不了 SNV(比如组网的例程)?
    因为组网例程所需 flash 较大,因此该工程的 SNV 部分被充分利用在了组网部分。
    可以看工程的预编译中包含了“OSAL_SNV=0”。
    4) 写 SNV 会耗时百毫秒级,尽可能在写的时候关闭中断。
    5) 尽可能地少写 SNV,因为它耗时耗电。
    6) 如果 SNV 的存储结构改变,或者协议栈版本升级了,有必要重新擦除和初始化 SNV 内存数据,否则读写时会出错。
    7) 尽量不要把 SNV 的代码放到中断函数里,建议单独弄个事件处理 SNV。
    8) 一次最多只能对一个 ID 写 252 个字节,写多时虽然返回值仍然是“SUCCESS”,但实测读出来的数据是错的。

    三、移植文件

    链接:https://pan.baidu.com/s/1fzlCQEthZHpK5qd3rr3JDA 提取码:3nbv
    snv_flash.csnv_flash.h 两个文件拖拽至CCS工程的Application文件夹下


    添加文件过程中,选项选择如下

    3.1 snv_flash.c

    /*********************************************************************
     * INCLUDES
     */
    #include "osal_snv.h"
    #include "snv_flash.h"
    
    /*********************************************************************
     * PUBLIC FUNCTIONS
     */
    
    /**
     @brief SNV读写内存操作
     @param snvId NV页数
     @param readWriteFlag 读写操作标志
     @param pData 指向需要操作的数据
     @param dataLen 数据长度
     @return SUCCESS - 成功;FAILURE - 失败
    */
    uint8 Snv_FlashContrl(uint8 snvId, uint8 readWriteFlag, uint8 *pData, uint8 dataLen)
    {
        if(readWriteFlag == SNV_READ)                       // 读取数据
        {
            return osal_snv_read(snvId, dataLen, pData);
        }
        else                                                // 写入数据
        {
            return osal_snv_write(snvId, dataLen, pData);
        }
    }
    
    /*************************************END OF FILE*************************************/
    

    3.2 snv_flash.h

    #ifndef _SNV_FLASH_H_
    #define _SNV_FLASH_H_
    
    /*********************************************************************
     * DEFINITIONS
     */
    #define SNV_READ            0x00
    #define SNV_WRITE           0x01
    
    #define CUSTOM_SNV_ID       0x80    // 使用的ID,用户可用0x80~0x8F
    #define CUSTOM_SNV_NUM      252     // 此ID使用到的字节数
    
    /*********************************************************************
     * API FUNCTIONS
     */
    uint8 Snv_FlashContrl(uint8 snvId, uint8 readWriteFlag, uint8 *pData, uint8 dataLen);
    
    #endif /* _SNV_FLASH_H_ */
    

    四、API调用

    需包含头文件 snv_flash.h

    Snv_FlashContrl

    功能 SNV读写内存操作
    函数定义 uint8 Snv_FlashContrl(uint8 snvId, uint8 readWriteFlag, uint8 *pData, uint8 dataLen)
    参数1 snvId NV页数
    参数2 readWriteFlag 读写操作标志
    参数3 pData 指向需要操作的数据
    参数4 dataLen 数据长度
    返回 SUCCESS - 成功;FAILURE - 失败

    五、使用例子

    1)添加头文件(例 multi_role.c 中)

    #include "snv_flash.h"
    

    2)定义一个数据缓存区(例 multi_role.c 中)

    // 数据缓冲区
    static uint8 s_testData[256] = {0};
    

    3)添加读取数据代码(multi_role.c 的 multi_role_init 函数末尾中)

    // 读取保存在SNV中的数据
    Snv_FlashContrl(CUSTOM_SNV_ID, SNV_READ, (uint8 *)s_testData, CUSTOM_SNV_NUM);
    

    4)添加写入数据代码(在某个事件回调函数中)

    // SNV写入内存
    Snv_FlashContrl(CUSTOM_SNV_ID, SNV_WRITE, (uint8 *)s_testData, CUSTOM_SNV_NUM);                            
    

    • 由 Leung 写于 2019 年 4 月 11 日

    • 参考:【BLE-CC2640】CC2640之SNV

    相关文章

      网友评论

        本文标题:CC2640R2F学习笔记(16)——SNV Flash使用

        本文链接:https://www.haomeiwen.com/subject/iisziqtx.html