292 lines
17 KiB
C
292 lines
17 KiB
C
#include <string.h>
|
||
#include <stdio.h>
|
||
#include "usb.h"
|
||
#include "iap.h"
|
||
#include "sys.h"
|
||
#include "systick.h"
|
||
#include "usart.h"
|
||
#include "led.h"
|
||
#include "timer.h"
|
||
#include "sysport.h"
|
||
#include "mac.h"
|
||
#include "stm32Temp.h"
|
||
#include "watchdog.h"
|
||
#include "rtc.h"
|
||
#include "user_tcp.h"
|
||
#include "user_key.h"
|
||
#include "logflash.h"
|
||
#include "user_ftp.h"
|
||
#include "user_http.h"
|
||
#include "ec20module.h"
|
||
#include "ec20tcp.h"
|
||
#include "ec20http.h"
|
||
#include "userapp.h"
|
||
#include "user_flash.h"
|
||
#include "user_ftp.h"
|
||
#include "usercmd.h"
|
||
#include "user_oled.h"
|
||
|
||
/**********************************************************************************
|
||
*内部函数声明
|
||
**********************************************************************************/
|
||
RunResult NetTask(void) ; //网络初始化网络
|
||
|
||
|
||
int main(void)
|
||
{
|
||
RunResult result = RUNERR ; //函数运行状态变量
|
||
uint32_t appAddr = 0 ; //最终跳转的APP FLASH段首地址
|
||
InitIapFlashConfig(&uIapFlash) ; //读出FLASH中的Iap配置,初始化共用体变量uIapFlash,最后重新写入FLASH中
|
||
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4) ; //设置系统中断优先级分组4 无子优先级、0~15共计16个抢占优先级
|
||
InitApplictationState(&gateApp); //初始化结构体变量gateApp
|
||
UsbInit(9600) ; //调试串口、串口转USB口初始化
|
||
Board_Init() ; //硬件驱动初始化和功能块初始化
|
||
Watchdog_Feed() ; //看门狗喂狗
|
||
|
||
/*强制升级检测、开始变砖检测修复 ▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼*/
|
||
if( (uIapFlash.sIapFlash.JumpResult == 0x30) ) // 跳转失败或者按键操作进入恢复模式,则运行应急程序
|
||
{
|
||
DisplayInfo("执行应急程序") ;
|
||
goto SAVEAPPOUT ; //跳转到应急程序运行
|
||
}
|
||
else //跳转APP未出现失败,设置标志位jumpResult为暂未跳转成功状
|
||
{
|
||
uIapFlash.sIapFlash.JumpResult = 0x30 ; //复位JumpResult标志位
|
||
Set_uIapFlash(&uIapFlash) ; //保存JumpResult
|
||
}
|
||
|
||
/*结束变砖检测修复、强制升级检测*/
|
||
|
||
/*开始检测是否需要升级APP(即判断IapFlag标志位)▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼*/
|
||
if(true == IS_IapFlag_ALL_PERIPH(uIapFlash.sIapFlash.IapFlag)) /*IapFlag合法*/ //IapFlag标志位合法性校验
|
||
{
|
||
if(uIapFlash.sIapFlash.IapFlag == 0x30 ) /*升级标志位为‘0’, 说明不需要升级,直接跳转即可*/
|
||
{
|
||
AppLogPrintf("无需升级,即将执行APP%c .", uIapFlash.sIapFlash.RunAppNum) ;
|
||
|
||
goto APPNUMOUT ; //跳转到RunAppNum,执行原先的程序
|
||
}
|
||
}
|
||
else /*IapFlag不合法*/
|
||
{
|
||
AppLogPrintf("IapFlag=%c,不合法,即将执行APP%c .", uIapFlash.sIapFlash.IapFlag, uIapFlash.sIapFlash.RunAppNum) ;
|
||
uIapFlash.sIapFlash.IapFlag = 0x30 ; //清除升级标志位
|
||
Set_uIapFlash(&uIapFlash) ; //保存升级标志位
|
||
goto APPNUMOUT ; //跳转到RunAppNum,执行原先的程序
|
||
}
|
||
/*检测是否需要升级APP结束▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲*/
|
||
|
||
/*升级APP(连接TCP\FTP下载写入固件,最后跳转APPP)开始▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼*/
|
||
//保存升级标志位
|
||
Watchdog_Feed() ; //看门狗喂狗
|
||
|
||
/*∧∧网络连接开始∧∧∧∧∧∧∧∧∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨*/
|
||
result = NetTask() ; //网络初始化
|
||
if(RUNERR == result) /*TCP\FTP初始化、连接失败 */
|
||
{
|
||
DisplayInfo("FTP连接失败") ;
|
||
TcpUpdata( BOOTTOTCPFRAME, "FTP初始化失败,即将跳转RunAppNum: APP%c!", uIapFlash.sIapFlash.RunAppNum) ;
|
||
Wait_For_Nms(20) ; //延时2S用于显示屏显示(实际项目可以屏蔽延时)
|
||
goto APPNUMOUT ; //跳转到RunAppNum,执行原先的程序
|
||
}
|
||
/*∧∧网络连接结束∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧*/
|
||
|
||
/*∨∨查找新固件开始∨∨∨∨∨∨∨∧∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨*/
|
||
TcpUpdata( BOOTTOTCPFRAME, "FTP初始化成功,即将开始升级!") ;
|
||
Watchdog_Feed() ; //看门狗喂狗
|
||
result = FindAppFile(&sDownApp) ; //查找新固件
|
||
if(RUNERR == result) /*未找到新固件*/
|
||
{
|
||
TcpUpdata( BOOTTOTCPFRAME, "未搜索到新固件,即将跳转RunAppNum: APP%c!", uIapFlash.sIapFlash.RunAppNum) ;
|
||
Wait_For_Nms(200) ; //延时2S用于显示屏显示(实际项目可以屏蔽延时)
|
||
goto APPNUMOUT ; //跳转到RunAppNum,执行原先的程序
|
||
}
|
||
/*∧∧查找新固件结束∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧*/
|
||
|
||
/*∨∨获取新固件文件大小开始∨∨∨∨∨∨∨∧∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨*/
|
||
sDownApp.fileSize = Ftp_Get_FileSize( sDownApp.fileName ) ; //获取新固件文件的大小
|
||
if(sDownApp.fileSize <= 0) /*获取文件大小失败*/
|
||
{
|
||
TcpUpdata( BOOTTOTCPFRAME, "获取新固件大小失败,即将跳转RunAppNum: APP%c!", uIapFlash.sIapFlash.RunAppNum) ;
|
||
goto APPNUMOUT ; //跳转到RunAppNum,执行原先的程序
|
||
}
|
||
sDownApp.subPackSum = sDownApp.fileSize/ONCE_DOWN_LEN ;
|
||
if(sDownApp.fileSize%ONCE_DOWN_LEN > 0)
|
||
sDownApp.subPackSum = sDownApp.subPackSum + 1 ; //计算固件subPackSum
|
||
TcpUpdata( BOOTTOTCPFRAME, "新固件包大小 %d bytes ; 拆分子包数目: %d 。",sDownApp.fileSize, sDownApp.subPackSum) ;
|
||
/*∧∧获取新固件文件大小结束∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧*/
|
||
|
||
/*∨∨新固件合法性校验开始∨∨∨∨∨∨∨∧∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨∨*/
|
||
int headPos = -1 ;
|
||
result = DownSubpackVerify(&sDownApp, &headPos) ; //下载第一个subpack并进行固件合法性校验
|
||
if(RUNERR == result) /*固件校验不合法”*/
|
||
{
|
||
TcpUpdata( BOOTTOTCPFRAME, "新固件栈顶地址校验失败!") ;
|
||
// char *newName = (char*)portMalloc(MAC_BYTES_LEN*2) ;
|
||
// strncat( (char*)newName, (const char*)sDownApp.fileName, 2) ;
|
||
// strncat( (char*)newName, "(BinErr)", 8) ;
|
||
// strncat( (char*)newName, (const char*)&sDownApp.fileName[2], 26) ;
|
||
// Wait_For_Nms(2000) ; //延时2S用于修改文件名(实测发现在下载完数据后立即更名,会返回+CME ERROR: 603错误)
|
||
// Ftp_File_Rename( sDownApp.fileName , (uint8_t *)newName ) ; //对不合法的固件进行重名了, 防止二次升级
|
||
// portFree(newName) ;
|
||
goto APPNUMOUT ; // 跳转到RunAppNum,执行原先的程序
|
||
}
|
||
else if(TIMEOUT == result) /*固件校验失败*/
|
||
{
|
||
TcpUpdata( BOOTTOTCPFRAME, "新固件栈顶地址校验超时!") ;
|
||
Wait_For_Nms(50) ; //延时2S用于显示屏显示(实际项目可以屏蔽延时)
|
||
goto APPNUMOUT ; // 跳转到RunAppNum,执行原先的程序
|
||
}
|
||
/*∧∧新固件合法性校验结束∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧*/
|
||
|
||
|
||
Erase_App_Area(sDownApp.appFlashAddr) ; //擦除相应代码段准备将新的代码写入FLASH,此时该APP段已经不可用了,如果后续出现下载/写入FLASH错误,需要跳转到应急程序
|
||
TcpUpdata( BOOTTOTCPFRAME, "子包:1 。下载成功!") ;
|
||
if( RUNOK == Write_Flash(sDownApp.appFlashAddr, (uint8_t*)(ec20FtpBuf+headPos), ONCE_DOWN_LEN)) /*写FLASH成功*///将上一步下载的subpack1写入falsh中
|
||
{
|
||
TcpUpdata( BOOTTOTCPFRAME, "子包:1 。写入FLASH成功!") ;
|
||
}
|
||
else /*subpack1写入FLASH失败*/
|
||
{
|
||
TcpUpdata( BOOTTOTCPFRAME, "子包:1 。写入FLASH失败!设备即将跳转到应急程序!") ;
|
||
goto SAVEAPPOUT ; //跳转到应急程序
|
||
}
|
||
result = DownOtherSubpack(&sDownApp) ; //下载其余的subpack
|
||
if( RUNOK != result ) //余下subpack下载失败
|
||
{
|
||
Erase_App_Area(sDownApp.appFlashAddr) ; //固件写入FLSHA失败,此APP段已经作废,防止程序异常,需要清除FLASH段
|
||
Wait_For_Nms(50) ; //延时2S用于显示屏显示(实际项目可以屏蔽延时)
|
||
goto SAVEAPPOUT ; //跳转应急程序
|
||
}
|
||
else /*余下所有subpack固件下载成功且写入flash成功*/
|
||
{
|
||
// if( sDownApp.eAppType == SelfApp) /*硬件独有的APP文件升级成功,修改文件名*/
|
||
// {
|
||
// char *newName = (char*)portMalloc(MAC_BYTES_LEN*2) ;
|
||
// strncat( (char*)newName, (const char*)sDownApp.fileName, 2) ;
|
||
// strncat( (char*)newName, "(BinOk)", 8) ;
|
||
// strncat( (char*)newName, (const char*)&sDownApp.fileName[2], 26) ;
|
||
// Wait_For_Nms(2000) ; //延时2S用于显示屏显示(实际项目可以屏蔽延时)
|
||
// Ftp_File_Rename( sDownApp.fileName , (uint8_t *)newName ) ;//对已经升级成功的固件进行重名了, 防止二次升级
|
||
// portFree(newName) ;
|
||
// }
|
||
goto NEWAPPOUT ; //跳转到最新下载的固件的栈顶地址运行APP
|
||
}
|
||
/*∧∧下载新固件并写FLASH 结束∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧∧*/
|
||
|
||
APPNUMOUT:
|
||
appAddr = QueryNewAppArea(0x32); //校验固件合法性、获取跳转的FLASH存放区域首地址
|
||
// appAddr = QueryNewAppArea((u32)uIapFlash.sIapFlash.RunAppNum); //校验固件合法性、获取跳转的FLASH存放区域首地址
|
||
|
||
NetDisconnetc() ; //断开网络连接,注销FTP登陆
|
||
Iap_Load_App(appAddr) ; //执行APP,不会再往下执行了
|
||
|
||
NEWAPPOUT:
|
||
uIapFlash.sIapFlash.IapFlag = 0x32 ; //清除升级标志位
|
||
Set_uIapFlash(&uIapFlash) ;
|
||
appAddr = QueryNewAppArea(sDownApp.appFlashAddr); //校验固件合法性、获取跳转的FLASH存放区域首地址
|
||
NetDisconnetc() ; //断开网络连接,注销FTP登陆
|
||
Iap_Load_App(appAddr) ; //执行APP,不会再往下执行了
|
||
|
||
SAVEAPPOUT:
|
||
appAddr = QueryNewAppArea(SAVEAPP_AREA_ADDR); //校验固件合法性、获取跳转的FLASH存放区域首地址
|
||
NetDisconnetc() ; //断开网络连接,注销FTP登陆
|
||
Iap_Load_App(SAVEAPP_AREA_ADDR) ; //执行APP,不会再往下执行了
|
||
|
||
DisplayTitle("设备故障:") ;
|
||
DisplayInfo("请联系厂家") ;
|
||
Wait_For_Nms(50) ; //理论上程序不可能执行到此处
|
||
SystemSoftReset() ; //软重启
|
||
}
|
||
|
||
RunResult NetTask(void)
|
||
{
|
||
RunResult runResult = TIMEOUT ; //RunResult类型变量,存储函数执行结果
|
||
int tryTimes = 2 ; //网络连接重试次数
|
||
while( tryTimes >= 0 ) //重试条件成立
|
||
{
|
||
tryTimes-- ;
|
||
if( MODULEBIT_0 == false ) /*EC20没有module初始化成功则执行*/
|
||
{
|
||
runResult = EC20_Module_Init() ; //需要保证串口通信正常且关闭模块串口ECHO成功
|
||
if( RUNOK == runResult) /*模块UART \gpio\POW\ECHO\RELESE皆无异常*/
|
||
{
|
||
MODULEBIT_0 = true ; //修改MODULEBIT_0状态标志位
|
||
AppLogPrintf("握手成功") ;
|
||
}
|
||
else /*EC20_Module_Init初始化失败不做异常处理,该任务会一直运行EC20_Module_Init()*/
|
||
{
|
||
AppLogPrintf("握手失败") ;
|
||
}
|
||
}
|
||
|
||
if( (MODULEBIT_0 == true) &&
|
||
(NETREGBIT_1 == false) ) //EC20module初始化完成,且CSPS初始化未完成,则进行CS、PS初始化
|
||
{
|
||
char *errInfo = portMalloc(30) ;
|
||
runResult = EC20_Net_Reg(errInfo, 30) ; //连接运营商核心网,即CS SERVER、PS SERVER
|
||
if( RUNOK == runResult) /*EC20_Net_Reg(SIM/CS/PS)皆无异常*/
|
||
{
|
||
NETREGBIT_1 = true ; //修改NETREGBIT_1状态标志位
|
||
}
|
||
else /*1、EC20_Net_Reg异常,需要重新进行EC20_Module_Init; 2、模块关机*/
|
||
{
|
||
MODULEBIT_0 = false ; //设置MODULEBIT_0状态位为失败
|
||
EC20_CLOSE() ; //EC20关机
|
||
}
|
||
AppLogPrintf(errInfo) ; //提示错误:请插入SIM卡、SIM欠费、CSQ
|
||
portFree(errInfo) ;
|
||
}
|
||
if( (MODULEBIT_0 == true) &&
|
||
(NETREGBIT_1 == true) &&
|
||
(TCPBIT_2 == false) ) /*EC20module、EC20_Net_Reg初始化都完成,则进行AppTcpInit初始化*/
|
||
{
|
||
runResult = AppTcpInit() ; //TCP PDP初始化 SOCKET连接
|
||
if( RUNOK == runResult) /*TCP连接成功*/
|
||
{
|
||
TCPBIT_2 =true ; //设置TCP网络状态标志位TCPBIT_2 STATE_OK
|
||
TcpUpdata( BOOTTOTCPFRAME, "Device tcp connetced!") ; //上传TCP数据,更新服务器硬件客户端列表
|
||
AppLogPrintf("TCP连接成功") ;
|
||
}
|
||
else /*TCP连接失败不影响主业务逻辑,所以TCP异常只做重新初始化,不做异常处理*/
|
||
{
|
||
TCPBIT_2 = false ; //设置TCP网络状态标志位 STATE_ERR
|
||
AppLogPrintf("TCP连接失败") ;
|
||
}
|
||
}
|
||
if( (MODULEBIT_0 == true) &&
|
||
(NETREGBIT_1 == true) &&
|
||
(FTPBIT_4 == false) ) /*EC20module、EC20_Net_Reg初始化都完成,则进行AppFtpInit初始化*/
|
||
{
|
||
DisplayTitle("连接FTP服务器:") ;
|
||
runResult = AppFtpInit() ; //FTP初始化
|
||
if( RUNOK == runResult) //FTP连接成功
|
||
{
|
||
FTPBIT_4 =true ; //设置FTP网络状态标志位FTPBIT_4 STATE_OK
|
||
AppLogPrintf("FTP连接成功") ;
|
||
break ;
|
||
}
|
||
else
|
||
{
|
||
FTPBIT_4 = false ; //设置FTP网络状态标志位 STATE_ERR
|
||
AppLogPrintf("FTP连接失败") ;
|
||
}
|
||
}
|
||
}
|
||
if( (MODULEBIT_0 == true) &&
|
||
(NETREGBIT_1 == true) &&
|
||
(FTPBIT_4 == true ) ) /*EC20module、EC20_Net_Reg、AppFtpInit全部初始化成功(TCP只用于上传日志,AppTcpInit初始化失败不影响升级)*/
|
||
{
|
||
runResult = RUNOK ;
|
||
EC20_Query_CSQ(sEc20Param.csq) ; //获取CSQ的值
|
||
EC20_Query_Voltage(sEc20Param.ec20Voltage) ; //获取EC20电压值
|
||
// DisplayStatusBar() ; //状态栏显示信号质量和电压
|
||
}
|
||
else /*网络初始化存在异常*/
|
||
{
|
||
runResult = RUNERR ;
|
||
}
|
||
return (runResult) ;
|
||
}
|
||
|