单片机 flash 擦写(先擦除 后写任意字节)

很多情况下,我们写扇区病不一定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;
}
相关推荐
polarislove02148 小时前
9.6 [定时器]超声波测距实验-嵌入式铁头山羊STM32笔记
笔记·stm32·嵌入式硬件
一路往蓝-Anbo9 小时前
C语言从句柄到对象 (六) —— 继承与 HAL:父类指针访问子类数据
c语言·开发语言·stm32·嵌入式硬件·物联网
一路往蓝-Anbo11 小时前
C语言从句柄到对象 (七) —— 给对象加把锁:RTOS 环境下的并发安全
java·c语言·开发语言·stm32·单片机·嵌入式硬件·算法
一路往蓝-Anbo12 小时前
C语言从句柄到对象 (八) —— 当对象会说话:观察者模式与事件链表
c语言·开发语言·数据结构·stm32·单片机·观察者模式·链表
polarislove021412 小时前
9.5 [定时器]输入捕获-嵌入式铁头山羊STM32笔记
笔记·stm32·嵌入式硬件
国科安芯12 小时前
核工业检测系统通信链路的国产化元器件安全等级评估
运维·网络·人工智能·单片机·嵌入式硬件·安全·安全性测试
IT阳晨。14 小时前
【STM32】采集温湿度数据上传至OneNET平台项目
stm32·单片机·嵌入式硬件
FL162386312914 小时前
flash_attn windows whl下载安装教程
windows·stm32·单片机
d111111111d14 小时前
配置STM32F411CEU6的系统时钟-避免芯片内核锁死
笔记·stm32·单片机·嵌入式硬件·学习
小李做物联网15 小时前
【单片机毕设】77.2基于单片机stm32智能大棚环境监控-语音
stm32·单片机·嵌入式硬件·物联网