📄 commprotocol.cpp
字号:
/****************************************************************************************************
* 文 件 名: commprotocol.cpp
* 输入接口: BOOL StartupComm(COMMINFO stCommInfo)
* 启动通讯
* INT32 TransferAndAnalyse(UINT32 ulLength, UINT8* pcRecInfo);
* 处理底层接收数据
* 输出接口: GetSendData(UINT8* pcSendInfo) UINT32 GetCommSendLength();
* 提供需要发送的数据,然后由底层驱动发送
* GetRecCommInfo(COMMINFO* stCommInfo)
* 将通讯结果返回
* 控制接口: BOOL GetEndCommFlag();
* 当前通讯是否结束
* 说 明: 升级模块有以下值得注意的:
* 1、协议内不能使用动态内存分配,因为可能升级过程中返回原系统
* 2、实际上无论是输入还是输出都是依赖成员m_stCommInfo
* 对于版本通讯,通过m_stCommInfo保存对方的ver_no,处理后再修改(放入
* 自己的ver_no)m_stCommInfo并输出
* (m_stCommInfo.commData.verData.ver_no)
* 对于文件通讯,接收一方,启动通讯时,给出文件保存的位置指针pcFileInfo,
* 然后通讯种将数据放入pcFileInfo并返回
* (m_stCommInfo.fileData.pcFileInfo)
* 3、注意comm_frame中pack.dataPack包含info指针是永远不能直接使用的,
* 因为除了它之外其他comm_frame结构成员都不是指针,所以不涉及它时,可以直接使用
* pstCommFrame = (CommFrame*) m_acReceiveFrameInfo;
* 将接收帧直接转化为结构使用,而一旦要使用它时,必须这样使用:
* memcpy (m_stCommInfo.commData.fileData.pcFileInfo + m_lFileHandlePos,
* (UINT8*)(m_acReceiveFrameInfo + 20), pstCommFrame->pack.dataPack.length);
* (pack.dataPack.info是(UINT8*)(m_acReceiveFrameInfo + 20),但不能赋值)
* 作 者: 史梁材
* 创建时间: 2002.07.30
* 修改记录:
* (1) 2002.09.11 构造函数CCommProtocol() 合并构造函数,并将构造函数的参数
* 改为缺省参数(见commprotocol.h的函数声明位置)
* (2) 2002.10.23 完善重发机制,如果是文件传输中的重发,那么需要在重发命令中,加入
* 需要重发的包的序号,对FileCommSend()进行修改
* (3) 2002.10.25 增加动态文件读取机制,在这种方式下,使用指针函数来m_funcDynamicGetFilePackInfo
* 进行动态文件读取,即每次取一部分文件内容来发送,文件缓冲只需要帧那么大就行
* 利用m_bIsDynamicSendFile来区别并兼容以前的静态文件读取(即一次将所有的文件内容读取在一个缓冲)
* (4) 2003.02.18 在版本数据结构中,增加硬件类型(主控板的FLASH容量)
* (5) 2003.04.11 在StartupComm,对于CST_FILE,计算stCmdPack.info.fs.data_pack_num时,
* 发现了问题:对于长度正好是m_nFrameDataMaxSize时,加1处理是不对的,
* 导致发送数据时,造成发送的实际pack_num比FILE_START中发送的文件信息中的少1
***************************************************************************************************/
#include "CommProtocol.h"
//////////////////////////////////////////////////////////////////////
// Construction / Destruction
//////////////////////////////////////////////////////////////////////
CCommProtocol::CCommProtocol(BOOL cpu_is_same, UINT32 frame_size)
{
m_bCpuIsSame = cpu_is_same;
m_lReceivePos = 0;
m_lSendSize = 0;
m_lReceiveSize = 0;
m_bHaveSendFrame = 0;
m_nResendNum = 0;
m_bCheckoutIsRight = 1;
m_bIsDynamicSendFile = 0;
SetFrameSize(frame_size);
}
CCommProtocol::~CCommProtocol()
{
}
/*********************************************************************
* 函数名称: CCommProtocol::TransferAndAnalyse
* 说 明: 将底层缓冲中的接收数据移到协议处理缓冲,并校验帧。
* 执行完该函数后,应该立即执行函数GetSendData来
* 确定是否需要会传数据
* 入口参数:
* UINT32 length -- 当前接受到的数据的长度
* UINT8 *rec_info -- 当前接收到的数据的指针
* BOOL bAllDo -- 1,进行全部处理;0,仅仅做包的完整性检查
* 返 回 值:
* INT32 -- -1, 错误数据
* 0, 正确数据
* 1, 帧结束
* 作 者: Shi Liangcai
* 时 间: 2002-07-25 14:32:01
*********************************************************************/
INT32 CCommProtocol::TransferAndAnalyse(UINT32 length, UINT8 *rec_info, BOOL bAllDo)
{
UINT8* pcInfoPos = NULL;
if (m_nStatusFlag == CS_NULL && bAllDo == 1)
{
m_lReceiveSize = 0;
m_lReceivePos = 0;
return -1;
}
memcpy(m_acReceiveFrameInfo + m_lReceivePos, rec_info, length);
if (!m_lReceivePos) // 判断帧头是否等于0x7e
{
if (m_acReceiveFrameInfo[0] != 0x7e)
return -1;
}
m_lReceivePos += length;
if (m_lReceivePos >= 7) // 检验长度
{
m_lReceiveSize = GetFrameLength();
if (m_lReceiveSize < MIN_FRAME_LENGTH) // 长度校验出错,该帧无效
{
m_lReceivePos = 0;
return -1;
}
}
if (m_lReceivePos >= m_lReceiveSize && m_lReceivePos >= MIN_FRAME_LENGTH)
{
CheckupFrame(); // 帧校验,校验错,则由通讯处理函数组织重发命令
if (m_bCheckoutIsRight)
UnformatFrame();
if (bAllDo == 1)
{
switch (m_stCommInfo.nCommType)
{
case CST_START: // 初始化通讯发送方处理
StartCommSend();
break;
case CRT_START: // 初始化通讯接收方处理
StartCommReceive();
break;
case CST_VERSION: // 版本发送方处理
VersionCommSend();
break;
case CRT_VERSION: // 版本接收方处理
VersionCommReceive();
break;
case CST_FILE: // 文件发送方处理
FileCommSend();
break;
case CRT_FILE: // 文件接收方处理
FileCommReceive();
break;
case CST_BREAK: // 中断发送方处理
BreakCommSend();
break;
case CRT_BREAK: // 中断接收方处理
BreakCommReceive();
break;
case CST_RENEW:
RenewCommSend();
break;
case CRT_RENEW:
RenewCommReceive();
break;
default:
m_lReceivePos = 0x00;
m_lReceiveSize = 0x00;
return -1;
}
}
// 接收帧处理完毕,接收位置复位,等待接收下一帧
m_lReceiveSize = 0x00;
m_lReceivePos = 0x00;
return 1;
}
return 0;
}
/*********************************************************************
* 函数名称: CCommProtocol::StartupComm
* 说 明: 启动指定通讯
1、对于无数据通讯,只给出类型
2、对于版本通讯,对于通讯双方,stCommInfo中包含各自的版本信息
3、对于文件通讯,接收和发送的文件缓冲都是由应用提供,本身不提供
发送方stCommInfo中包含将发送的文件信息缓冲指针
接收方stCommInfo中包含将接收文件信息放入的缓冲指针
* 入口参数:
* CommInfo m_stCommInfo -- 通讯信息
* 返 回 值:
* BOOL -- 1,启动成功,需要调用GetSendData函数
* 0,无法启动
* 作者: Shi Liangcai
* 时间 : 2002-07-30 11:25:48
*********************************************************************/
BOOL CCommProtocol::StartupComm(COMMINFO stCommInfo)
{
CmdPack stCmdPack;
memcpy((UINT8*)(&m_stCommInfo), (UINT8*)(&stCommInfo), sizeof(COMMINFO));
// 清通讯标志
m_bHaveSendFrame = 0;
m_nResendNum = 0;
m_bCheckoutIsRight = 1;
m_nCommEndFlag = CET_NOT;
switch (m_stCommInfo.nCommType)
{
case CST_START: // 初始化通讯
stCmdPack.type = CMD_START;
stCmdPack.length = 0x00;
FormatFrame(CPT_CMD, &stCmdPack);
m_nStatusFlag = CSS_START_WAIT_YES;
break;
case CST_VERSION: // 版本
stCmdPack.type = CMD_VERSION;
stCmdPack.length = 0x14;
stCmdPack.info.ver.soft_no = m_stCommInfo.commData.verData.soft_no;
memcpy(stCmdPack.info.ver.ver_info, m_stCommInfo.commData.verData.ver_info, 4);
stCmdPack.info.ver.flash_no = m_stCommInfo.commData.verData.flash_no;
stCmdPack.info.ver.module_no = m_stCommInfo.commData.verData.module_no;
FormatFrame(CPT_CMD, &stCmdPack);
m_nStatusFlag = CSS_VERSION_WAIT_AV;
break;
case CST_FILE: // 文件发送方处理
stCmdPack.type = CMD_FILESTART;
stCmdPack.length = 0x14;
if (m_stCommInfo.commData.fileData.lFileLength % m_nFrameDataMaxSize)
stCmdPack.info.fs.data_pack_num = m_stCommInfo.commData.fileData.lFileLength / m_nFrameDataMaxSize + 1;
else
stCmdPack.info.fs.data_pack_num = m_stCommInfo.commData.fileData.lFileLength / m_nFrameDataMaxSize;
stCmdPack.info.fs.file_no = m_stCommInfo.commData.fileData.file_no;
stCmdPack.info.fs.file_type = m_stCommInfo.commData.fileData.file_type;
memcpy(stCmdPack.info.fs.file_name, m_stCommInfo.commData.fileData.file_name, FIELD_FILE_NAME_LENGTH);
m_lFileHandlePos = 0;
FormatFrame(CPT_CMD, &stCmdPack);
m_nStatusFlag = CSS_FILE_WAIT_SYES;
break;
case CST_BREAK: // 中断通讯
stCmdPack.type = CMD_BREAK;
stCmdPack.length = 0x00;
FormatFrame(CPT_CMD, &stCmdPack);
m_nStatusFlag = CSS_BREAK_WAIT_YES;
break;
case CST_RENEW: // 更新通讯发送
stCmdPack.type = CMD_RENEW;
stCmdPack.length = 0x01;
stCmdPack.info.rn.cResultFlag = m_stCommInfo.commData.renewData.cResultFlag;
FormatFrame(CPT_CMD, &stCmdPack);
m_nStatusFlag = CSS_RENEW_WAIT_YES;
break;
case CRT_VERSION: // 版本通讯接收
m_nStatusFlag = CSR_VERSION_WAIT_RV;
break;
case CRT_FILE: // 文件通讯接收
m_nStatusFlag = CSR_FILE_WAIT_SCMD;
break;
case CRT_BREAK: // 中断通讯接收
m_nStatusFlag = CSR_BREAK_WAIT_BCMD;
break;
case CRT_START: // 初始化通讯
m_nStatusFlag = CSR_START_WAIT_CMD;
break;
case CRT_RENEW: // 更新通讯接收
m_nStatusFlag = CSR_RENEW_WAIT_CMD;
break;
default:
return 0;
}
return 1;
}
/*********************************************************************
* 函数名称: CCommProtocol::GetSendData
* 说 明: 将需要的回传(应答)数据返回给底层驱动,然后发送数据无效;
* 如果不需要,那么返回NULL
* 此外,将通讯状态置位等待
*
* 入口参数:
* UINT8* pcSendInfo -- 返回发送数据的指针,
* 长度由GetSendLength返回,不使用结束符
* 返 回 值:
* void --
* 作 者: Shi Liangcai
* 时 间: 2002-07-30 09:16:39
*********************************************************************/
void CCommProtocol::GetSendData(UINT8* pcSendInfo)
{
if (m_bHaveSendFrame)
{
memcpy(pcSendInfo, m_acSendFrameInfo, m_lSendSize);
m_bHaveSendFrame = 0;
}
return;
}
/*********************************************************************
* 函数名称: CCommProtocol::GetEndCommFlag
* 说 明: 目前执行的通讯是否结束
* 入口参数:
* 返 回 值:
* 通讯结束标志,见enum CommEndType
* 作 者: Shi Liangcai
* 时 间: 2002-08-01 08:48:56
*********************************************************************/
UINT32 CCommProtocol::GetEndCommFlag()
{
if (m_nStatusFlag == CT_NULL)
return m_nCommEndFlag;
else
return CET_NOT;
}
/*********************************************************************
* 函数名称: CCommProtocol::GetRecCommInfo
* 说 明: 返回通讯结果
* 入口参数:
* CommInfo* pstCommInfo -- 通讯信息
* 返 回 值:
* void --
* 作 者: Shi Liangcai
* 时 间: 2002-08-07 11:18:59
*********************************************************************/
void CCommProtocol::GetRecCommInfo(COMMINFO* pstCommInfo)
{
memcpy((UINT8*)(pstCommInfo), (UINT8*)(&m_stCommInfo), sizeof(COMMINFO));
return;
}
/*********************************************************************
* 函数名称:CCommProtocol::GetCommSendLength
* 说明:
* 入口参数:
* 返回值:
* UINT32 -- 桢长度
* 作者: Shi Liangcai
* 时间 : 2002-08-07 11:17:40
*********************************************************************/
UINT32 CCommProtocol::GetCommSendLength()
{
if (m_bHaveSendFrame)
return m_lSendSize;
else
return 0;
}
/*********************************************************************
* 函数名称: CCommProtocol::CheckupData
* 说 明: 对一段信息(字符串)进行校验
* 入口参数:
* UINT8 *pcData -- 校验目标字符串
* UINT32 lDataLen -- 校验字符串的长度
* UINT32 lCode -- 校验码
* UINT16 nValueByteNum -- 校验结果取几个字节
* 返 回 值:
* BOOL -- 1,校验正确;0,校验失败
* 作 者: Shi Liangcai
* 时 间: 2002-07-31 08:47:10
*********************************************************************/
BOOL CCommProtocol::CheckupData(UINT8 *pcData, UINT32 lDataLen, UINT32 lCheckCode, UINT16 nValueByteNum)
{
UINT32 i;
UINT32 lCode;
lCode = 0;
for (i = 0; i < lDataLen; i ++)
{
lCode += *(pcData + i);
}
switch (nValueByteNum)
{
case 1:
lCode = (UINT8)lCode;
break;
case 2:
lCode = (UINT16)lCode;
break;
default: // 其他情况均看做4个字节,32位的校验码
break;
}
if (lCode == lCheckCode)
return TRUE;
else
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -