/*
 * flash_handle.c
 *
 *  Created on: 2021年11月14日
 *      Author: FENGAO
 */


#include "F021.h"
#include "flash_handle.h"

//TMS570LS3137的flash分区表
struct Sector_List gSector_List[SECTOR_NUM] =
{
 //     块编号                                             扇区编号                扇区起始地址              扇区大小
     {Fapi_FlashBank0,    0,      0x00000000, 32*1024},
     {Fapi_FlashBank0,    1,      0x00008000, 32*1024},
     {Fapi_FlashBank0,    2,      0x00010000, 32*1024},
     {Fapi_FlashBank0,    3,      0x00018000, 32*1024},
     {Fapi_FlashBank0,    4,      0x00020000, 128*1024},
     {Fapi_FlashBank0,    5,      0x00040000, 128*1024},
     {Fapi_FlashBank0,    6,      0x00060000, 128*1024},
     {Fapi_FlashBank0,    7,      0x00080000, 128*1024},
     {Fapi_FlashBank0,    8,      0x000A0000, 128*1024},
     {Fapi_FlashBank0,    9,      0x000C0000, 128*1024},
     {Fapi_FlashBank0,    10,     0x000E0000, 128*1024},
     {Fapi_FlashBank0,    11,     0x00100000, 128*1024},
     {Fapi_FlashBank0,    12,     0x00012000, 128*1024},
     {Fapi_FlashBank0,    13,     0x00014000, 128*1024},
     {Fapi_FlashBank0,    14,     0x00016000, 128*1024},
     {Fapi_FlashBank1,    0,      0x00018000, 128*1024},
     {Fapi_FlashBank1,    1,      0x0001A000, 128*1024},
     {Fapi_FlashBank1,    2,      0x0001C000, 128*1024},
     {Fapi_FlashBank1,    3,      0x0001E000, 128*1024},
     {Fapi_FlashBank1,    4,      0x00020000, 128*1024},
     {Fapi_FlashBank1,    5,      0x00022000, 128*1024},
     {Fapi_FlashBank1,    6,      0x00024000, 128*1024},
     {Fapi_FlashBank1,    7,      0x00026000, 128*1024},
     {Fapi_FlashBank1,    8,      0x00028000, 128*1024},
     {Fapi_FlashBank1,    9,      0x0002A000, 128*1024},
     {Fapi_FlashBank1,    10,     0x0002C000, 128*1024},
     {Fapi_FlashBank1,    11,     0x0002E000, 128*1024},
     {Fapi_FlashBank7,    0,      0xF0200000, 16*1024},
     {Fapi_FlashBank7,    1,      0xF0204000, 16*1024},
     {Fapi_FlashBank7,    2,      0xF0208000, 16*1024},
     {Fapi_FlashBank7,    3,      0xF020C000, 16*1024},
};


/*  @brief  查找扇区信息
*   @param[in] oNewFlashBank：块编号
*   @param[in] sector：扇区编号
*
*   return：扇区在数据结构中的位置
*/
uint32_t find_sector(Fapi_FlashBankType oNewFlashBank, uint32_t sector)
{
    int i=0;

    for(i=0; i<SECTOR_NUM; i++)
    {
        if( (gSector_List[i].banks_num == oNewFlashBank) && (gSector_List[i].sector_num == sector) )
        {
            return i;
        }
    }
}

/*  @brief  擦除扇区
*   @param[in] oNewFlashBank：块编号
*   @param[in] sector：扇区编号
*
*   return：
*/
enum e_flash_status Flash_EraseSector(Fapi_FlashBankType oNewFlashBank, uint32_t sector)
{
    int num = 0;
    Fapi_StatusType oReturnCheck = Fapi_Status_Success;

    num = find_sector(oNewFlashBank, sector);   //根据块ID和扇区ID查找扇区信息
    //printf("addr = %x\n", gSector_List[num].low_addr);

    oReturnCheck = Fapi_initializeFlashBanks(180); //初始化Flash Bank以进行API操作
    if((oReturnCheck == Fapi_Status_Success) && (FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY != Fapi_Status_FsmBusy))
    {
       oReturnCheck = Fapi_setActiveFlashBank(oNewFlashBank);  //设置活动的Flash Bank
       if( (oNewFlashBank == Fapi_FlashBank0) || (oNewFlashBank == Fapi_FlashBank1) )
           oReturnCheck = Fapi_enableMainBankSectors( 1<<(sector+1) );  //设置EEPROM存储区中可用的扇区以进行擦除和编程
       else if( oNewFlashBank == Fapi_FlashBank7 )
           oReturnCheck = Fapi_enableEepromBankSectors(1<<(sector+1) ,1<<((sector+1)%32));  //设置EEPROM存储区中可用的扇区以进行擦除和编程
       while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy);
       Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, gSector_List[num].low_addr);  //向Flash状态机发出命令
       /* Place specific example code here */
       /* Wait for FSM to finish */
       while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy);
       /* Check the FSM Status to see if there were no errors */
       if (FLASH_CONTROL_REGISTER->FmStat.u32Register != 0)
       {
           /* Put Error handling code here */
           return flash_failure;
       }
    }
    return flash_succeed;
}


/*  @brief  擦除块
*   @param[in] oNewFlashBank：块编号
*
*   return：
*/
enum e_flash_status Flash_EraseBanks(Fapi_FlashBankType oNewFlashBank)
{
    int num = 0;
    Fapi_StatusType oReturnCheck = Fapi_Status_Success;

    num = find_sector(oNewFlashBank, 0);

    oReturnCheck = Fapi_initializeFlashBanks(180); //初始化Flash Bank以进行API操作
    if((oReturnCheck == Fapi_Status_Success) && (FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY != Fapi_Status_FsmBusy))
    {
       oReturnCheck = Fapi_setActiveFlashBank(oNewFlashBank);  //设置活动的Flash Bank
       if( (oNewFlashBank == Fapi_FlashBank0) || (oNewFlashBank == Fapi_FlashBank1) )
           oReturnCheck = Fapi_enableMainBankSectors( 0xffffffff );  //设置EEPROM存储区中可用的扇区以进行擦除和编程
       else if( oNewFlashBank == Fapi_FlashBank7 )
           oReturnCheck = Fapi_enableEepromBankSectors(0xffffffff, 0xffffffff);  //设置EEPROM存储区中可用的扇区以进行擦除和编程
       while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy);
       Fapi_issueAsyncCommandWithAddress(Fapi_EraseBank, gSector_List[num].low_addr);  //向Flash状态机发出命令
       /* Place specific example code here */
       /* Wait for FSM to finish */
       while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy);
       /* Check the FSM Status to see if there were no errors */
       if (FLASH_CONTROL_REGISTER->FmStat.u32Register != 0)
       {
           /* Put Error handling code here */
           return flash_failure;
       }
    }
    return flash_succeed;
}

/*  @brief  写扇区数据
*   @param[in] oNewFlashBank：块编号
*   @param[in] sector：扇区编号
*   @param[in] offset：扇区偏移地址
*   @param[in] buff：数据
*   @param[in] len：数据长度
*
*   return：
*/
enum e_flash_status Flash_WriteData(Fapi_FlashBankType oNewFlashBank, uint32_t sector, uint32_t offset, uint8_t * buff, uint32_t len)
{
    int num = 0;
    Fapi_StatusType oReturnCheck = Fapi_Status_Success;

    num = find_sector(oNewFlashBank, sector);

    //如果写的大小起过扇区的大小
    if( (offset+len) > gSector_List[num].size )
    {
        return flash_failure;
    }

    oReturnCheck = Fapi_initializeFlashBanks(180); //初始化Flash Bank以进行API操作
    if((oReturnCheck == Fapi_Status_Success) && (FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY != Fapi_Status_FsmBusy))
    {
        oReturnCheck = Fapi_setActiveFlashBank(oNewFlashBank);  //设置活动的Flash Bank
        if( (oNewFlashBank == Fapi_FlashBank0) || (oNewFlashBank == Fapi_FlashBank1) )
            oReturnCheck = Fapi_enableMainBankSectors( 0xffffffff );  //设置EEPROM存储区中可用的扇区以进行擦除和编程
        else if( oNewFlashBank == Fapi_FlashBank7 )
            oReturnCheck = Fapi_enableEepromBankSectors(0xffffffff ,0xffffffff);  //设置EEPROM存储区中可用的扇区以进行擦除和编程
        while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy);
        Fapi_issueProgrammingCommand(gSector_List[num].low_addr+offset, buff, len, 0, 0, Fapi_DataOnly);  //设置数据并将程序命令发送到有效的闪存地址
        /* Place specific example code here */
        /* Wait for FSM to finish */
        while(FLASH_CONTROL_REGISTER->FmStat.FMSTAT_BITS.BUSY == Fapi_Status_FsmBusy);
        /* Check the FSM Status to see if there were no errors */
        if (FLASH_CONTROL_REGISTER->FmStat.u32Register != 0)
        {
            /* Put Error handling code here */
            return flash_failure;
        }
    }
    return flash_succeed;
}

/*  @brief  读扇区数据
*   @param[in] oNewFlashBank：块编号
*   @param[in] sector：扇区编号
*   @param[in] offset：扇区偏移地址
*   @param[in] buff：数据
*   @param[in] len：数据长度
*
*   return：
*/
void Flash_ReadData(Fapi_FlashBankType oNewFlashBank, uint32_t sector, uint32_t offset, uint8_t * buff, uint32_t len)
{
    int num = 0;

    num = find_sector(oNewFlashBank, sector);

        //如果读的大小超过扇区的大小
    if( (offset+len) > gSector_List[num].size )
    {
        return flash_failure;
    }

    memcpy(buff, gSector_List[num].low_addr+offset, len);
}




