167 lines
7.2 KiB
C
167 lines
7.2 KiB
C
|
|
#include "drv_flash.h"
|
||
|
|
|
||
|
|
/* flash数据帧格式 */
|
||
|
|
/* 帧头, 同时表示当前帧状态 */
|
||
|
|
/* 整帧大小, 5~65536 */
|
||
|
|
/* 帧类型, 用于区分不同存储数据, 0~255*/
|
||
|
|
/* 帧数据 */
|
||
|
|
/* 帧尾, 同时表示当前帧状态 */
|
||
|
|
|
||
|
|
/* 可读帧表,存放不同帧类型的第一个可读帧的地址与大小 */
|
||
|
|
type_readable_frame_t data_form[255] = {0};
|
||
|
|
/* 首个可写地址 */
|
||
|
|
uint32_t writeable_addr = 0;
|
||
|
|
uint8_t erase_flag = 0;
|
||
|
|
|
||
|
|
/* 地址对齐向高地址取整 */
|
||
|
|
#define ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1))
|
||
|
|
|
||
|
|
uint32_t i = 0;
|
||
|
|
|
||
|
|
int8_t flash_manage_init(flash_manage_t *flash_manage)
|
||
|
|
{
|
||
|
|
uint8_t buff[4] = {0}; /* 存放帧头,帧大小,帧类型 */
|
||
|
|
|
||
|
|
if (flash_manage->manage_sector_num == 0 || flash_manage->sector_size == 0 || flash_manage->read_flash == 0 ||
|
||
|
|
flash_manage->write_flash == 0 || flash_manage->erase_sector == 0) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 遍历管理的空间以更新地址 */
|
||
|
|
for (; i < flash_manage->manage_sector_num * flash_manage->sector_size; ) {
|
||
|
|
/* 取出帧信息 */
|
||
|
|
flash_manage->read_flash(buff, ALIGN_UP(flash_manage->flash_start_address + i, flash_manage->align_num), 4);
|
||
|
|
/* 只获取该类帧类型的首个可读帧地址 */
|
||
|
|
if (buff[0] == FLASH_READABLE_HEAD) {
|
||
|
|
if (data_form[buff[3]].state == 0) {
|
||
|
|
uint8_t frame_tail = 0;
|
||
|
|
flash_manage->read_flash(&frame_tail, ALIGN_UP(flash_manage->flash_start_address + i, flash_manage->align_num) + (buff[2] << 8 | buff[1]) - 1, 1);
|
||
|
|
if (frame_tail == FLASH_READABLE_TAIL) {
|
||
|
|
/* 只有帧头帧尾均为可读, 才把对齐后的地址填入 */
|
||
|
|
data_form[buff[3]].addr = ALIGN_UP(flash_manage->flash_start_address + i, flash_manage->align_num);
|
||
|
|
/* 帧大小按小端排列 */
|
||
|
|
data_form[buff[3]].size = buff[2] << 8 | buff[1];
|
||
|
|
data_form[buff[3]].state = 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
i = i + ALIGN_UP(buff[2] << 8 | buff[1], flash_manage->align_num);
|
||
|
|
} else if ((buff[0] & buff[1] & buff[2] & buff[3]) == FLASH_WRITABLE) {
|
||
|
|
/* 遍历提前结束 */
|
||
|
|
writeable_addr = ALIGN_UP(flash_manage->flash_start_address + i, flash_manage->align_num);
|
||
|
|
return 1;
|
||
|
|
} else {
|
||
|
|
i += flash_manage->align_num;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
erase_flag = 1;
|
||
|
|
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
void update_readable_frame(flash_manage_t *flash_manage, uint32_t addr, uint8_t frame_type)
|
||
|
|
{
|
||
|
|
uint8_t buff[4] = {0}; /* 存放帧头,帧大小,帧类型 */
|
||
|
|
|
||
|
|
/* 从当前位置遍历剩余空间 */
|
||
|
|
for (uint32_t i = 0; i < flash_manage->manage_sector_num * flash_manage->sector_size - (addr - flash_manage->flash_start_address);) {
|
||
|
|
/* 取出帧信息 */
|
||
|
|
flash_manage->read_flash(buff, ALIGN_UP(addr + i, flash_manage->align_num), 4);
|
||
|
|
/* 寻找相同类型的帧数据 */
|
||
|
|
if (buff[0] == FLASH_READABLE_HEAD) {
|
||
|
|
if (buff[3] == frame_type) {
|
||
|
|
uint8_t frame_tail = 0;
|
||
|
|
flash_manage->read_flash(&frame_tail, ALIGN_UP(addr + i, flash_manage->align_num) + (buff[2] << 8 | buff[1]) - 1, 1);
|
||
|
|
if (frame_tail == FLASH_READABLE_TAIL) {
|
||
|
|
/* 只有帧头帧尾均为可读, 才把地址填入 */
|
||
|
|
data_form[buff[3]].addr = ALIGN_UP(addr + i, flash_manage->align_num);
|
||
|
|
data_form[buff[3]].size = buff[2] << 8 | buff[1];
|
||
|
|
data_form[buff[3]].state = 1;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
i += ALIGN_UP(buff[2] << 8 | buff[1], flash_manage->align_num);
|
||
|
|
} else if ((buff[0] | buff[1] | buff[2] | buff[3]) == FLASH_WRITABLE) {
|
||
|
|
return;
|
||
|
|
} else {
|
||
|
|
i += flash_manage->align_num;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
int8_t flash_manage_read(flash_manage_t *flash_manage, uint8_t *pbuf, uint8_t frame_type)
|
||
|
|
{
|
||
|
|
if (flash_manage->manage_sector_num == 0 || flash_manage->sector_size == 0 || flash_manage->read_flash == 0 ||
|
||
|
|
flash_manage->write_flash == 0 || flash_manage->erase_sector == 0) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 可读表存在数据 */
|
||
|
|
if (data_form[frame_type].state != 0) {
|
||
|
|
flash_manage->read_flash(pbuf, data_form[frame_type].addr + 4, data_form[frame_type].size - 5);
|
||
|
|
if (flash_manage->flash_read_mode == FLASH_CLEAR_MODE) {
|
||
|
|
/* 将flash内部数据帧头尾置为无效数据 */
|
||
|
|
uint8_t frame_head[flash_manage->align_num];
|
||
|
|
memset(frame_head, FLASH_NULL, flash_manage->align_num);
|
||
|
|
flash_manage->write_flash(frame_head, data_form[frame_type].addr, flash_manage->align_num);
|
||
|
|
flash_manage->write_flash(frame_head, data_form[frame_type].addr + data_form[frame_type].size - 32, flash_manage->align_num);
|
||
|
|
/* 将对应类型的可读表置0 */
|
||
|
|
data_form[frame_type].state = 0;
|
||
|
|
if (flash_manage->flash_write_mode == FLASH_NO_OVERWRITING_MODE) {
|
||
|
|
/* flash处于覆写模式下, 可读帧是唯一的,故无需更新可读表, 而非覆写模式, 需要更新可读表 */
|
||
|
|
update_readable_frame(flash_manage, ALIGN_UP(data_form[frame_type].addr + data_form[frame_type].size, flash_manage->align_num), frame_type);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int8_t flash_manage_write(flash_manage_t *flash_manage, uint8_t *pbuf, uint16_t size, uint8_t frame_type)
|
||
|
|
{
|
||
|
|
uint8_t buff[size + 5];
|
||
|
|
uint16_t len = 0;
|
||
|
|
|
||
|
|
memset(buff, 0, size + 5);
|
||
|
|
len = size + 5;
|
||
|
|
|
||
|
|
if (flash_manage->manage_sector_num == 0 || flash_manage->sector_size == 0 || flash_manage->read_flash == 0 ||
|
||
|
|
flash_manage->write_flash == 0 || flash_manage->erase_sector == 0) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (writeable_addr > flash_manage->flash_start_address + flash_manage->manage_sector_num * flash_manage->sector_size - len || erase_flag == 1) {
|
||
|
|
erase_flag = 0;
|
||
|
|
flash_manage->erase_sector(flash_manage->flash_start_address);
|
||
|
|
writeable_addr = ALIGN_UP(flash_manage->flash_start_address, flash_manage->align_num);
|
||
|
|
/* 重置可读表 */
|
||
|
|
for (uint8_t i = 0; i < 255; i++) {
|
||
|
|
data_form[i].state = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
buff[0] = FLASH_READABLE_HEAD;
|
||
|
|
buff[1] = len & 0xff;
|
||
|
|
buff[2] = len >> 8 & 0xff;
|
||
|
|
buff[3] = frame_type;
|
||
|
|
buff[len - 1] = FLASH_READABLE_TAIL;
|
||
|
|
memcpy(buff + 4, pbuf, size);
|
||
|
|
flash_manage->write_flash(buff, writeable_addr, len);
|
||
|
|
|
||
|
|
if (data_form[frame_type].state == 0) {
|
||
|
|
/* 可读表为空时更新 */
|
||
|
|
data_form[frame_type].addr = writeable_addr;
|
||
|
|
data_form[frame_type].size = len;
|
||
|
|
data_form[frame_type].state = 1;
|
||
|
|
} else if (flash_manage->flash_write_mode == FLASH_OVERWRITING_MODE && data_form[frame_type].state == 1) {
|
||
|
|
/* 将flash内部上一个相同类型的数据帧头置为无效数据 */
|
||
|
|
uint8_t frame_head[flash_manage->align_num];
|
||
|
|
memset(frame_head, FLASH_NULL, flash_manage->align_num);
|
||
|
|
flash_manage->write_flash(frame_head, data_form[frame_type].addr, flash_manage->align_num);
|
||
|
|
data_form[frame_type].addr = writeable_addr;
|
||
|
|
data_form[frame_type].size = len;
|
||
|
|
}
|
||
|
|
writeable_addr = ALIGN_UP(writeable_addr + len, flash_manage->align_num);
|
||
|
|
|
||
|
|
return 1;
|
||
|
|
}
|