/** ****************************************************************************** * @file device_param.c * @author AMG Energy Solution Team * @version V1.0.0 * @date 07-Feb-2022 * @brief This file provides all the codes of parameter functions. ****************************************************************************** * @attention * * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. * *

© COPYRIGHT 2022 AMG

****************************************************************************** */ /** @addtogroup mBMS2 * @{ */ /* Includes ------------------------------------------------------------------*/ #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 "asutil.h" #include "temp.h" #include "malloc.h" /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ #define CALIB_INIT_DATA 0xBBBB0002 #define PARAM_INIT_DATA 0xAAAA4001 /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ const char InvFileName[] = "0:/inv.bin"; const char ParamFileName[] = "0:/param.bin"; const char bakParamFileName[] = "0:/param_old.bin"; FIL pFile; /* File objects */ TDEVICE_VALUE device_value, bakdevice_value, dis_device_value; TDEVICE_STATUS device_status, dis_device_status; TDEVICE_CALIB_DATA device_calib_data, dis_device_calib_data; TDEVICE_PARAM device_param, dis_device_param; TDEVICE_INV device_inv, dis_device_inv; /* Private function prototypes -----------------------------------------------*/ /* Private function ----------------------------------------------------------*/ void SetCellQuantity(uint8_t cQuantity) { if ((cQuantity > 0) && (cQuantity <= 16)) { device_param.info.CellQuantity = cQuantity; Save_Param(); } } void Param_Init(uint8_t flag, uint8_t 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 Load_InvData(void) { FRESULT rc; uint32_t wlen; if (ReqUseFatfs()) { rc = f_open(&pFile, InvFileName, FA_READ); if (rc == FR_NO_FILE) { rc = f_open(&pFile, InvFileName, FA_CREATE_NEW | FA_WRITE); if (rc == FR_OK) { // Inventory init Inv_Init(); f_lseek(&pFile, 0); // From start rc = f_write(&pFile, (const char *)&device_inv, sizeof(TDEVICE_INV), &wlen); f_close(&pFile); } } else if (rc == FR_OK) { if (pFile.obj.objsize != sizeof(TDEVICE_INV)) { f_close(&pFile); rc = f_unlink(InvFileName); if (rc != FR_OK) return; rc = f_open(&pFile, InvFileName, FA_CREATE_NEW | FA_WRITE); if (rc == FR_OK) { // Inventory init Inv_Init(); f_lseek(&pFile, 0); // From start rc = f_write(&pFile, (const char *)&device_inv, sizeof(TDEVICE_INV), &wlen); f_close(&pFile); } } else { f_lseek(&pFile, 0); // From start f_read(&pFile, &device_inv, sizeof(TDEVICE_INV), &wlen); f_close(&pFile); } } else { // Inventory init Inv_Init(); } leaveFatfs(); } } void Save_InvData(void) { FRESULT rc; uint32_t wlen; if (ReqUseFatfs()) { rc = f_open(&pFile, InvFileName, FA_WRITE); if (rc == FR_NO_FILE) { rc = f_open(&pFile, InvFileName, FA_CREATE_NEW | FA_WRITE); if (rc == FR_OK) { f_lseek(&pFile, 0); // From start f_write(&pFile, (const char *)&device_inv, sizeof(TDEVICE_INV), &wlen); f_close(&pFile); } } else if (rc == FR_OK) { f_lseek(&pFile, 0); // From start f_write(&pFile, &device_inv, sizeof(TDEVICE_INV), &wlen); f_close(&pFile); } leaveFatfs(); } } /* Calibration Data Load and Save Function */ void Load_CalibData(void) { memcpy(&device_calib_data, (uint8_t *)mBMS_CALIB_BASE_ADDR, sizeof(TDEVICE_CALIB_DATA)); if (device_calib_data.initdata != CALIB_INIT_DATA) { #ifdef CONSOLE_DEBUG printf("\r\n Initialize Calibration Data"); #endif device_calib_data.initdata = CALIB_INIT_DATA; Cal_InitData(); Save_CalibData(); } } void Save_CalibData(void) { uint32_t result = 0; uint32_t sector_addr = mBMS_CALIB_BASE_ADDR; result = FLASH_If_SingleSectorErase(sector_addr); if (result == 0) { uint32_t base = (uint32_t)&device_calib_data; uint32_t len = sizeof(TDEVICE_CALIB_DATA); 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 } } extern FIL File[2]; /* File objects */ uint32_t copyTimer = 0; void IncFileCopyTimer(uint32_t tick) { copyTimer += tick; } uint8_t FileCopy(const char *src, const char *dst, uint32_t length) { BYTE res; #ifdef CONSOLE_DEBUG uint32_t p1 = 0; #endif uint32_t p2, p3; res = f_open(&File[0], src, FA_OPEN_EXISTING | FA_READ); #ifdef CONSOLE_DEBUG printf("Opening \"%s\"", src); printf("\r\n"); put_rc((FRESULT)res); #endif if (res) return 1; copyTimer = 0; BYTE *fBuff = 0; fBuff = mymalloc(length); if (fBuff == NULL) { f_close(&File[0]); return 2; } res = f_read(&File[0], fBuff, length, &p2); if (res || (length != p2)) { f_close(&File[0]); myfree(fBuff); return 3; } f_close(&File[0]); res = f_open(&File[0], dst, FA_CREATE_ALWAYS | FA_WRITE); #ifdef CONSOLE_DEBUG printf("Creating \"%s\"", dst); printf("\r\n"); put_rc((FRESULT)res); #endif if (res) { // f_close(&File[0]); myfree(fBuff); return 4; } #ifdef CONSOLE_DEBUG printf("Copying file...(%d)", p2); #endif res = f_write(&File[0], fBuff, p2, &p3); #ifdef CONSOLE_DEBUG printf("\r\nf_write (%d:%d)", res, p3); printf("\r\n%u bytes copied with %u kB/sec.\r\n\r\n", p1, p1 / copyTimer); #endif myfree(fBuff); f_close(&File[0]); return 0; } void Load_Param_File(void) { FRESULT rc; uint32_t wlen; if (ReqUseFatfs()) { Refeat: rc = f_open(&pFile, ParamFileName, FA_READ); if (rc == FR_NO_FILE) { rc = f_open(&pFile, bakParamFileName, FA_READ); if (rc == FR_OK) { f_close(&pFile); if (FileCopy(bakParamFileName, ParamFileName, sizeof(TDEVICE_PARAM)) == 0) goto Refeat; } 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); rc = f_unlink(bakParamFileName); 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); } } else { // Parameter init Param_Init(true, true); } leaveFatfs(); } } void Save_Param_File(void) { FRESULT rc; uint32_t wlen; if (ReqUseFatfs()) { rc = (FRESULT)FileCopy(ParamFileName, bakParamFileName, sizeof(TDEVICE_PARAM)); if (rc == 0) { 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(); } else { #ifdef CONSOLE_DEBUG printf("\r\nParameter backup fail(%d)\r\n", rc); #endif } } } void Load_Param(void) { Load_CalibData(); Load_InvData(); Load_Param_File(); /* Force parameter reset at least once on firmware update (magic code mismatch) */ if (device_param.initdata != PARAM_INIT_DATA) { #ifdef CONSOLE_DEBUG printf("\r\n[PARAM] Firmware updated: Resetting parameters to KT default (0x%08X -> 0x%08X)", device_param.initdata, PARAM_INIT_DATA); #endif device_param.initdata = PARAM_INIT_DATA; Param_Init(true, true); Save_Param(); } ADC_Param_Load(); device_param.chg_ctrl.current_thr.Discharge_Detection_Threshold = 6000; // 0.05C = 100 * 0.05 = 5A device_param.chg_ctrl.current_thr.Charge_Detection_Threshold = 6000; /* 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; } /* 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) { Save_Param_File(); // 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 // } } 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 } return result; }