/* Copyright (c) 2012-2013 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ /* * High Level description: * http://www.ti.com/lit/ds/symlink/device.pdf * Thechnical Reference: * http://www.ti.com/lit/ug/sluu431/sluu431.pdf */ #include "includes.h" #include "device_param.h" #include "ff.h" #include "ff_shell.h" #include "flash_if.h" #include "dflash_sf1.h" #include "dflash_chg_ctrl.h" #include "dflash_cal.h" #include "dflash_sbs.h" #include "temp.h" #include "asutil.h" #define PARAM_INIT_DATA 0xAAAA32F4 #define CAL_PARAM_BASE_ADDR mBMS_PARAM_BASE_ADDR + 0x2000 const char ParamFileName[] = "0:/param.bin"; FIL pFile; /* File objects */ TDEVICE_VALUE device_value, bakdevice_value, dis_device_value; TDEVICE_STATUS device_status, dis_device_status; TDEVICE_PARAM device_param, dis_device_param; TDEVICE_INV device_inv, dis_device_inv; void SetCellQuantity(u8 cQuantity) { if ((cQuantity > 0) && (cQuantity <= 16)) { device_param.info.CellQuantity = cQuantity; Save_Param(); } } void Param_Init(u8 flag, u8 factory) { if (factory) Cal_InitData(); if (flag) SBS_InitData(); SF1_InitData(); ChgCtrlCfg_InitData(); } /* Inventory Data Load and Save Function */ void Inv_Init(void) { device_inv.ManufactureDate = 0; memset(device_inv.ModuleNo, 0x00, sizeof(device_inv.ModuleNo)); memset(device_inv.SerialNo, 0x00, sizeof(device_inv.SerialNo)); } void Save_InvData(void) { uint32_t result = 0; uint32_t sector_addr = mBMS_INV_BASE_ADDR; /* init flash */ FLASH_If_Init(); result = FLASH_If_SingleSectorErase(sector_addr); if (result == 0) { uint32_t base = (uint32_t)&device_inv; uint32_t len = sizeof(TDEVICE_INV); if ((len % 4) > 0) len = len / 4 + 1; else len = len / 4; result = FLASH_If_Write(§or_addr, (uint32_t *)base, len); #ifdef CONSOLE_DEBUG if (result != 0) printf("\r\n Inventory save fail (%d)", result); #endif } } void Load_InvData(void) { memcpy(&device_inv, (uint8_t *)mBMS_INV_BASE_ADDR, sizeof(TDEVICE_INV)); if (device_inv.initdata != INV_INIT_DATA) { #ifdef CONSOLE_DEBUG printf("\r\n Initialize Inventory Data"); #endif device_inv.initdata = INV_INIT_DATA; Inv_Init(); Save_InvData(); } } void Load_Param(void) { memcpy(&device_param, (uint8_t *)mBMS_PARAM_BASE_ADDR, sizeof(TDEVICE_PARAM)); if (device_param.initdata != PARAM_INIT_DATA) { device_param.initdata = PARAM_INIT_DATA; // Parameter init Param_Init(true, true); Save_Param(); } ADC_Param_Load(); /* KT Requirement: Cell deviation 200mV threshold (Warning/Time unused, CV_Diff_ProtectHoldTime 24h default) */ if ((device_param.safety.cv_diff.Cell_Voltage_Diff_Threshold == 0) || (device_param.safety.cv_diff.Cell_Voltage_Diff_Threshold > 200)) { device_param.safety.cv_diff.Cell_Voltage_Diff_Threshold = 200; } /* Load Inventory Data */ Load_InvData(); /* KT Requirement: Cell balancing threshold set to 3350mV in RAM at boot */ device_param.chg_ctrl.cell_bal_cfg.Cell_Balance_Threshold = 3350; } void Save_Param(void) { uint32_t result = 0; uint32_t sector_addr = mBMS_PARAM_BASE_ADDR; result = FLASH_If_SingleSectorErase(sector_addr); if (result == 0) { uint32_t base = (uint32_t)&device_param; uint32_t len = sizeof(TDEVICE_PARAM); if ((len % 4) > 0) len = len / 4 + 1; else len = len / 4; result = FLASH_If_Write(§or_addr, (uint32_t *)base, len); #ifdef CONSOLE_DEBUG if (result != 0) printf("\r\n Param save fail (%d)", result); #endif /* CONSOLE_DEBUG */ } } void LoadFwInfo(void) { memcpy(&fwinfo, (uint8_t *)mBMS_FW_INFO_BASE_ADDR, sizeof(FW_INFO)); } uint32_t SaveFwInfo(void) { uint32_t result = 0; uint32_t sector_addr = mBMS_FW_INFO_BASE_ADDR; /* init flash */ FLASH_If_Init(); result = FLASH_If_SingleSectorErase(sector_addr); if (result == 0) { uint32_t base = (uint32_t)&fwinfo; uint32_t len = sizeof(FW_INFO); if ((len % 4) > 0) len = len / 4 + 1; else len = len / 4; result = FLASH_If_Write(§or_addr, (uint32_t *)base, len); if ((result == 0) && ((sector_addr != (mBMS_FW_INFO_BASE_ADDR + len * 4)) || (memcmp((const void *)mBMS_FW_INFO_BASE_ADDR, &fwinfo, sizeof(FW_INFO)) != 0))) { result = 3; /* Incomplete write or flash readback mismatch. */ } #ifdef CONSOLE_DEBUG if (result != 0) printf("\r\n Fw information save fail (%d)", result); #endif /* CONSOLE_DEBUG */ } return result; } void Load_Param_File(void) { FRESULT rc; u32 wlen; if (ReqUseFatfs()) { rc = f_open(&pFile, ParamFileName, FA_READ); if (rc == FR_NO_FILE) { rc = f_open(&pFile, ParamFileName, FA_CREATE_NEW | FA_WRITE); if (rc == FR_OK) { // Parameter init Param_Init(true, true); f_lseek(&pFile, 0); // From start rc = f_write(&pFile, (const char *)&device_param, sizeof(TDEVICE_PARAM), &wlen); f_close(&pFile); } } else if (rc == FR_OK) { if (pFile.obj.objsize != sizeof(TDEVICE_PARAM)) { f_close(&pFile); rc = f_unlink(ParamFileName); if (rc != FR_OK) return; rc = f_open(&pFile, ParamFileName, FA_CREATE_NEW | FA_WRITE); if (rc == FR_OK) { // Parameter init Param_Init(true, true); f_lseek(&pFile, 0); // From start rc = f_write(&pFile, (const char *)&device_param, sizeof(TDEVICE_PARAM), &wlen); f_close(&pFile); } } else { f_lseek(&pFile, 0); // From start f_read(&pFile, &device_param, sizeof(TDEVICE_PARAM), &wlen); f_close(&pFile); } } leaveFatfs(); } ADC_Param_Load(); /* KT Requirement: Cell deviation 200mV threshold (Warning/Time unused, CV_Diff_ProtectHoldTime 24h default) */ if ((device_param.safety.cv_diff.Cell_Voltage_Diff_Threshold == 0) || (device_param.safety.cv_diff.Cell_Voltage_Diff_Threshold > 200)) { device_param.safety.cv_diff.Cell_Voltage_Diff_Threshold = 200; } } void Save_Param_File(void) { FRESULT rc; u32 wlen; if (ReqUseFatfs()) { rc = f_open(&pFile, ParamFileName, FA_WRITE); if (rc == FR_NO_FILE) { rc = f_open(&pFile, ParamFileName, FA_CREATE_NEW | FA_WRITE); if (rc == FR_OK) { f_lseek(&pFile, 0); // From start f_write(&pFile, (const char *)&device_param, sizeof(TDEVICE_PARAM), &wlen); f_close(&pFile); } } else if (rc == FR_OK) { f_lseek(&pFile, 0); // From start f_write(&pFile, &device_param, sizeof(TDEVICE_PARAM), &wlen); f_close(&pFile); } leaveFatfs(); } }