• 数据存储与导出


    嵌入式设备一般都处理一些数据,大多都是通过flash分块来管理。

    如下示例写入一些调试数据到flash

    dump.c

    #include <stdlib.h>
    #include <string.h>
    #include "drivers/spi_flash.h"
    
    #define  DEBUG_DATA_START         705
    #define  DEBUG_DATA_NB_BLOCKS     255
    #define  DEBUG_DATA_ITEM_COUNT    (255*255)
    
    typedef struct {
      uint32_t  id;    
      uint32_t  time; 
      uint16_t  battery_level;
      uint16_t  battery_vbat;
      uint16_t  boot_target;
      uint16_t  wakelock_lock;
    }debug_data_item_t;
    
    static uint32_t spi_flash_get_debug_item_id(void)
    {
        struct td_device *spi_flash_handler =(struct td_device *)&pf_sba_device_flash_spi0;
        unsigned int retlen;
        uint32_t item_cnt;
        uint32_t spi_addr = DEBUG_DATA_START * SERIAL_FLASH_BLOCK_SIZE;
        spi_flash_read(spi_flash_handler,spi_addr,1,&retlen,&item_cnt);
            if(item_cnt==0xffffffff) return 0;   
            else return item_cnt;
    }
    
    static void spi_flash_write_debug_item(uint32_t itemOffset,uint8_t itemCount,void *data)
    {
        struct td_device *spi_flash_handler =(struct td_device *)&pf_sba_device_flash_spi0;
        unsigned int retlen;    
        DRIVER_API_RC ret = spi_flash_sector_erase(spi_flash_handler, DEBUG_DATA_START, 1);
        uint32_t spi_addr = DEBUG_DATA_START * SERIAL_FLASH_BLOCK_SIZE;
        uint32_t item_offset_v = itemOffset+itemCount;     
        ret = spi_flash_write(spi_flash_handler, spi_addr, 1,&retlen, &item_offset_v);     
        spi_addr += SERIAL_FLASH_BLOCK_SIZE * 1 + itemOffset*sizeof(debug_data_item_t);
        ret = spi_flash_write(spi_flash_handler, spi_addr , sizeof(debug_data_item_t)*itemCount/4,&retlen,data);
    }
    
    static void spi_flash_read_debug_item(uint32_t itemOffset,uint8_t itemCount, debug_data_item_t *data_read)
    {
        struct td_device *spi_flash_handler =(struct td_device *)&pf_sba_device_flash_spi0;
        unsigned int retlen;    
        uint32_t* data_tmp;
        data_tmp = balloc((itemCount) * sizeof(debug_data_item_t), NULL);
        uint32_t spi_addr = DEBUG_DATA_START * SERIAL_FLASH_BLOCK_SIZE;
        spi_addr += SERIAL_FLASH_BLOCK_SIZE * 1 + (itemOffset*sizeof(debug_data_item_t));
        spi_flash_read(spi_flash_handler, spi_addr ,sizeof(debug_data_item_t)*itemCount/4,&retlen,data_tmp);
    
        uint8_t i=0;
        uint8_t j=0;
        while(i < 4*itemCount)
        {
            data_read[j].id     =data_tmp[i]; 
            data_read[j].time   =data_tmp[i+1];
            data_read[j].battery_level  =(uint16_t)data_tmp[i+2];
            data_read[j].battery_vbat   =(uint16_t)(data_tmp[i+2]>>16);
            data_read[j].boot_target    =(uint16_t)data_tmp[i+3];
            data_read[j].wakelock_lock  =(uint16_t)(data_tmp[i+3]>>16);
            i=i+4;
            j++;
        }
        bfree(data_tmp);
    }
    
    extern uint16_t battery_level;
    extern uint16_t battery_vbat;
    extern enum get_boot_target();
    extern uint16_t wakeup_lock();
    void debug_data_write()
    {
        debug_data_item_t data;
        uint32_t id_offset = spi_flash_get_debug_item_id();
        if(id_offset >= DEBUG_DATA_ITEM_COUNT) return;
        data.id=id_offset;
        data.time=utc_time_read();
        data.battery_level=battery_level;
        data.battery_vbat= battery_vbat;
        data.boot_target = (uint16_t)get_boot_target();
        data.wakelock_lock = wakeup_lock();
        spi_flash_write_debug_item(data.id,1,&data);
    }
    
    void debug_data_read(uint32_t itemOffset,uint8_t itemCount, debug_data_item_t *data_read)
    {
        if(itemOffset >= DEBUG_DATA_ITEM_COUNT) return;
        spi_flash_read_debug_item(itemOffset,itemCount, data_read);
    }
    
    void debug_data_erase(void)
    {
        struct td_device *spi_flash_handler =(struct td_device *)&pf_sba_device_flash_spi0;
        spi_flash_sector_erase(spi_flash_handler, DEBUG_DATA_START, DEBUG_DATA_NB_BLOCKS);
    }
    
    void debug_data_erase_item(uint32_t item_cnt)
    {
        struct td_device *spi_flash_handler =(struct td_device *)&pf_sba_device_flash_spi0;
        spi_flash_sector_erase(spi_flash_handler,DEBUG_DATA_START, (item_cnt*sizeof(debug_data_item_t) / SERIAL_FLASH_BLOCK_SIZE)+2);
    }
    
    int main(void)
    {
        time_60s_cnt++;
    
        if(time_60s_cnt % 12 == 0)    debug_data_write();
    
        return 0;
    }

    通过app来导出flash中的数据

    dump_app.c

    void shoes_debug_upload(uint8_t* buf, uint16_t len)
    {    
        uint16_t block_cnt = 0, remain_cnt = 0, i = 0;
        block_cnt = len / BLE_UART_MAX_CHAR_LEN;
        remain_cnt = len % BLE_UART_MAX_CHAR_LEN;
    
        for (i = 0; i < block_cnt; i++)
        {
            bt_gatt_notify(NULL,shoes_debug_value, buf + i * BLE_UART_MAX_CHAR_LEN,BLE_UART_MAX_CHAR_LEN,NULL);
            //local_task_sleep_ms(10);
        }
    
        if (remain_cnt > 0)
        {
            bt_gatt_notify(NULL,shoes_debug_value, buf + block_cnt*BLE_UART_MAX_CHAR_LEN, remain_cnt,NULL);  
        }    
    }
    
    ssize_t on_debug_data_write(struct bt_conn *conn, const struct bt_gatt_attr *attr,
                 const void *buf, uint16_t len, uint16_t offset)
    {
        if (len!=2) return 0;
    
        if(!data_is_synchronizing){
            debug_data_write();
            data_is_synchronizing = true;
        }
                
        uint8_t para[2];
        memcpy(para,buf,2);
        uint16_t  block_index =( (uint16_t)(para[1])        |
                                  (uint16_t)(para[0]) << 8);  
            
        uint8_t item_valid;
        uint16_t block_total;
        uint32_t item_id = spi_flash_get_debug_item_id();
        if( item_id%ITEM_NUM_ONE_BLOCK == 0)                 
            block_total=(uint16_t)((item_id)/ITEM_NUM_ONE_BLOCK);
        else block_total=(uint16_t)((item_id)/ITEM_NUM_ONE_BLOCK+1);
    
        pr_info(LOG_MODULE_MAIN, "item_id:%d block_index:%d  block_total:%d", item_id,block_index, block_total);
    
        if(block_index >= block_total)  {
            shoes_debug_upload((uint8_t*)buf,len);
            data_is_synchronizing = false;        
            return 0;
        }
             
        if((item_id % ITEM_NUM_ONE_BLOCK) && (block_index == block_total-1))                  
            item_valid = (item_id) % ITEM_NUM_ONE_BLOCK;
        else
            item_valid = ITEM_NUM_ONE_BLOCK;        
    
        pr_info(LOG_MODULE_MAIN, "item_valid:%d", item_valid);
    
        debug_data_item_t debug_sport_data[ITEM_NUM_ONE_BLOCK];
        
        debug_data_read(block_index*ITEM_NUM_ONE_BLOCK,item_valid,debug_sport_data);
        for(int j=0;j<item_valid;j++)
            pr_info(LOG_MODULE_MAIN, "time:0x%x,battery_l:0x%x,battery_v:0x%x,boot_target:0x%x,wakelock:0x%x",debug_sport_data[j].time,debug_sport_data[j].battery_level,debug_sport_data[j].battery_vbat,debug_sport_data[j].boot_target,debug_sport_data[j].wakelock_lock);
                                 
        uint8_t send_app_data_info[5+ITEM_NUM_ONE_BLOCK*13] = {
            (uint8_t)(block_index >> 8),
            (uint8_t)block_index,           
        
            (uint8_t)(block_total >> 8),
            (uint8_t)block_total,    
    
            item_valid*13,                   //len        
        };
                                                         
        uint16_t i = 0;
        for(i=0;i<item_valid;i++)
        {
            send_app_data_info[5+i*13]=(uint8_t)(debug_sport_data[i].time);
            send_app_data_info[6+i*13]=(uint8_t)(debug_sport_data[i].time >> 24);
            send_app_data_info[7+i*13]=(uint8_t)(debug_sport_data[i].time >> 16);
            send_app_data_info[8+i*13]=(uint8_t)(debug_sport_data[i].time >> 8);
            send_app_data_info[9+i*13]=(uint8_t)debug_sport_data[i].time;
    
            send_app_data_info[10+i*13]=(uint8_t)(debug_sport_data[i].battery_level >> 8);
            send_app_data_info[11+i*13]=(uint8_t)debug_sport_data[i].battery_level;
    
            send_app_data_info[12+i*13]=(uint8_t)(debug_sport_data[i].battery_vbat >> 8);
            send_app_data_info[13+i*13]=(uint8_t)debug_sport_data[i].battery_vbat;
    
            send_app_data_info[14+i*13]=(uint8_t)(debug_sport_data[i].boot_target >> 8);
            send_app_data_info[15+i*13]=(uint8_t)debug_sport_data[i].boot_target;
    
            send_app_data_info[16+i*13]=(uint8_t)(debug_sport_data[i].wakelock_lock >> 8);
            send_app_data_info[17+i*13]=(uint8_t)debug_sport_data[i].wakelock_lock;
        }
    
        if(block_index == block_total-1){
            debug_data_erase_item(item_id);
            data_is_synchronizing = false;
        }
    
        shoes_debug_upload(send_app_data_info,send_app_data_info[4]+5);
        
        return len;
    }

    以上数据存储与导出都是按字(4字节)来处理的,如果按字节呢,要转换一下数据长度

    uint8_t spi_flash_data_read(uint8_t * buf, int len,uint32_t add){
      uint32_t retlen = 0, real_len, *data_buf;
      DRIVER_API_RC ret;
      struct td_device *spi_flash_handler = (struct td_device *)&pf_sba_device_flash_spi0;
      
      if(buf == NULL || len <= 0){
        return -1;
      }
    
      real_len = (len + 3) / 4;
      data_buf = (uint32_t *)malloc(real_len * sizeof(uint32_t));
      if(NULL == data_buf) {
        return -1;
      }
    
      ret = spi_flash_read(spi_flash_handler, add, real_len, &retlen, data_buf);
    
      if(DRV_RC_OK != ret || real_len != retlen) {
        free(data_buf);
        return -1;
      }
    
      memcpy(buf, (uint8_t *)data_buf, len);
      free(data_buf);
    
      return 0;
    }
    
    uint8_t spi_flash_data_write(uint8_t* buf, int len,uint32_t add){
    
      uint32_t retlen = 0, real_len, *data_buf;
      DRIVER_API_RC ret;
      struct td_device *spi_flash_handler = (struct td_device *)&pf_sba_device_flash_spi0;
      
      if(buf == NULL || len <= 0){
        return -1;
      }
    
      real_len = (len + 3) / 4;
      data_buf = (uint32_t *)malloc(real_len * sizeof(uint32_t));
      if(NULL == data_buf) {
        return -1;
      } else {
        memcpy((uint8_t *)data_buf, buf, len);
      }
    
      ret = spi_flash_block_erase(spi_flash_handler, UER_ID_OFFSET, 1);
      ret = spi_flash_write(spi_flash_handler, add, real_len, &retlen, data_buf);
    
      if(DRV_RC_OK != ret || real_len != retlen) {
        free(data_buf);
        return -1;
      }
    
      free(data_buf);
      return 0;
    }

    以上都是些调试代码,没有成体系比较零散,对于flash数据块的管理,在固件设计中非常重要,后面遇上再整理。

  • 相关阅读:
    重构原则
    【重构:改善既有代码的设计】读书笔记——开篇
    C#值参数和引用参数
    使用Aspose.Cells利用模板导出Excel(C#)
    在MVC中使用rdlc格式的报表
    程序员如何高效学习
    IT 圈里有哪些经常被读错的词?
    VS2017生成解决方案报错,提示对路径的访问被拒绝
    JavaScript中的数值转换
    Xadmin的配置及使用
  • 原文地址:https://www.cnblogs.com/dong1/p/7790954.html
Copyright © 2020-2023  润新知