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 */
}