数据存储与导出

嵌入式设备一般都处理一些数据,大多都是通过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数据块的管理,在固件设计中非常重要,后面遇上再整理。

 

posted @ 2017-11-06 01:43  dong1  阅读(388)  评论(0编辑  收藏  举报