
#include "Non_volatile_Memorys.h"

uint8_t NVMEEPROMFault;

NVMInitUnion          NVMInit;
NVMODOUnion           NVMODO;
NVMUserSettingsUnion  NVMUserSettings;
//NVMConfigF110Union    NVMConfigF110;
//NVMConfigF101Union    NVMConfigF101;
NVMDTCUnion           NVMDTC;
NVMConfig3300Union    NVMConfig3300;
NVMUpdateCtrlStruct   NVMUpdateCtrl;
uint8_t NVMDiesel;
NVMConfigF184Union   NVMConfigF184;
NVMConfigF1A8Union   NVMConfigF1A8;
NVMConfigF190Union   NVMConfigF190;
NVMRESETODOUnion     NVMRESETODO;

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)                                 //存储器已初始化过,则从存储器中读取数据
  {
#pragma MESSAGE DISABLE C4000
    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
}

