component/inc/wl_flash.h

109 lines
4.1 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file wl_flash.h
* @author xushenghao
* @date 2024-07-22 13:57:02
* @brief
* @copyright Copyright (c) 2024 by xxx, All Rights Reserved.
*/
/**
* @brief 磨损平衡算法
*
* 1. 初始化block_page大小和当前写入地址
* 2. 写入数据前,检查剩余空间是否足够
* a. 如果足够,直接写入数据
* b. 如果不足够,执行以下步骤:
* i. 检查是否有已擦除但未使用的block_page如果有移动到该block_page继续写入
* ii. 如果没有已擦除的block_page检查当前block_page是否已满
* - 如果已满移动到下一个block_page
* - 在移动前检查该block_page是否有有效数据需要迁移如果有则先迁移数据
* 3. 在决定擦除新的block_page前采用Wear Leveling算法选择最佳的block_page进行擦除
* 4. 数据写入后,更新剩余空间大小和当前写入地址
*/
/**
* 使用方法
*
#define LL_FLASH_PAGE_SIZE (2 * 1024)
#define PVD_RESET_STORAGE_START_ADDRESS (256 * LL_FLASH_PAGE_SIZE)
static void test_wl_flash(void)
{
uint32_t address = 0;
wl_flash_t wf = {
.wl_flag = TRUE,
.addr = PVD_RESET_STORAGE_START_ADDRESS,
.len = 2 * LL_FLASH_PAGE_SIZE,
.page_size = LL_FLASH_PAGE_SIZE,
.data_size = sizeof(device_reset_t),
.write_gran = 8,
.ops.srand = board_srand,
.ops.read = flash_read,
.ops.write = flash_write,
.ops.erase_page = flash_erase_page,
};
wl_flash_init(&wf);
wl_flash_erase(&wf);
address = wl_flash_get_current_address(&wf);
device_reset_t power_on;
power_on.flag = PVD_RESET_FLAG;
// 一页2048/16 = 128个数据,2页 = 256个数据i=255时数据从头开始
for (uint16_t i = 0; i < 1000; i++)
{
wl_flash_write(&wf, (uint8_t *)&power_on, sizeof(device_reset_t));
wl_flash_set_next_address(&wf);
address = wl_flash_get_current_address(&wf);
if (address == wf.addr)
{
__NOP();
}
}
}
*/
#ifndef __WL_FLASH_H__
#define __WL_FLASH_H__
#include "lib.h"
typedef struct
{
BOOL wl_flag; // 开启平衡擦写标志
uint32_t addr; // Flash 起始地址
uint32_t len; // Flash 长度
uint16_t page_size; // Flash 页大小 2^N
uint16_t data_size; // 数据大小
/* write minimum granularity, unit: byte.
1(stm32f2/f4)/ 4(stm32f1)/ 8(stm32l4)
0 will not take effect. */
uint8_t write_gran;
struct
{
void (*srand)(void); // 随机数种子
BOOL(*read)
(uint32_t addr, uint8_t *buf, uint16_t size);
BOOL(*write)
(uint32_t addr, const uint8_t *buf, uint16_t size);
BOOL(*erase_page)
(uint32_t page);
} ops;
struct
{
uint32_t current_address; // 当前准备写入的地址
uint16_t residue_size; // 剩余可写大小
uint16_t start_page; // 起始页
uint16_t page_total; // 总页数
uint16_t block_page; // 擦除块大小
} private;
} wl_flash_t;
extern void wl_flash_init(wl_flash_t *cfg); ///< 初始化 Flash 磨损平衡算法
extern uint32_t wl_flash_get_current_address(wl_flash_t *cfg); ///< 获取当前写入地址
extern void wl_flash_set_next_address(wl_flash_t *cfg); ///< 设置下一个写入地址,下一个写入区域会被擦除
extern void wl_flash_set_current_address(wl_flash_t *cfg, uint32_t address); ///< 设置当前写入地址
extern void wl_flash_erase(wl_flash_t *cfg); ///< 擦除 Flash, 如果开启了平衡擦写标志, 则会随机分配写入地址
extern BOOL wl_flash_write(wl_flash_t *cfg, const uint8_t *buf, uint16_t size); ///< 写入 Flash
extern BOOL wl_flash_read(wl_flash_t *cfg, uint8_t *buf, uint16_t size); ///< 读取 Flash
#endif // __WL_FLASH_H__