Files
CHJ/lhl_flash.c
2026-03-20 21:09:48 +08:00

218 lines
6.8 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "../main/SystemInclude.h"
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
USER_PARAMS_ADDR 参数数据保存区对应EEPROM的 0x10-0x6C0 区间
参数页说明:将 u16 MBReg[336]; u16 WordReg[128]; u32 DWordReg[64];
总共 1712bytes 依次连续存储到USER_PARAMS_ADDR为起始地址的页;
CORRECT_DATA_ADDR 默认校准页保存区对应EEPROM的 0x1000-及以后按照内码量设计的区间
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
//写参数数据保存区-临时缓冲区
u8 param_buffer[TOTAL_PARAM_SIZE] __attribute__((aligned(4))); //4字节对齐
void update_param_bufferFromFlash(void)//
{
memcpy(param_buffer, (void*)USER_PARAMS_ADDR, TOTAL_PARAM_SIZE);
}
//写参数数据保存区-将临时缓冲区param_buffer数据存入flash ------------------
static void WriteAllParamToFlash(void)
{
//擦除 Flash 页USER_PARAMS_ADDR 是页起始)
if(LHL_FLASH_Erase(USER_PARAMS_ADDR, USER_PARAMS_ADDR, LHL_LNG_TIMEOUT) != LHL_OK)
{
while(1);
}
//按 32-bit word 写入 必须 4-byte 对齐
u16 word_count = (TOTAL_PARAM_SIZE + 3)>>2; // 向上取整 转换为32位数据的个数
LHL_FLASH_Program( USER_PARAMS_ADDR, (uint32_t*)param_buffer, word_count, LHL_LNG_TIMEOUT );
}
//写参数数据保存区-双字节保存区
u16 WriteShortParameterToFlash(u16 parameterAdr)
{
//访问双字节数据保存区------------------------------------------------------------------
// if((parameterAdr >=REG_MEM_ADDR_START) && (parameterAdr < REG_INT_DWORD_MEM_ADDR_START))
// {}
u8 *p = param_buffer;
tempL.Byte[2] = CRC8(tempL.Byte, 2);//计算新值校验码
p += parameterAdr;
//更新变量
p[0] = tempL.Byte[0];
p[1] = tempL.Byte[1];
p[2] = tempL.Byte[2];
//写param_buffer到Flash
WriteAllParamToFlash();
tempL.Word[0] = ReadShortParameterFromFlash(parameterAdr,WordDefault[ADR_WORD_IDX(parameterAdr)][DEFAULT]);
tempL.Byte[2] = 0;
// 注意:此时不用更新 WordReg[index]
// 因为上层会用返回值来更新:*WRSource = 返回值;
return tempL.Word[0]; //上层会用此值更新 WordReg[I]
}
//写参数数据保存区-四字节保存区
u32 WriteLongParameterToFlash(u16 parameterAdr)
{
// if( (parameterAdr >=REG_INT_DWORD_MEM_ADDR_START)&& parameterAdr <= REG_INT_DWORD_MEM_ADDR_END)
// { }
tempDev.Byte[4] = CRC8(tempDev.Byte, 4);//计算新值校验码
//更新变量
u8 *p = param_buffer;
p += (parameterAdr );
p[0] = tempDev.Byte[0];
p[1] = tempDev.Byte[1];
p[2] = tempDev.Byte[2];
p[3] = tempDev.Byte[3];
p[4] = tempDev.Byte[4];
//写param_buffer到Flash
WriteAllParamToFlash();
tempDev.DWord[0] = ReadLongParameterFromFlash(parameterAdr,WordDefault[ADR_DWORD_IDX(parameterAdr)][DEFAULT]);
tempDev.Byte[4] = 0;
return tempDev.DWord[0];
}
//写校准页保存区 ,二次修正保存区 ,不定长参数数据保存区---------------------------------------------------
void WriteMultiByteToFlash(u16 address, u8 *wrtData, u16 dataLenth, u8 flashAdr)
{
(void)flashAdr; // 没有多个Flash
//默认校准曲线---------------------------------------------------------------
if(address >= CALI_DATA1_ADDR)//要写入的地址为原eeprom的校准区
{
//0.转换成Flash地址
u32 ADDR = (u32)(address - CALI_DATA1_ADDR);
ADDR = ADDR + CORRECT_DATA_ADDR;
//判断是否新一页,擦除新页准备写入
if((ADDR&0x0FFF) == 0x000) LHL_FLASH_Erase(ADDR,ADDR,LHL_LNG_TIMEOUT);//ADDR跨页即ADDR为页首地址
if(ADDR >(CORRECT_DATA_ADDR+ CALIB_STORED_SIZE) ) MBBuf.BusError = SLAVE_DEVICE_FAILURE;//溢出
//写校准进入Flash
LHL_FLASH_Program(ADDR,(u32 *)wrtData,dataLenth>>2 ,LHL_LNG_TIMEOUT);
}
//校准曲线2---------------------------------------------------------------
//CALI_DATA2_ADDR CORRECT_DATA2_ADDR CALIB_STORED_SIZE2
//校准曲线3---------------------------------------------------------------
//CALI_DATA3_ADDR CORRECT_DATA3_ADDR CALIB_STORED_SIZE3
//二次修正区---------------------------------------------------------------
// else if()
// {
// USER_DCOEF_TAG_ADDR
// }
//写入多个到参数数据保存区------------------------------------------------------------------
else if((address >=REG_MEMORY_ADDR) && (address <= REG_INT_DWORD_MEM_ADDR_END))
{
wrtData[dataLenth] = CRC8(wrtData, dataLenth);//计算新值校验码
//更新变量
u8 *p = param_buffer;
p += address;
/*for(u8 i = 0 ; i < dataLenth+1 ; i ++)
{
p[i] = wrtData[i];
}*/
//每两个字节交换
for (int i = 0; i < dataLenth; i += 2) {
p[i] = wrtData[i + 1]; //低地址
p[i + 1] = wrtData[i]; //高地址
}
p[dataLenth]= wrtData[dataLenth];//CRC直接复制
WriteAllParamToFlash();
}
}
//读双字节数据保存区------------------------------------------------------------------
u16 ReadShortParameterFromFlash(u16 parameterAdr , u16 parameterDefault)
{
// if(parameterAdr >=REG_MEM_ADDR_START && parameterAdr < REG_INT_DWORD_MEM_ADDR_START)
// { }
u32 ADDR = ((u32)parameterAdr + USER_PARAMS_ADDR);// 将EEPROM 参数地址(如 MEM_ADDR_REG_0X30 = 0x10转为 Flash 物理地址
tempL.Word[0] = 0;
memcpy(tempL.Byte,(const void*)ADDR, 3);
if(tempL.Byte[2] != CRC8(tempL.Byte, 2))
{
tempL.Word[0] = (u32)parameterDefault;
isReadParameterOK = 0;
}
else
{
tempL.Byte[2] = 0;
isReadParameterOK = 1;
}
return tempL.Word[0];
}
//读四字节数据保存区------------------------------------------------------------------
u32 ReadLongParameterFromFlash(u16 parameterAdr , u16 parameterDefault)
{
// if( (parameterAdr >=REG_INT_DWORD_MEM_ADDR_START)&& parameterAdr <= REG_INT_DWORD_MEM_ADDR_END)
// { }
u32 ADDR = (u32)(parameterAdr + USER_PARAMS_ADDR);
tempDev.DWord[0] = 0;
memcpy(tempDev.Byte,(const void*)ADDR, 5);
if(tempDev.Byte[4] != CRC8(tempDev.Byte, 4))
{
tempDev.DWord[0] = (u32)parameterDefault;
isReadParameterOK = 0;
}
else
{
isReadParameterOK = 1;
}
return tempDev.DWord[0];
}
//读数据保存区,校准数据保存区------------------------------------------------------------------
void ReadMultiByteFromFlash(u16 address,u8 *wrtData, u16 dataLenth, u8 flashAdr)
{
(void)flashAdr; // 没有多个Flash,避免编译器 warning
u32 ADDR;
//读校准数据保存区--------------------------------------------------------
//由于校准数据地址基准为eeprom的地址而所有的校准都在该地址后因此只需要判断这一个即可
if(address >=CALI_DATA1_ADDR)
{
ADDR =(u32)(address-CALI_DATA1_ADDR );
ADDR += CORRECT_DATA_ADDR; //转换为Flash地址
memcpy(wrtData,(const void*)ADDR, dataLenth);
}
//读数据保存区----------------------------------------------------------
else if((address >=REG_MEMORY_ADDR) && (address <= REG_INT_DWORD_MEM_ADDR_END))
{
ADDR =((u32)address + USER_PARAMS_ADDR);
memcpy(wrtData,(const void*)ADDR, dataLenth); //不定长参数的校验位是存了的,若判断但是默认值=?未判断
}
}