嵌入式中数据在FLASH存储机制

这篇博客详细介绍了嵌入式系统中Flash存储的管理,包括历史记录的存储结构、索引管理、数据写入与读取、以及存储区的整理和擦除流程。通过一系列函数实现未发送历史记录的添加、状态更新以及数据完整性检查,确保系统稳定运行。
摘要由CSDN通过智能技术生成

源码下载地址:

下载路径


//Flash中可存储的历史记录数量
#define  RECORD_SIZE       500
//进行历史记录索引区整理时,flash中存储已发送历史记录数量需满足条件
#define  SET_INDEX_BUF_COND   100
Flash中每个扇区大小
#define  FLASH_SECTOR_SIZE  4096

#define  NOUP_RECORD_INDEX_SECTOR1       0x2B000       //未发送历史记录索引存储扇区1地址,空间大小4k
#define  NOUP_RECORD_INDEX_SECTOR2       0x2C000        //未发送历史记录索引存储扇区2地址,空间大小4k
#define  HIS_RECORD_DATA_BASE_ADDR       0x2D000        //未发送历史记录索引存储扇区2地址,空间大小4k,需要保留5个4096作为数据

//未发送历史记录索引结构
typedef struct
{
    u8  bIdentify;     //标识符
    u8  rsv;          //发送表示符
    u16  wIndex;
} NO_UP_RECORD_INDEX_T;


//未发送历史记录索引存储扇区起始地址,默认选择扇区1
extern u32  np_record_index_sec_base;

//查看历史记录,已发送数据总数
extern u16  F_Get_Send_Record_Num(u32 cur_sector_addr);
//查看历史记录,未发送数据总数
extern u16  F_Get_Noup_Record_Num(u32  cur_sector_addr);
//查看历史记录,已发送+未发送 数据总数
extern u16 F_Get_Total_Record_Num(u32 cur_sector_addr);


//查看历史数据索引-靠近当前时间的一条索引,获取流水号
extern  u16 F_Get_Record_Index(u32 cur_sector_addr);//
//查看历史数据索引-远离当前时间的一条索引
extern u16  F_Get_Noup_Record_Index(u32 cur_sector_addr);



//增加一个未发送历史记录索引
extern u8   F_Add_Noup_Record_Index(u16  index, u32  cur_sector_addr);
//将一个未发送历史记录索引置为已发送
extern u8   F_Set_Record_Index_Send(u16  index, u32  cur_sector_addr);


//开机进行存储区整理
extern void  F_Set_Buf_PowerOn(void);
//查看当前是否需要整理历史记录索引存储区
extern u8 F_Check_Set_Record_Index_Buf(void);
//整理未发送历史记录索引存储区
extern u8   F_Set_Noup_Record_Buf(void);
//检查是否需要整理数据记录存储区
extern u8  F_Check_Set_Record_Buf(void);


//擦除历史数据记录区
extern void  F_Erase_Record_Buf(void);



//向flash中写入一个新的数据记录
extern  u8  F_Write_New_Record(u8* record, u16 index);
//从flash中读取一个数据记录
extern  u8  F_Read_Record(uint8_t* record, u16  index);

测试流程
①开机调用初始化函数

F_Set_Buf_PowerOn();

②写数据

                osal_memset(write_record_flash_buf,0x55,sizeof(write_record_flash_buf));
                write_record_flash_buf[0]=write_record_flash_index1;
                write_record_flash_buf[1]=write_record_flash_index2;
                uart_test_write_flash(write_record_flash_buf);
                write_record_flash_index1++;
                if (write_record_flash_index1>250)
                {
                    write_record_flash_index2++;
                    write_record_flash_index1=0;
                }
uint8_t write_record_flash_buf[32];
uint8_t write_record_flash_index1=0;
uint8_t write_record_flash_index2=0;
void uart_test_write_flash(uint8_t *p_data)
{
    u16 cur_index = 0;
    u16 total_index = 0;
    u16 crc_val = 0;
    u8 write_times = 5;
    u16 record_index = 0;
    u8 resutl =0;

    total_index = F_Get_Noup_Record_Num(np_record_index_sec_base);
    if(total_index >= 200)
    {
        record_index = F_Get_Noup_Record_Index(np_record_index_sec_base);
        if(record_index > 639)
        {
            user_printf_level1("-->error:%d cur index>639\r\n",__LINE__);
            return;
        }
        resutl = F_Set_Record_Index_Send(record_index, np_record_index_sec_base);
		user_printf_level2("->^_^ del index:%d\r\n",record_index);
        if (resutl)user_printf_level2("->error del index:%d\r\n",record_index);
    }


    //获取当前流水号
    cur_index = F_Get_Record_Index(np_record_index_sec_base);
    user_printf_level2("->cur index =%d\r\n", cur_index);
    if (cur_index == 0x55AA)
    {   //没有任何数据
        user_printf_level1("->index buf is empty!\r\n");
        cur_index = 0;
    } else if (cur_index > 639)
    {   //
        user_printf_level1("-->error:%d cur index>639\r\n",__LINE__);
        return;
    } else
    {
        cur_index++;
    }

    //查看当前索引值是否为数据记录空间最大流水号,如是则置零
    if (cur_index == 640)
    {  
        cur_index = 0;
    }

    //查看是否需要整理历史记录存储区
    F_Check_Set_Record_Buf();


    //查看是否需要整理历史记录索引存储区
    if (!F_Check_Set_Record_Index_Buf())
    {   //2块4k FLASH管理下表
        //进行历史记录索引存储区整理
        if (F_Set_Noup_Record_Buf())
        {
            user_printf_level1("->eorror set no up record buf fail!\r\n");
        }
    }
	
	total_index = F_Get_Total_Record_Num(np_record_index_sec_base);
    if(total_index >= RECORD_SIZE)
    {
		user_printf_level2("->^_^ total index%d\r\n",total_index);
		return ;
	}
///
    p_data[2] = cur_index>>8;
    p_data[3] = cur_index;
    crc_val = fals_calcCrc16(p_data, 30);
    p_data[30]=crc_val>>8;
    p_data[31]=crc_val;



    //向flash中写入记录
    while (write_times)
    {   //最多写write_times次

        //向索引区增加一个索引值,且写入记录成功
        if (!F_Add_Noup_Record_Index(cur_index, np_record_index_sec_base))
        {   //写索引成功
            if (!F_Write_New_Record(p_data, cur_index))//写入记录成功
            {
                break;
            } else
            {
                user_printf_level1("->error add a record fail!,%d\r\n",write_times);
            }

        }
        //将该写入记录置为已发送
        resutl = F_Set_Record_Index_Send(cur_index, np_record_index_sec_base);
        if (resutl)user_printf_level2("->del index:%d\r\n",record_index);

        cur_index++;
        if(cur_index == 640)
        {
            cur_index = 0;
        }
        write_times--;
    }

}

③读数据

uint8_t read_record_flash_buf[32];
uint16_t uart_test_read_flash(void)//read flash && ble send
{
    u16 data_remain = 0;
    u16 record_index = 0;
    u16 crc_val = 0;
    u16 crc_get = 0;

    u16 index_get=0;

    data_remain = F_Get_Noup_Record_Num(np_record_index_sec_base);
    if (data_remain == 0)
    {
        user_printf_level2("->^_^ uart_test_read_flash empty\r\n",__LINE__);
        return 0;
    }


    record_index = F_Get_Noup_Record_Index(np_record_index_sec_base);
    if(record_index > 639)
    {
        user_printf_level2("->error:%d record index>639\r\n",__LINE__);
        return 0;
    }

    F_Read_Record(read_record_flash_buf, record_index);
    crc_val = fals_calcCrc16(read_record_flash_buf, 30);

    crc_get = (read_record_flash_buf[30]<<8);
    crc_get |= read_record_flash_buf[31];

    index_get = (read_record_flash_buf[2]<<8);
    index_get |= read_record_flash_buf[3];

    if((index_get != record_index)||(crc_val != crc_get))
    {
        F_Set_Record_Index_Send(record_index, np_record_index_sec_base);
        if (index_get != record_index) user_printf_level2("->error get index\r\n");
        if (crc_val != crc_get) user_printf_level2("->error get crc\r\n");
        return 0;
    }



    user_printf_level2("->data %03d,%03d,%d\r\n",\
                       read_record_flash_buf[0],read_record_flash_buf[1],\
                       index_get);



    if (F_Set_Record_Index_Send(record_index, np_record_index_sec_base))
    {
        user_printf_level2("->error del one record\r\n");
    }

    return data_remain;
}

④擦除所有数据

                F_Erase_Record_Buf();
                F_Set_Buf_PowerOn();
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值