存储组件的实现思路分析及代码实现

1 存储组件实现思路

1.1 存储方式的选择

一般存储方案可以分为如下几种:
在这里插入图片描述
stm32l0有内部的eeprom,所以我们更倾向于使用内部的eeprom,并且eeprom也是统一编址,只是使用时需要先解锁。

1.2 stm32的存储冷知识

对于stm32f1和stm32l0存储架构是不一样的,stm32f1在擦除flash时是不能响应中断的,而stm32l0擦除时是可以响应中断的。
在这里插入图片描述

1.3 eeprom存储数据结构设计

在这里插入图片描述

1.4 存储组件操作流程

写操作:
在这里插入图片描述
读操作:
在这里插入图片描述
删除操作:
在这里插入图片描述


2 代码实现

app_storage.h:

#ifndef __APP_STORAGE_H
#define __APP_STORAGE_H

#include <stdbool.h>


#define EEPROM_BANK1_BASE   (0x08080000UL)
#define EEPROM_BANK1_END    (0x08080BFFUL)
#define EEPROM_BANK1_SIZE   3072
#define EEPROM_BANK2_BASE   (0x08080C00UL)
#define EEPROM_BANK2_END    (0x080817FFUL)
#define EEPROM_BANK2_SIZE   3072

#define STORAGE_PACK_LEN 64
#define STORAGE_DATA_LEN (STORAGE_PACK_LEN-8)
#define STORAGE_PACK_COUNT (EEPROM_BANK2_SIZE/STORAGE_PACK_LEN)
#define STORAGE_USED_FLAG   0XA1A2A3A4


typedef struct 
{
    uint32_t flag;
    uint16_t name;
    uint16_t len;
    uint8_t  data[STORAGE_DATA_LEN];
}storage_t;

#define STORAGE ((storage_t*)EEPROM_BANK2_BASE)



bool storage_write(uint16_t name,uint16_t len,uint8_t* pdata);
bool storage_read(uint16_t name,uint16_t* p_len,uint8_t* pdata);
bool storage_delete(uint16_t name);

#endif

app_storage.c:

#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "main.h"
#include "app_storage.h"

static uint16_t storage_find_null()
{
    for(uint8_t i=0;i<STORAGE_PACK_COUNT;i++)
    {
        if(STORAGE[i].flag!=STORAGE_USED_FLAG)
        {
            return i;
        }
    }
    return 0XFFFF;
}
static uint16_t storage_find_name(uint16_t name)
{
    for(uint8_t i=0;i<STORAGE_PACK_COUNT;i++)
    {
        if((STORAGE[i].flag==STORAGE_USED_FLAG)&&(STORAGE[i].name==name))
        {
            return i;
        }
    }
    return 0XFFFF;    
}


bool storage_write(uint16_t name,uint16_t len,uint8_t* pdata)
{
    uint16_t pack_number;
    
    if(len>STORAGE_DATA_LEN)return false;
    
    pack_number=storage_find_name(name);
    if(pack_number>=STORAGE_PACK_COUNT)
    {
        pack_number=storage_find_null();
        if(pack_number>=STORAGE_PACK_COUNT)return false;
    } 

    HAL_FLASHEx_DATAEEPROM_Unlock();
    HAL_FLASHEx_DATAEEPROM_Erase((uint32_t)&STORAGE[pack_number].flag);
    HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_HALFWORD,(uint32_t)&STORAGE[pack_number].name,name);
    HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_HALFWORD,(uint32_t)&STORAGE[pack_number].len,len);
    for(uint8_t i=0;i<len;i++)
    {
        HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE,(uint32_t)STORAGE[pack_number].data+i,pdata[i]);
    }
    HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_WORD,(uint32_t)&STORAGE[pack_number].flag,STORAGE_USED_FLAG);
    HAL_FLASHEx_DATAEEPROM_Lock();
	
	return true;
}

bool storage_read(uint16_t name,uint16_t* p_len,uint8_t* pdata)
{
    uint16_t pack_number;
    pack_number=storage_find_name(name);
    if(pack_number>=STORAGE_PACK_COUNT)return false;
    if(*p_len<STORAGE[pack_number].len)return false;

    memcpy(pdata,STORAGE[pack_number].data,STORAGE[pack_number].len);
    *p_len=STORAGE[pack_number].len;

    return true;
}
bool storage_delete(uint16_t name)
{
    uint16_t pack_number;
    pack_number=storage_find_name(name);
    if(pack_number>=STORAGE_PACK_COUNT)return false;    

    HAL_FLASHEx_DATAEEPROM_Unlock();
    HAL_FLASHEx_DATAEEPROM_Erase((uint32_t)&STORAGE[pack_number].flag);
    HAL_FLASHEx_DATAEEPROM_Lock(); 
	
	return true;
}


测试代码如下:

/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  float temp,humi;
  uint8_t write_buf[]="1234567890";
  uint8_t read_buf[20];
  uint16_t read_len;
  #define TEST_NAME 0X0001

  debug_init();
  led_init();
  key_init();
  led_blink(2,5);
  sht30_init();
  for(;;)
  {
    storage_write(TEST_NAME,sizeof(write_buf),write_buf);
    memset(read_buf,0,20);
    read_len=20;
    if(storage_read(TEST_NAME,&read_len,read_buf))
    {
      DEBUG("------%s-----",read_buf);
    }
    // if(sht30_get_temp_humi(&temp,&humi))
    // {
    //   DEBUG("temp=%f,humi=%f",temp,humi);
    // }
    osDelay(1000);
  }
  /* USER CODE END StartDefaultTask */
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值