// cpu内部Flash驱动
// 杭州秒寻科技有限公司
// 周涛
// 2023-09-26

#include "includes.h"

// 根据地址获得扇区编号
// dwAddress：flash地址
// pbySector:扇区编号（返回参数）
// 返回值：0：失败，1：成功
uint8 driver_cpuflash_get_sector(uint32 dwAddress, uint8 *pbySector)
{
    uint8 bySector = 0;
    if (dwAddress >= DRIVERCPUFLASH_SECTOR0_START_ADDRESS && dwAddress <= DRIVERCPUFLASH_SECTOR0_STOP_ADDRESS)
    {
        bySector = FLASH_Sector_0;
    }
    else if (dwAddress >= DRIVERCPUFLASH_SECTOR1_START_ADDRESS && dwAddress <= DRIVERCPUFLASH_SECTOR1_STOP_ADDRESS)
    {
        bySector = FLASH_Sector_1;
    }
    else if (dwAddress >= DRIVERCPUFLASH_SECTOR2_START_ADDRESS && dwAddress <= DRIVERCPUFLASH_SECTOR2_STOP_ADDRESS)
    {
        bySector = FLASH_Sector_2;
    }
    else if (dwAddress >= DRIVERCPUFLASH_SECTOR3_START_ADDRESS && dwAddress <= DRIVERCPUFLASH_SECTOR3_STOP_ADDRESS)
    {
        bySector = FLASH_Sector_3;
    }
    else if (dwAddress >= DRIVERCPUFLASH_SECTOR4_START_ADDRESS && dwAddress <= DRIVERCPUFLASH_SECTOR4_STOP_ADDRESS)
    {
        bySector = FLASH_Sector_4;
    }
    else if (dwAddress >= DRIVERCPUFLASH_SECTOR5_START_ADDRESS && dwAddress <= DRIVERCPUFLASH_SECTOR5_STOP_ADDRESS)
    {
        bySector = FLASH_Sector_5;
    }
    else if (dwAddress >= DRIVERCPUFLASH_SECTOR6_START_ADDRESS && dwAddress <= DRIVERCPUFLASH_SECTOR6_STOP_ADDRESS)
    {
        bySector = FLASH_Sector_6;
    }
    else if (dwAddress >= DRIVERCPUFLASH_SECTOR7_START_ADDRESS && dwAddress <= DRIVERCPUFLASH_SECTOR7_STOP_ADDRESS)
    {
        bySector = FLASH_Sector_7;
    }
    else if (dwAddress >= DRIVERCPUFLASH_SECTOR8_START_ADDRESS && dwAddress <= DRIVERCPUFLASH_SECTOR8_STOP_ADDRESS)
    {
        bySector = FLASH_Sector_8;
    }
    else if (dwAddress >= DRIVERCPUFLASH_SECTOR9_START_ADDRESS && dwAddress <= DRIVERCPUFLASH_SECTOR9_STOP_ADDRESS)
    {
        bySector = FLASH_Sector_9;
    }
    else if (dwAddress >= DRIVERCPUFLASH_SECTOR10_START_ADDRESS && dwAddress <= DRIVERCPUFLASH_SECTOR10_STOP_ADDRESS)
    {
        bySector = FLASH_Sector_10;
    }
    else if (dwAddress >= DRIVERCPUFLASH_SECTOR11_START_ADDRESS && dwAddress <= DRIVERCPUFLASH_SECTOR11_STOP_ADDRESS)
    {
        bySector = FLASH_Sector_11;
    }
    else
    {
        bySector = 255;
        return 0;
    }

    *pbySector = bySector;

    return 1;
}

// 擦除扇区
// bySector:扇区编号
uint8 driver_cpuflash_erase_sector(uint8 bySector)
{
    uint8 byFlag = 0;

    // 参数容错处理
    if (bySector < FLASH_Sector_0 || bySector > FLASH_Sector_11)
    {
        return 0;
    }

    // 擦除当前扇区
    FLASH_Unlock(); // 解锁
    FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR | FLASH_FLAG_RDERR | FLASH_FLAG_BSY);
    byFlag = FLASH_EraseSector((uint32)bySector, VoltageRange_3);
    if (byFlag != FLASH_COMPLETE)
    {
        FLASH_Lock(); // 上锁
        return 0;
    }
    FLASH_Lock(); // 上锁

    return 1;
}

// 从flash读出指定字节的数据(4byte)
// dwAddress:flash地址
// wLen:数据长度（4字节对齐）
// pdwData（返回参数）:数据（注意，需要一片连续的内存）
uint8 driver_cpuflash_read_word_data(uint32 dwAddress, uint16 wLen, uint32 *pdwData)
{
    uint32 dwAddressHead = dwAddress;
    uint32 *pdwDataHead = pdwData;

    // 容错处理
    if ((dwAddress + wLen * 4) > DRIVERCPUFLASH_SECTOR11_STOP_ADDRESS || pdwData == NULL)
    {
        return 0;
    }

    // 读数据
    for (uint16 i = 0; i < wLen; i++)
    {
        *pdwDataHead = *(uint32 *)dwAddressHead;
        pdwDataHead++;
        dwAddressHead += 4;
    }

    return 1;
}

// 将数据写入flash指定区(4byte)
// dwAddress:flash地址
// pdwData:数据
// dwLen:数据长度
uint8 driver_cpuflash_write_word_data(uint32 dwAddress, uint32 *pdwData, uint32 dwLen)
{
    uint8 byFlag = 0;
    uint32 *pdwHead = pdwData;
    uint32 dwHeadAddress = dwAddress;
    uint32 dwTmp = 0;

    // 写入数据
    FLASH_Unlock(); // 解锁
    FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR | FLASH_FLAG_RDERR | FLASH_FLAG_BSY);
    for (uint32 i = 0; i < dwLen; i++)
    {
        byFlag = FLASH_ProgramWord(dwHeadAddress, *pdwHead);
        if (byFlag != FLASH_COMPLETE)
        {
            FLASH_Lock(); // 上锁
            return 0;
        }
        pdwHead++;
        dwHeadAddress += 4;
    }
    FLASH_Lock(); // 上锁

    // 比较数据是否正确写入
    pdwHead = pdwData;
    dwHeadAddress = dwAddress;
    for (uint32 j = 0; j < dwLen; j++)
    {
        dwTmp = *(int32 *)dwHeadAddress;
        if (dwTmp != *pdwHead)
        {
            return 0;
        }
        pdwHead++;
        dwHeadAddress += 4;
    }

    return 1;
}