



#include "Non_volatile_Memorys.h"

#pragma location="BACKUP_RAM_CONTENT"
uint8_t NVMEEPROMFault;
#pragma location="BACKUP_RAM_CONTENT"
NVMInitUnion          NVMInit;
#pragma location="BACKUP_RAM_CONTENT"
NVMODOUnion           NVMODO;
#pragma location="BACKUP_RAM_CONTENT"
NVMODOUnion           NVMODO_back;
#pragma location="BACKUP_RAM_CONTENT"
NVMUpdateCtrlStruct   NVMUpdateCtrl;


void NVM_Init ( void )
{
    uint8_t   i;
    uint8_t   j;

    uint8_t   *pData;
    uint8_t   *pDefaultValue;
    uint8_t   Len;

#if NVM_USE_EEPROM

    uint8_t   Type;
    uint16_t  Addr;

    uint8_t   InitStatus;
    EEPROMAccessStatusEnum    Status;

    //初始化更新控制
    NVMUpdateCtrl.Enable  = 0;
    NVMUpdateCtrl.Current = 0xFF;              //0xFF = 无效信号
    for ( i = 0; i < NVM_TOTAL_DATA_NUM; i++ )
    {
        NVMUpdateCtrl.Req [ i ] = 0;
    }

    //检查EEPROM有无初始化过
    pData  = NVMDataAttributeTable[NVM_INIT_DATA].pData;
    Len    = NVMDataAttributeTable[NVM_INIT_DATA].Len;
    Type   = NVMDataAttributeTable[NVM_INIT_DATA].DataType;
    Addr   = NVMDataAttributeTable[NVM_INIT_DATA].Addr;

    //读取初始化标志
    Status = EEPROM_Startup_Data_Read ( Type, Addr, pData, Len );

    //根据读取状态判断初始化状态
    if ( Status == EEPROM_DATA_OK )
    {
        NVM_EEPROM_FAULT = 0;
        InitStatus       = 1;
    }
    else if ( Status == EEPROM_DATA_PARTIAL_LOST )
    {
        NVM_EEPROM_FAULT = 0;
        InitStatus       = 1;
        NVM_Data_Update ( NVM_INIT_DATA );
    }
    else if ( Status == EEPROM_DATA_LOST )
    {
        NVM_EEPROM_FAULT = 0;
        InitStatus       = 0;
    }
    else
    {
        NVM_EEPROM_FAULT = 1;
        InitStatus       = 0;
    }

    //比对初始化标志
    if ( InitStatus )
    {
        i = 0;
        pDefaultValue = NVMDataAttributeTable[NVM_INIT_DATA].pDefaultValue;

        while ( i < Len )
        {
            if ( pData[i] != pDefaultValue[i] )
            {
                InitStatus = 0;
                break;
            }

            i++;
        }
    }

    if ( InitStatus )                               //存储器已初始化过,则从存储器中读取数据
    {

        if ( NVM_TOTAL_DATA_NUM > 1 )
        {
            for ( i = 1; i < NVM_TOTAL_DATA_NUM; i++ )
            {
                pData  = NVMDataAttributeTable[i].pData;
                Len    = NVMDataAttributeTable[i].Len;
                Type   = NVMDataAttributeTable[i].DataType;
                Addr   = NVMDataAttributeTable[i].Addr;

                //读取数据
                Status = EEPROM_Startup_Data_Read ( Type, Addr, pData, Len );

                if ( Status == EEPROM_DATA_PARTIAL_LOST ) //数据部分丢失,使用读出的数据,并重新更新存储器
                {
                    NVM_Data_Update ( i );
                }
                else if ( Status != EEPROM_DATA_OK )      //数据没有被成功读出,使用默认值,并更新存储器
                {
                    pDefaultValue = NVMDataAttributeTable[i].pDefaultValue;

                    for ( j = 0; j < Len; j++ )
                        pData[j] = pDefaultValue[j];

                    NVM_Data_Update ( i );
                }
            }
        }
    }
    else                                            //存储器未初始化过,则使用数据默认值,并请求更新到存储器
    {
        for ( i = 0; i < NVM_TOTAL_DATA_NUM; i++ )
        {
            pData         = NVMDataAttributeTable[i].pData;
            pDefaultValue = NVMDataAttributeTable[i].pDefaultValue;
            Len           = NVMDataAttributeTable[i].Len;

            for ( j = 0; j < Len; j++ )
                pData[j] = pDefaultValue[j];

            NVM_Data_Update ( i );
        }
    }

#else

    NVM_EEPROM_FAULT = 0;

    for ( i = 0; i < NVM_TOTAL_DATA_NUM; i++ )
    {
        pData         = NVMDataAttributeTable[i].pData;
        pDefaultValue = NVMDataAttributeTable[i].pDefaultValue;
        Len           = NVMDataAttributeTable[i].Len;

        for ( j = 0; j < Len; j++ )
            pData[j] = pDefaultValue[j];
    }

#endif
}

void NVM_Data_Update ( uint8_t DataName )
{
#if NVM_USE_EEPROM

    if ( NVM_EEPROM_FAULT == 0 )              //如果存储器未发生故障
    {
        if ( DataName < NVM_TOTAL_DATA_NUM )
        {
            NVMUpdateCtrl.Req[DataName] = 1;
            NVMUpdateCtrl.Enable = 1;
        }
    }

#endif
}


void NVM_Data_Update_Service ( void )
{
#if NVM_USE_EEPROM

    uint8_t   i;

    uint8_t   *pData;
    uint8_t   Len;
    uint8_t   Type;
    uint16_t  Addr;

    EEPROMAccessStatusEnum Status;

    if ( NVMUpdateCtrl.Enable )
    {
        if ( NVMUpdateCtrl.Current < NVM_TOTAL_DATA_NUM ) //曾经发起过数据存储
        {
            Status = EEPROM_Get_Data_Write_Status();

            if ( Status == EEPROM_DATA_OK )                 //数据成功写入,清除写入请求
                NVMUpdateCtrl.Req[NVMUpdateCtrl.Current] = 0;
            else if ( Status == EEPROM_MEMORY_BUSY )        //数据仍在写入中,直接返回
                return;
        }

        NVMUpdateCtrl.Current = 0xFF;

        //查找需要更新的数据,在更新完所有数据后才更新初始化数据
        i = NVM_TOTAL_DATA_NUM;

        while ( i )
        {
            i--;

            if ( NVMUpdateCtrl.Req[i] )
            {
                pData  = NVMDataAttributeTable[i].pData;
                Len    = NVMDataAttributeTable[i].Len;
                Type   = NVMDataAttributeTable[i].DataType;
                Addr   = NVMDataAttributeTable[i].Addr;

                Status = EEPROM_Data_Write ( Type, Addr, pData, Len );

                if ( Status == EEPROM_DATA_OK )
                    NVMUpdateCtrl.Current = i;

                return;
            }
        }

        NVMUpdateCtrl.Enable  = 0;
    }

#endif
}
