ZDBMS/code_drv/McuFlash.c

369 lines
8.5 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.

/********************************************************************************
Copyright (C), Sinowealth Electronic. Ltd.
Author: Sino
Version: V0.0
Date: 2020/04/26
History:
V2.0 2020/04/26 Preliminary
********************************************************************************/
#include "Main.h"
BOOL bMcuFlashWrWaitFlg;
BOOL bMcuFlashWrFlg;
BOOL bMcuFlashErr;
U8 xdata ucMcuFlashWrValid;
U8 xdata bMcuFlashWrWaitCnt;
/*************************************************************************************************
* 函数名: McuFlashWrOneByte
* 参 数: McuFlashAddr起始地址WrData写入的注释
* 返回值: 无
* 描 述: 写1个字节
*************************************************************************************************/
void McuFlashWrOneByte(U16 McuFlashAddr, U8 WrData)
{
IrqDis();
McuFlashEn();
XPAGE = McuFlashAddr>>8;
IB_OFFSET = McuFlashAddr % 256;
IB_DATA = WrData;
IB_CON1 = 0x6E;
IB_CON2 = 0x05;
IB_CON3 = 0x0A;
IB_CON4 = 0x09;
if(XPAGE == (McuFlashAddr>>8))
{
IB_CON5 = 0x06;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
McuFlashDis();
IrqEn();
}
/*************************************************************************************************
* 函数名: McuFlashBlankCheck
* 参 数: McuFlashAddr起始地址
* 返回值: 0非全0Erase失败1全0Erase成功
* 描 述: 当Erase完1个Sector需检查是否全为0
*************************************************************************************************/
BOOL McuFlashBlankCheck(U16 McuFlashAddr)
{
BOOL Result = 1;
U16 i;
for(i=0; i<MCUFLASH_SECTOR_SIZE; i++)
{
if(CBYTE[McuFlashAddr+i] != 0x00)
{
Result = 0;
break;
}
}
return Result;
}
/*************************************************************************************************
* 函数名: McuFlashDataCheck
* 参 数: McuFlashAddr起始地址
* 返回值: 0校验错误1校验正确
* 描 述: 校验被写的Sector数据是否和XRAM区一致
*************************************************************************************************/
BOOL McuFlashDataCheck(U16 McuFlashAddr, U16 XramAddr)
{
BOOL Result = 1;
U8 xdata *ptr = (U8 xdata *)XramAddr; //强制将变量的值作为地址赋值给指针变量
U16 i;
for(i=0; i<MCUFLASH_SECTOR_SIZE; i++)
{
if(CBYTE[McuFlashAddr+i] != *(ptr+i))
{
Result = 0;
break;
}
}
return Result;
}
/*************************************************************************************************
* 函数名: McuFlashWrSector
* 参 数: 无
* 返回值: 无
* 描 述: 写1个Sector的数据
*************************************************************************************************/
BOOL McuFlashWrSector(U16 McuFlashAddr, U16 XramAddr)
{
BOOL Result = 0;
U16 i;
U8 xdata *ptr = (U8 xdata *)XramAddr; //强制将变量的值作为地址赋值给指针变量
for(i=0; i<MCUFLASH_SECTOR_SIZE; i++)
{
IB_OFFSET = McuFlashAddr+i;
XPAGE = (McuFlashAddr+i)>>8;
IB_DATA = *(ptr+i);
IB_CON1 = 0x6E;
if(!EA)
{
IB_CON2 = 0x05;
if(FLASHCON)
{
IB_CON3 = 0x0A;
if(ucMcuFlashWrValid == 0x55)
{
IB_CON4 = 0x09;
if(XPAGE == ((McuFlashAddr+i)>>8))
{
IB_CON5 = 0x06;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
Result = 1;
}
else
{
Result = 0;
break;
}
}
else
{
Result = 0;
break;
}
}
else
{
Result = 0;
break;
}
}
else
{
Result = 0;
break;
}
}
return Result;
}
/*************************************************************************************************
* 函数名: McuFlashWrite
* 参 数: McuFlashAddr写入的地址长度固定为1个Sector
* 返回值: 0写入失败1写入成功
* 描 述: 写MCU Flash的1个Sector:
1.Erase Sector
2.检查当前Sector是否全为0
3.将XRAM数据写入
4.校验XRAM和MCU Flash区数据是否一致
*************************************************************************************************/
BOOL McuFlashWrite(U16 McuFlashAddr, U16 XramAddr)
{
BOOL Result = 0;
McuWDTClear(); //清看门狗
IrqDis(); //关闭中断源
McuFlashEn();
XPAGE = McuFlashAddr >> 8;
IB_CON1 = 0xE6;
if(!EA)
{
IB_CON2 = 0x05;
if(FLASHCON)
{
IB_CON3 = 0x0A;
if(ucMcuFlashWrValid == 0x55)
{
IB_CON4 = 0x09;
if(XPAGE == (McuFlashAddr >> 8))
{
IB_CON5 = 0x06;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
if(McuFlashBlankCheck(McuFlashAddr)) //查空
{
if(McuFlashWrSector(McuFlashAddr, XramAddr)) //写入
{
if(McuFlashDataCheck(McuFlashAddr, XramAddr)) //校验
{
Result = 1;
}
}
}
}
}
}
}
IB_CON1 = 0;
IB_CON2 = 0;
IB_CON3 = 0;
IB_CON4 = 0;
IB_CON5 = 0;
McuFlashDis();
XPAGE = 0x00;
IrqEn();
return Result;
}
/*************************************************************************************************
* 函数名: McuFlashProcess
* 参 数: 无
* 返回值: 无
* 描 述: 写MCU Flash同时更新备份1区和2区
*************************************************************************************************/
void McuFlashProcess(void)
{
BOOL McuFlashBk1WrFailFlg = 0, McuFlashBk2WrFailFlg = 0;
U16 VoltageMin;
if(bMcuFlashWrFlg)
{
bMcuFlashWrFlg = 0;
ucMcuFlashWrValid = 0x55; //防误写检验标志
if(ucCellNum > 5) //6~10串应用需要总电压超过10V
{
VoltageMin = 10000;
}
else //3~5串应用需要总电压超过5V
{
VoltageMin = 5000;
}
if((Info.ulVoltage>=VoltageMin) && (E2uiCheckFlag==0x5AA5))
{
if(!McuFlashWrite(MCUFLASH_BK1_ADDR, XRAM_MAP_ADDR)) //连续写两次,如果都错误则置位错误标志
{
if(!McuFlashWrite(MCUFLASH_BK1_ADDR, XRAM_MAP_ADDR))
{
McuFlashBk1WrFailFlg = 1;
E2uiCheckFlag = 0xFFFF;
McuFlashWrOneByte(MCUFLASH_BK1_ADDR+510,0xFF);
McuFlashWrOneByte(MCUFLASH_BK1_ADDR+511,0xFF);
}
}
if(!McuFlashWrite(MCUFLASH_BK2_ADDR, XRAM_MAP_ADDR))
{
if(!McuFlashWrite(MCUFLASH_BK2_ADDR, XRAM_MAP_ADDR))
{
McuFlashBk2WrFailFlg = 1;
E2uiCheckFlag = 0xFFFF;
McuFlashWrOneByte(MCUFLASH_BK2_ADDR+510,0xFF);
McuFlashWrOneByte(MCUFLASH_BK2_ADDR+511,0xFF);
}
}
}
else
{
McuFlashBk1WrFailFlg = 1;
McuFlashBk2WrFailFlg = 1;
}
ucMcuFlashWrValid = 0x00;
if(McuFlashBk1WrFailFlg && McuFlashBk2WrFailFlg) //如果Flash两个区都操作错误则置位Flash错误标志
{
bMcuFlashErr = 1;
}
}
}
/*************************************************************************************************
* 函数名: McuFlashRead
* 参 数: SourceAddr源地址TargetAddr目标地址Length数据长度
* 返回值: 0数据正确1数据错误
* 描 述: 判断MCU Flash参数区的最后一个字节是否为0x5AA5检查数据区是否被破坏
*************************************************************************************************/
BOOL McuFlashRead(U16 SourceAddr, U8 xdata *TargetAddr, U16 Length)
{
U16 i;
BOOL Result = 1;
U8 xdata *data TargetAddr1 = TargetAddr; //*后面的data关键字的作用是把指针TargetAddr1定义在data区中
IrqDis();
McuFlashEn();
McuWDTClear();
for(i=0; i<Length; i++)
{
*TargetAddr1 = CBYTE[SourceAddr+i];
TargetAddr1++;
}
McuFlashDis();
IrqEn();
return Result;
}
/*************************************************************************************************
* 函数名: McuFlashWrWaitCheck
* 参 数: 无
* 返回值: 无
* 描 述: 当需要写MCU Flash参数时部分模块需要延时2S执行写操作上位机修改参数部分模块立即写
*************************************************************************************************/
void McuFlashWrWaitCheck(void)
{
if(bMcuFlashWrWaitFlg)
{
if(++bMcuFlashWrWaitCnt >= MCU_FLASH_WATI_DELAY)
{
bMcuFlashWrWaitFlg = 0;
bMcuFlashWrWaitCnt = 0;
bMcuFlashWrFlg = 1;
}
}
}
/*************************************************************************************************
* 函数名: McuFlashCheckFlg
* 参 数: McuFlashAddrMCU Flash区的地址
* 返回值: 0数据正确1数据错误
* 描 述: 判断MCU Flash参数区的最后一个字节是否为0x5AA5检查数据区是否被破坏
*************************************************************************************************/
BOOL McuFlashCheckFlg(U16 McuFlashAddr)
{
BOOL Result = 0;
McuFlashEn();
if(CWORD[McuFlashAddr/2] == 0x5AA5)
{
Result = 1;
}
McuFlashDis();
return Result;
}