很多情况下,我们写扇区病不一定512对齐,甚至有的情况下跨扇区读写,为了满足这个需求,进行判断先擦除再写,并且不影响之前扇区的数据
擦除再写:
cpp
#define FLASH_TOTAL 0x50000 // 共320K
#define BLOCK_START_ADDR 0x2F800 // 前190K为COS预留空间
#define PAGE_SIZE 512 // ! 注意这里并不是页大小,而是可以擦除的最小单位
/**
* @description: 先擦除再写
* @detail:
* @return {*}
* @author: lkc
*/
ULONG DRV_FLASHWriteWithErase(UCHAR *pucSrc, ULONG ulDes, ULONG ulBytelen)
{
USHORT unalignment_bytes1 = 0, unalignment_bytes2 = 0, totle_len = 0;
UCHAR buf1[PAGE_SIZE], buf2[PAGE_SIZE], i;
if (ulBytelen <= 0 || ulDes < BLOCK_START_ADDR || (ulDes + ulBytelen) >= FLASH_TOTAL) {
return FALSE;
}
/*判断是否地址PAGESIZEbyte对齐*/
if ((ulDes % PAGE_SIZE) != 0) {
unalignment_bytes1 = ulDes % PAGE_SIZE; // X1的数据长度,即需要保护的数据
DRV_FlashRead(buf1, ulDes - unalignment_bytes1, unalignment_bytes1); // 读取X1的数据到buf1中
}
/*判断写入长度PAGESIZE字节对齐,*/
if (((ulDes + ulBytelen) % PAGE_SIZE) != 0) {
unalignment_bytes2 = PAGE_SIZE - (ulDes + ulBytelen) % PAGE_SIZE; // X2的数据长度
DRV_FlashRead(buf2, ulDes + ulBytelen, unalignment_bytes2); // 读取X2的数据到buf2中
}
/*数据拼接*/
totle_len = ulBytelen + unalignment_bytes1 + unalignment_bytes2;
/*擦除从地址des-unalignment_bytes1开始的n页,n = totle_len/PAGE_SIZE*/
DRV_FLASHEraseN(ulDes - unalignment_bytes1, totle_len / PAGE_SIZE);
/*当只有一页*/
if (totle_len / PAGE_SIZE == 1) {
memcpy(buf1 + unalignment_bytes1, pucSrc, ulBytelen);
memcpy(buf1 + unalignment_bytes1 + ulBytelen, buf2, unalignment_bytes2);
DRV_FlashWrite(buf1, ulDes - unalignment_bytes1, PAGE_SIZE);
} else {
for (i = 0; i < totle_len / PAGE_SIZE; i++) {
if (i == 0) {
memcpy(buf1 + unalignment_bytes1, pucSrc, PAGE_SIZE - unalignment_bytes1);
} else if (i == (totle_len / PAGE_SIZE - 1)) {
memcpy(buf1, pucSrc + ulBytelen - (PAGE_SIZE - unalignment_bytes2), PAGE_SIZE - unalignment_bytes2);
memcpy(buf1 + PAGE_SIZE - unalignment_bytes2, buf2, unalignment_bytes2);
} else {
memcpy(buf1, pucSrc + PAGE_SIZE - unalignment_bytes1 + (i - 1) * PAGE_SIZE, PAGE_SIZE);
}
DRV_FlashWrite(buf1, ulDes - unalignment_bytes1 + i * PAGE_SIZE, PAGE_SIZE);
}
}
return SUCCESS;
}
擦除多扇区:
cpp
VOID DRV_FLASHEraseN(ULONG ulAddr, ULONG ulPageN)
{
unsigned int i = 0;
for (i = 0; i < ulPageN; i++) {
DRV_FlashErasePage(ulAddr + i * PAGE_SIZE);
}
}
读写擦除接口:
cpp
/**
* @description: 读取flash
* @detail:
* @param {UCHAR} *pucBuf 读取buf
* @param {ULONG} ulSrcAddr 地址
* @param {ULONG} ulBytelen 字节长度
* @return {*}
* @author: lkc
*/
VOID DRV_FlashRead(UCHAR *pucBuf, ULONG ulSrcAddr, ULONG ulBytelen)
{
if ((NULL == pucBuf) || (0 == ulBytelen)) {
return;
}
if ((ulSrcAddr + ulBytelen) > FLASH_TOTAL) {
return;
}
// 实现
return;
}
/**
* @description: flash写
* @detail:
* @param {UCHAR} *pucBuf 写buf
* @param {UINT32} ulDstAddr 目的地址
* @param {ULONG} ulBytelen 字节长度
* @return {*}
* @author: lkc
*/
VOID DRV_FlashWrite(UCHAR *pucBuf, ULONG ulDstAddr, ULONG ulBytelen)
{
if ((NULL == pucBuf) || (0 == ulBytelen)) {
return;
}
if ((ulDstAddr + ulBytelen) > FLASH_TOTAL) {
return;
}
// 实现
return;
}
/**
* @description: flash单页擦除
* @detail:
* @param {UCHAR} *pucBuf 写buf
* @param {UINT32} ulDstAddr 目的地址
* @param {ULONG} ulBytelen 字节长度
* @return {*}
* @author: lkc
*/
VOID DRV_FlashErasePage(ULONG ulAddress)
{
// 实现
return;
}