# 09.01_FLASH-MAIN区域读写和擦除

## 测试步骤

通过调用FLASH_Write()和FLASH_Erase()函数，实现了对Flash存储器的读写和擦除操作。 向flash存储器写入256字节的数据，然后擦除flash存储器，最后再写入数据。 数据为0~255，然后读取flash存储器，最后比较写入和读取的数据是否一致。

## 实测数据

芯片上电
REG(0x8000) = ffffffff ffffffff ffffffff ffffffff
写入flash
REG(0x8000) = 03020100 07060504 0b0a0908 0f0e0d0c
擦除flash
REG(0x8000) = ffffffff ffffffff ffffffff ffffffff
写入flash
REG(0x8000) = 03020100 07060504 0b0a0908 0f0e0d0c
擦除flash
REG(0x8000) = ffffffff ffffffff ffffffff ffffffff

## 参考代码

09.01_FLASH_ReadWrite.c

    /**
     * @brief FLASH-MAIN区域读写和擦除
     * @details
     * 通过调用FLASH_Write()和FLASH_Erase()函数，实现了对Flash存储器的读写和擦除操作。
     * 向flash存储器写入256字节的数据，然后擦除flash存储器，最后再写入数据。
     * 数据为0~255，然后读取flash存储器，最后比较写入和读取的数据是否一致。
     */
    #include "lks32mc09x_flash.h"
    #include "lks32mc09x_sys.h"

    uint32_t address = 0x8000;
    uint8_t testdata[256];
    uint8_t buffer[256];

    volatile uint32_t write_flg = 0;
    /**
     * @brief 主函数
     */
    int main(void)
    {
        SYS_SetPowerFailureDetection(SYS_PVDSEL_OFF);
        for (int i = 0; i < 256; i++)
        {
            testdata[i] = i;
        }

        // 主循环，防止程序退出
        while (1)
        {
            switch (write_flg)
            {
            case 0:
                break;
            case 1:
                write_flg = 0;
                FLASH_Write(address, testdata, 256); // 写入flash
                break;
            case 2:
                FLASH_Erase(address); // 擦除flash
                write_flg = 0;
                break;
            case 3:
                FLASH_Read(address, buffer, 256); // 读取flash
                write_flg = 0;
                break;
            default:
                break;
            }
        }
    }

## 使用到的库函数

库函数部分代码

    #define FLASH FLASH0
    #define REG_WRITE(reg,mask) reg = (mask)
    #define REG_WRITE_BIT(reg,mask,val) reg = ((reg) & ~(mask)) | (val)
    #define SYS0 ((SYS_TypeDef *)(SYS_BASE))

    /**
     * @brief 从指定地址读取数据
     *
     * @param adr 目标地址
     * @param buf 数据缓冲区指针
     * @param len 数据长度
     */
    void FLASH_Read(uint32_t adr, uint8_t *data, uint32_t len)
    {
        uint32_t i;
        for (i = 0; i < len; i++)
        {
            data[i] = REG8(adr + i);
        }
    }
    /**
     * @brief 向指定地址写入数据
     * @param adr 目标地址
     * @param data 数据缓冲区指针
     * @param len 数据长度
     * @note 触发掉电检测后，对flash的操作无效，掉电检测的配置参考SYS_SetPowerFailureDetection
     */
    void FLASH_Write(uint32_t adr, uint8_t *data, uint32_t len)
    {
        uint8_t *p   = data;
        uint32_t flg = __get_PRIMASK();
        __disable_irq();
        SYS_WR_PROTECT = 0x7a83;
        SYS_FLSP       = 0x8f35;
        FLASH->CFG |= BIT27 | BIT23;
        FLASH->ADDR = adr;
        len &= ~3; // 低两位值忽略
        for (; len > 0; len -= 4)
        {
            FLASH->WDATA = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
            p += 4;
        }
        SYS_FLSP = 0;
        FLASH->CFG &= ~(BIT27 | BIT23);
        SYS_WR_PROTECT = 0;
        __set_PRIMASK(flg);
    }
    /**
     * @brief 掉电检测配置
     * @param SYS_PVDSEL_x 掉电检测配置值
     */
    void SYS_SetPowerFailureDetection(uint32_t SYS_PVDSEL_x)
    {
        REG_WRITE(SYS0->PROTECT, 0x7a83);
        REG_WRITE_BIT(SYS0->AFE_REG0, (BIT11 | BIT12 | BIT13 | BIT14), SYS_PVDSEL_x);
        REG_WRITE(SYS0->PROTECT, 0);
    }
    /**
     * @brief 擦除指定扇区
     *
     * @param adr 目标地址
     * @note 触发掉电检测后，对flash的操作无效，掉电检测的配置参考SYS_SetPowerFailureDetection
     */
    void FLASH_Erase(uint32_t adr)
    {
        uint32_t flg = __get_PRIMASK();
        __disable_irq();
        SYS_WR_PROTECT = 0x7a83;
        SYS_FLSE       = 0x8fca;
        FLASH->CFG |= BIT31;
        FLASH->CFG &= ~BIT15;
        FLASH->ADDR  = adr;
        FLASH->ERASE = 0x7654DCBA;
        SYS_FLSE     = 0;
        FLASH->CFG &= ~BIT31;
        __set_PRIMASK(flg);
    }