📄 xmodemlpc23xx.c
字号:
/*
*****************************************Copyright (c)**************************************************
**
**
**--------------文件信息--------------------------------------------------------------------------------
** 文件名称: XmodemLPC23xx.c
** 文件标识:
** 描 述: LPC23xx目标板Xmodem协议实现,用RealView 3.0+编译,必须使用ARM方式编译
**
**
**--------------修改记录--------------------------------------------------------------------------------
**
** 当前版本: 1.0
** 作 者:
** 完成日期: 2007年5月11日
** 修改内容:
**
** 取代版本:
** 作 者:
** 完成日期:
********************************************************************************************************
*/
#include "config.h"
//定义全局变量
const BYTE smStartupString[]="Type 'd' download, Others run app.\n\r\0";
//从RS232发送一个字节
static void UartSendByte(BYTE bChar)
{
UART1SendByte(bChar);
}
//从RS232接收一个字节
static DWORD UartGetByte(BYTE * pbRcvByte)
{
return UART1GetByte(pbRcvByte);
}
//向RS232发送一个字符串
static void UartSendStr(BYTE *pbStr)
{
UART1SendStr(pbStr);
}
/*
********************************************************************************************************
** 函数名称: WriteOnePageToFlash
** 函数功能:将EMCDCM_DFU_PAGESIZE个字节的数据写入Flash当前扇区的当前位置
** 输入参数: dwDstFlashAddr -- 将要写入的Flash地址
**
** 输出参数:
** 返回 值:EMCDCM_OK --在线设备固件更新成功
** EMCDCM_ERR --更新失败
** 全局变量:
** 调用模块:
** 注意事项:
**
**------------------------------------------------------------------------------------------------------
** 修改记录:
**
** 2007年5月12日,文件编写,原始版本,by
**
**------------------------------------------------------------------------------------------------------
********************************************************************************************************
*/
static DWORD WriteOnePageToFlash(DWORD dwDstFlashAddr)
{
DWORD dwRetc = EMCDCM_ERR;
dwRetc = IAPWriteFlash(dwDstFlashAddr,(DWORD)gv_smFlashWriteBuff,FLASH_WRITE_BUFF_SIZE);
return dwRetc;
}
/*
********************************************************************************************************
** 函数名称: DFUByXModem
** 函数功能:按照XModem协议更新设备固件
** 输入参数: wBytesPerPackage -- 每个数据包的字节数
** 输出参数:
** 返回 值:EMCDCM_OK --在线设备固件更新成功
** EMCDCM_ERR --更新失败
** 全局变量:
** 调用模块:
** 注意事项:
**
**------------------------------------------------------------------------------------------------------
** 修改记录:
**
** 2007年5月12日,文件编写,原始版本,by
**
**------------------------------------------------------------------------------------------------------
********************************************************************************************************
*/
DWORD DFUByXModem(WORD wBytesPerPackage)
{
DWORD dwDstFlashAddr = 0x00000000;
WORD i = 0;
WORD wTimeCount = 0; //超时计数器
BYTE bPackageNO = 1; //包序号
WORD wBuffPosition = 0; //存放数据缓冲区当前位置
//DWORD dwCRC = 0;
BYTE bTmpChar = 0x00;
DWORD dwUartGetRetc = EMCDCM_ERR;
DWORD dwRetc = EMCDCM_OK;
UartSendStr((BYTE *)smStartupString); //向PC机发送开始提示信息
while(1)
{
dwUartGetRetc = UartGetByte(&bTmpChar);
if(EMCDCM_OK == dwUartGetRetc)
{
if('d' == bTmpChar)
{
break;
}
}
else
{
}
}
MyMemSet((void *)gv_smFlashWriteBuff,0xFF,FLASH_WRITE_BUFF_SIZE);
if(EMCDCM_ERR == IAPWriteFlashPrepare(CODE_RUN_START_SECTOR, CODE_RUN_END_SECTOR))
{
dwRetc = EMCDCM_ERR;
return dwRetc;
}
//每秒向PC机发送一个控制字符“C”,等待控制字〈soh〉
while(1) //receive the start of Xmodem
{
bTmpChar = 0x00;
UartGetByte(&bTmpChar);
if(XMODEM_SOH == bTmpChar)
{
break;
}
else
{
if(++wTimeCount > 500) //wait for sometimes
{
UartSendByte(XMODEM_RECIEVING_WAIT_CHAR); //send a "C"
wTimeCount = 0;
}
}
}
wBuffPosition = 0;
//开始接收数据块
do
{
bTmpChar = 0x00;
UartGetByte(&bTmpChar);
if(bPackageNO == ((BYTE)bTmpChar))
{
bTmpChar = 0x00;
UartGetByte(&bTmpChar);
if(bPackageNO == ((BYTE)(~bTmpChar)))
{
for(i=0; i<wBytesPerPackage; i++) //接收wPackageBytes个字节数据
//for(i=0; i<256; i++)
{
UartGetByte((BYTE *)(gv_smFlashWriteBuff + wBuffPosition));
wBuffPosition++;
}
bTmpChar = 0x00;
UartGetByte(&bTmpChar);
bTmpChar = 0x00;
UartGetByte(&bTmpChar);
//???????????????
//if(calcrc(&data[bufferPoint-128],128) == crc) //CRC校验验证
//?????????????????????? 后续工作是要与上位机协调做CRC校验
if(1)
{
//UartSendByte(XMODEM_ACK); //正确收到一个数据块
//正确接收FLASH_WRITE_BUFF_SIZE个字节的数据
if(wBuffPosition == ((WORD)FLASH_WRITE_BUFF_SIZE))
{
dwRetc = WriteOnePageToFlash(dwDstFlashAddr); //收到FLASH_WRITE_BUFF_SIZE字节写入Flash中
if(EMCDCM_ERR == dwRetc)
{
return dwRetc;
}
MyMemSet((void *)gv_smFlashWriteBuff,0xFF,FLASH_WRITE_BUFF_SIZE);
dwDstFlashAddr += FLASH_WRITE_BUFF_SIZE; //Flash地址增加FLASH_WRITE_BUFF_SIZE长度个字节
wBuffPosition = 0;
}
UartSendByte(XMODEM_ACK); //正确收到一个数据块
bPackageNO++; //数据块编号加1
} //end of CRC验证通过
else
{
UartSendByte(XMODEM_NAK); //要求重发数据块
}
}
else //接收包序号不正确
{
UartSendByte(XMODEM_NAK); //要求重发数据块
}
}
else //接收包序号不正确
{
UartSendByte(XMODEM_NAK); //要求重发数据块
}
bTmpChar = 0x00;
UartGetByte(&bTmpChar);
if(XMODEM_EOT == bTmpChar)
{
break;
}
else
{
while(XMODEM_SOH != bTmpChar)
{
bTmpChar = 0x00;
UartGetByte(&bTmpChar);
if(XMODEM_EOT == bTmpChar)
{
break;
}
}//end of 等待包传输开始
}
}
while(bTmpChar != XMODEM_EOT); //循环接收,直到全部发完
UartSendByte(XMODEM_ACK); //通知PC机全部收到
if(wBuffPosition > 0)
{
dwRetc = WriteOnePageToFlash(dwDstFlashAddr); //把剩余的数据写入Flash中
}
return dwRetc;
}
/*
********************************************************************************************************
** 函数名称: DevFirmwareUpdate
** 函数功能:按照XModem协议更新设备固件入口函数
** 输入参数:
** 输出参数:
** 返回 值:
**
** 全局变量:
** 调用模块:
** 注意事项:
**
**------------------------------------------------------------------------------------------------------
** 修改记录:
**
** 2007年5月15日,文件编写,原始版本,by
**
**------------------------------------------------------------------------------------------------------
********************************************************************************************************
*/
void DevFirmwareUpdate(void)
{
DWORD dwRetc = EMCDCM_OK;
if(NO_BACKUP_CODE == gv_DevCfg.commonCfg.bBackupCodeFlag)
{
dwRetc = CopyRunToBackup();
if(EMCDCM_OK == dwRetc)
{
//Log4c("DevFirmwareUpdate()","CopyRunToBackup() succeed",COMMON_C_LOG_INFO);
gv_DevCfg.commonCfg.bBackupCodeFlag = HAS_BACKUP_CODE;
dwRetc = SaveDevCfg(); //是否需要申请对gv_smFlashWriteBuff的控制?
if(EMCDCM_OK == dwRetc)
{
//Log4c("DevFirmwareUpdate()","SaveDevCfg() succeed!",COMMON_C_LOG_INFO);
//进入更新流程
}
else
{
Log4c("DevFirmwareUpdate()","SaveDevCfg() error!",COMMON_C_LOG_FATAL);
//todo:通知上位机进行写配置信息失败需人工干预
}
}
else
{
Log4c("DevFirmwareUpdate()","CopyRunToBackup() error",COMMON_C_LOG_FATAL);
//todo:通知上位机备份代码时写Flash出错,需要人工干预,本次不执行更新;
//Reset();
}
}
dwRetc = DFUByXModem(128);
if(EMCDCM_OK == dwRetc)
{
//修改运行标志为试运行
gv_DevCfg.commonCfg.bRunningState = TRY_RUNNING;
dwRetc = SaveDevCfg(); //是否需要申请对gv_smFlashWriteBuff的控制?
if(EMCDCM_OK == dwRetc)
{
Reset();
}
else
{
Log4c("DevFirmwareUpdate()","SaveDevCfg()",COMMON_C_LOG_FATAL);
//todo:通知写配置信息失败,需人工干预
}
}//endof 更新成功
else
{
Log4c("DevFirmwareUpdate()","DFUByXModem() error",COMMON_C_LOG_ERR);
if(HAS_BACKUP_CODE == gv_DevCfg.commonCfg.bBackupCodeFlag)
{
dwRetc = CopyBackupToRun();
if(EMCDCM_OK == dwRetc)
{
//system will be restarted,so it cant go to here
}
else
{
Log4c("DevFirmwareUpdate()","CopyBackupToRun() error",COMMON_C_LOG_FATAL);
//todo:通知更新失败,将备份区代码复制到运行区出错,需人工干预
}
}//endof 备份区有代码
else
{
Log4c("DevFirmwareUpdate()","DFUByXModem() error! but no backup code!",COMMON_C_LOG_FATAL);
//todo:通知更新失败,需人工干预
}
}//endof DFUByXModem()自动更新失败
}
/*******************************************************************************************************
** End Of File
********************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -