385 lines
16 KiB
C
385 lines
16 KiB
C
#include "userapp.h"
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
|
||
/********************************************************************************
|
||
* @file userapp.c
|
||
* @author 晏诚科技 Mr.Wang
|
||
* @version V1.0.0
|
||
* @date 11-Dec-2018
|
||
* @brief 针对SmartGate应用程序,对所有驱动进行封装
|
||
******************************************************************************
|
||
* @attention
|
||
* 所有对除USER层的封装都放在gateapp中
|
||
*******************************************************************************/
|
||
|
||
|
||
/*********应用层外部调用文件*******************************************************/
|
||
#include "usart.h" //printf
|
||
#include "watchdog.h"
|
||
#include "ec20module.h"
|
||
#include "ec20net.h"
|
||
#include "ec20tcp.h"
|
||
#include "ec20http.h" //RunResult Send_Post( POSTP_s *psHttpP, char* postBody )
|
||
#include "user_key.h"
|
||
#include "sysport.h"
|
||
#include "malloc.h"
|
||
#include "cjson.h"
|
||
#include "rtc.h"
|
||
#include "beep.h"
|
||
#include "led.h"
|
||
#include "logflash.h"
|
||
#include "syslib.h"
|
||
#include "user_oled.h"
|
||
#include "user_ftp.h"
|
||
#include "user_tcp.h"
|
||
#include "user_http.h"
|
||
#include "gate_timer.h"
|
||
#include "usercmd.h"
|
||
#include "logflash.h"
|
||
#include "io.h"
|
||
#include "pvd.h"
|
||
#include "oled.h"
|
||
#include "stm32Temp.h"
|
||
#include "iap.h"
|
||
/**********************************************************************************/
|
||
|
||
/**********************************************************************************
|
||
*内部使用的常变量
|
||
**********************************************************************************/
|
||
|
||
/**********************************************************************************
|
||
*供外部使用的常变量
|
||
***********************************************************************************/
|
||
Application gateApp ; //gateApp存放应用参数
|
||
DownFileP_s sDownApp ; //sDownApp存放下载文件的相关参数的结构体变量
|
||
NETSTATUS_s sNetStatus ; //NETSTATUS_s结构体类型变量反映网络状态
|
||
|
||
/**************************************************************************************************
|
||
* 名 称: void Board_Init(void)
|
||
* 功能说明: 驱动及功能块初始化
|
||
**************************************************************************************************/
|
||
void Board_Init(void)
|
||
{
|
||
SysTick_Init() ; //系统滴答定时器初始化 1ms中断一次 中断内部进行了喂狗操作
|
||
MyMenInit(SRAMIN) ; //动态内存分配初始化
|
||
// Watchdog_Init() ; //延时函数可用,即可开启硬件看门狗
|
||
// RTC_Init(INT_RANK_15) ; //实时时钟初始化
|
||
// PrintfDeviceInfo() ; //UART_DEBUG输出硬件信息
|
||
// Watchdog_Feed() ; //看门狗喂狗
|
||
Gpio_Init(PC, PIN8, GPIO_Mode_Out_PP) ;
|
||
GPIO_WriteBit(GPIOC,PIN8,Bit_SET);
|
||
//KeyInit() ; //初始化KEY按键
|
||
// Led_Init() ; //初始化LED
|
||
//Beep_Init() ; //初始化蜂鸣器
|
||
// OLED_Init() ; //OLED初始化
|
||
// RS232Init(115200) ; //RS232初始化
|
||
// RS485Init(115200) ; //RS485初始化
|
||
// Pvd_Init( EXTI_Trigger_Rising_Falling, INT_RANK_14) ;
|
||
// PWR_PVD_Init() ;
|
||
}
|
||
|
||
/**************************************************************************************************
|
||
* 名 称: RunResult FindAppFile(DownFileP_s *psFileParm)
|
||
* 功能说明: 在sFtpBoot.ftpDirectory目录中查找(文件名为24位MAC地址+.bin)/("CommonApp.bin")的文件,函数将修改结构体变量中的fileName和eAppType
|
||
* 入口参数:
|
||
* @param1 *psFileParm DownFileP_s结构体指针
|
||
* 出口参数:
|
||
* @param1 RUNOK 在目录中能找到新的固件
|
||
* 说 明: ec20AtBuf[EC20_ATBUF_LEN] 320字节, 所以当dir中文件名总字节数大于(EC20_ATBUF_LEN-50)时也会出现查找失败。
|
||
**************************************************************************************************/
|
||
RunResult NetDisconnetc(void)
|
||
{
|
||
RunResult result = RUNOK ;
|
||
if( TCPBIT_2 == true )
|
||
{
|
||
AppLogPrintf("BOOT断开TCP连接") ;
|
||
TcpDisconnetc() ; //断开Socket 去激活TCP链路的PDP
|
||
}
|
||
if( FTPBIT_4 == true )
|
||
{
|
||
AppLogPrintf("BOOT注销FTP登陆!") ;
|
||
result = AppFtpClose() ; //FTP注销
|
||
}
|
||
return result ;
|
||
}
|
||
|
||
/**************************************************************************************************
|
||
* 名 称: RunResult FindAppFile(DownFileP_s *psFileParm)
|
||
* 功能说明: 在sFtpBoot.ftpDirectory目录中查找(文件名为24位MAC地址+.bin)/("CommonApp.bin")的文件,函数将修改结构体变量中的fileName和eAppType
|
||
* 入口参数:
|
||
* @param1 *psFileParm DownFileP_s结构体指针
|
||
* 出口参数:
|
||
* @param1 RUNOK 在目录中能找到新的固件
|
||
* 说 明: ec20AtBuf[EC20_ATBUF_LEN] 320字节, 所以当dir中文件名总字节数大于(EC20_ATBUF_LEN-50)时也会出现查找失败。
|
||
**************************************************************************************************/
|
||
RunResult FindAppFile(DownFileP_s *psFileParm)
|
||
{
|
||
RunResult result = RUNERR ;
|
||
GetDeviceMacAddress(psFileParm->fileName, STRMACID) ;
|
||
strcat((char*)psFileParm->fileName, ".bin") ; //需要获取新固件文件名 (文件名为24位MAC地址+.bin)
|
||
if(RUNOK == Ftp_Find_File( sFtpBoot.ftpDirectory, psFileParm->fileName ) ) //在FTP服务器中查找唯一新固件(文件名为24位MAC地址+.bin)
|
||
{
|
||
psFileParm->eAppType = SelfApp ;
|
||
result = RUNOK ;
|
||
}
|
||
else //在FTP服务器中查找通用新固件(文件名CommonApp.bin)
|
||
{
|
||
memset(psFileParm->fileName, 0, MAC_BYTES_LEN+4+1) ; //清空下载文件的文件名
|
||
strcat((char*)psFileParm->fileName, "App.bin") ; //填充通用升级文件的文件名
|
||
//result= Ftp_Find_File( sFtpBoot.ftpDirectory, psFileParm->fileName ) ; //在FTP服务器中查找通用固件包(文件名:CommonApp.bin)
|
||
if( kmp(ec20AtBuf, (char*)psFileParm->fileName) >= 0 )
|
||
{
|
||
psFileParm->eAppType = CommonApp ;
|
||
result = RUNOK ;
|
||
}
|
||
}
|
||
return (result) ;
|
||
}
|
||
|
||
/**************************************************************************************************
|
||
* 名 称: RunResult DownSubpackVerify(DownFileP_s *psFileParm, int *pHeadPos)
|
||
* 功能说明: 下载第一个子包然后进行固件合法性校验,函数将修改结构体变量中的appFlashAddr(校验方法:BIN文件的前4个字节存放“栈顶地址”:__initial_sp 所对应的就是堆栈的起始地址 这是编译器自动分配的“栈顶地址”)
|
||
* 入口参数:
|
||
* @param1 *psFileParm DownFileP_s结构体指针
|
||
* 出口参数:
|
||
* @param1 RUNOK 固件栈顶地址校验成功
|
||
* @param2 RUNERR 固件栈顶地址校验失败
|
||
* @param3 TIMEOUT 固件下载失败
|
||
* @param4 *pHeadPos 下载数据在ec20FtpBuf中的偏移地址
|
||
**************************************************************************************************/
|
||
RunResult DownSubpackVerify(DownFileP_s *psFileParm, int *pHeadPos)
|
||
{
|
||
RunResult result = RUNERR ;
|
||
*pHeadPos = Ftp_Down_File(psFileParm->fileName, 0, ONCE_DOWN_LEN) ; //下载第一个子包
|
||
if( *pHeadPos >= 0 ) /*下载数据成功*/
|
||
{
|
||
psFileParm->appFlashAddr = Check_AppNum(*(vu32*)((u32)&ec20FtpBuf[*pHeadPos+4])) ; //检查APP中的栈顶地址是否符合APP2\APP3
|
||
if( psFileParm->appFlashAddr != 0) // 固件校验合法
|
||
{
|
||
result = RUNOK ;
|
||
}
|
||
else //固件校验失败
|
||
{
|
||
result = RUNERR ;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
result = TIMEOUT ;
|
||
}
|
||
return (result) ;
|
||
}
|
||
|
||
/**************************************************************************************************
|
||
* 名 称: RunResult DownOtherSubpack(DownFileP_s *psFileParm)
|
||
* 功能说明: 下载新固件除第一个subpack的其余sbupack并写入对应的FLASH段
|
||
* 入口参数:
|
||
* @param1 *psFileParm DownFileP_s结构体指针
|
||
* 出口参数:
|
||
* @param1 RUNOK 固件下载成功且写入FLASH成功
|
||
* @param2 RUNERR 固件下载时存在子包下载失败
|
||
* @param3 TIMEOUT 固件下载时存在子包写入FLASH失败
|
||
**************************************************************************************************/
|
||
RunResult DownOtherSubpack(DownFileP_s *psFileParm)
|
||
{
|
||
int headPos ;
|
||
for( psFileParm->subPackNum = 2; psFileParm->subPackNum <= psFileParm->subPackSum; psFileParm->subPackNum++ ) //从第2个包开始,采用循环下载
|
||
{
|
||
OledPrintf(LINE_LEFT, HIGH_16, LINE4, false, "下载子包:%d", psFileParm->subPackNum ) ;
|
||
Data_Led_Reverse() ;
|
||
Wait_For_Nms(5) ;
|
||
uint16_t downLen = ONCE_DOWN_LEN ; //本次下载数据的长度
|
||
if( psFileParm->subPackNum == psFileParm->subPackSum ) /*下载最后一个包,下载数据长度需要重新计算*/
|
||
{
|
||
downLen = psFileParm->fileSize%ONCE_DOWN_LEN ; //最后一个包的数据长度
|
||
}
|
||
headPos = Ftp_Down_File(psFileParm->fileName, (psFileParm->subPackNum-1)*ONCE_DOWN_LEN, downLen) ; //下载文件
|
||
if( headPos >= 0 ) //子包下载成功
|
||
{
|
||
TcpUpdata( BOOTTOTCPFRAME, "子包:%d 。下载成功!", psFileParm->subPackNum) ;
|
||
if( RUNOK == Write_Flash(psFileParm->appFlashAddr+(psFileParm->subPackNum-1)*ONCE_DOWN_LEN, (uint8_t*)(ec20FtpBuf+headPos), downLen))
|
||
{
|
||
TcpUpdata( BOOTTOTCPFRAME, "子包:%d 。写入FLASH成功!", psFileParm->subPackNum) ;
|
||
}
|
||
else //子包写FLASH失败
|
||
{
|
||
TcpUpdata( BOOTTOTCPFRAME, "子包:%d 。写入FLASH失败!设备即将跳转到应急程序!", psFileParm->subPackNum) ;
|
||
return TIMEOUT ;
|
||
}
|
||
}
|
||
else //子包下载失败
|
||
{
|
||
TcpUpdata( BOOTTOTCPFRAME, "子包:%d 。下载失败!设备即将跳转到应急程序!", psFileParm->subPackNum) ;
|
||
return RUNERR ;
|
||
}
|
||
}
|
||
return (RUNOK) ;
|
||
}
|
||
|
||
|
||
/**************************************************************************************************
|
||
* 名 称: uint32_t Check_AppNum( u32 appNumFlagWord )
|
||
* 功能说明: 检查下载的固件是否合法,并且记录appNum
|
||
* 入口参数:
|
||
* @param1 appNum appNum号或者APP存放的FLASH首地址
|
||
* 出口参数:
|
||
* @param1 flagWord 返回固件应该写入FLASH的开始地址
|
||
* @arg APP2_AREA_ADDR: 下载的固件为APP2,应该写入FLASH内的APP2_AREA_ADDR位置
|
||
* @arg APP3_AREA_ADDR: 下载的固件为APP3,应该写入FLASH内的APP3_AREA_ADDR位置
|
||
* @arg 0: 固件不合法
|
||
**************************************************************************************************/
|
||
uint32_t Check_AppNum( u32 appNumFlagWord )
|
||
{
|
||
uint32_t flagWord = appNumFlagWord & 0xFFFF0000 ;
|
||
if(flagWord >= APP3_AREA_ADDR){
|
||
return APP3_AREA_ADDR ;
|
||
}
|
||
if(flagWord >= APP2_AREA_ADDR){
|
||
return APP2_AREA_ADDR ;
|
||
}
|
||
return 0;
|
||
/*
|
||
switch(flagWord)
|
||
{
|
||
case(APP2_AREA_ADDR & 0xFFFF0000):
|
||
return APP2_AREA_ADDR ;
|
||
|
||
case(APP3_AREA_ADDR & 0xFFFF0000):
|
||
return APP3_AREA_ADDR ;
|
||
default:
|
||
return 0 ;
|
||
}*/
|
||
}
|
||
|
||
/**************************************************************************************************
|
||
* 名 称: void Erase_App_Area(uint32_t appNum)
|
||
* 功能说明: 擦除APP1\APP2\APP3程序存储的FLASH区域
|
||
* 入口参数:
|
||
* @param1 appNum appNum号或者APP存放的FLASH首地址
|
||
**************************************************************************************************/
|
||
void Erase_App_Area(uint32_t appNum)
|
||
{
|
||
FLASH_Status eraseResult ;
|
||
uint8_t pageSum = 0, pageNum = 0 ;
|
||
FLASH_Unlock(); //Flash解锁
|
||
switch(appNum)
|
||
{
|
||
case 0x00000031: case APP1_AREA_ADDR:
|
||
{
|
||
// pageSum = APP1_AREA_SIZE/FLASH_PAGE_SIZE ; //计算出APP1_AREA_SIZE共计占用多少页
|
||
// while(pageSum--)
|
||
// {
|
||
// eraseResult = FLASH_ErasePage(APP1_AREA_ADDR+pageNum*FLASH_PAGE_SIZE) ;
|
||
// pageNum++ ;
|
||
// }
|
||
break ;
|
||
}
|
||
case 0x00000032: case APP2_AREA_ADDR:
|
||
{
|
||
pageSum = APP2_AREA_SIZE/FLASH_PAGE_SIZE ; //计算出APP1_AREA_SIZE共计占用多少页
|
||
while(pageSum--)
|
||
{
|
||
eraseResult = FLASH_ErasePage(APP2_AREA_ADDR+pageNum*FLASH_PAGE_SIZE) ;
|
||
pageNum++ ;
|
||
}
|
||
break ;
|
||
}
|
||
case 0x00000033: case APP3_AREA_ADDR:
|
||
{
|
||
pageSum = APP3_AREA_SIZE/FLASH_PAGE_SIZE ; //计算出APP1_AREA_SIZE共计占用多少页
|
||
while(pageSum--)
|
||
{
|
||
eraseResult = FLASH_ErasePage(APP3_AREA_ADDR+pageNum*FLASH_PAGE_SIZE) ;
|
||
pageNum++ ;
|
||
}
|
||
break ;
|
||
}
|
||
default:
|
||
{
|
||
break ;
|
||
}
|
||
}
|
||
FLASH_Lock(); //Flash上锁
|
||
}
|
||
|
||
/**************************************************************************************************
|
||
* 名 称: void PrintfDeviceInfo(void)
|
||
* 功能说明: DEBUG口输出信息
|
||
**************************************************************************************************/
|
||
void PrintfDeviceInfo(void)
|
||
{
|
||
printf("\r\n**************************************************************" ) ;
|
||
printf("\r\n版权归属 : 晏诚科技 2017/8-2027/8 .\
|
||
\r\n技术支持 : Mr. Wang 13635513618 .") ;
|
||
Query_AppVersion((char*)gateApp.bootVers) ;
|
||
//SetAppVersion(&gateApp, (char*)gateApp.bootVers) ;
|
||
printf("\r\nBoot版本 : %.*s",VERSION_LEN, gateApp.bootVers) ;
|
||
memset(uIapFlash.sIapFlash.BootVers, 0, VERSION_LEN+1) ;
|
||
strncpy((char*)uIapFlash.sIapFlash.BootVers, (const char*)gateApp.bootVers, VERSION_LEN ) ; //清除Boot版本,并写入新的boot版本号
|
||
Set_uIapFlash(&uIapFlash) ; //保存版本号到FLASH中
|
||
GetDeviceMacAddress((uint8_t*)gateApp.macId, STRMACID) ;
|
||
printf("\r\n设备编号 : %.*s", MAC_BYTES_LEN, gateApp.macId) ;
|
||
DeviceRstReason((uint8_t*)gateApp.rstReason, VERSION_LEN) ;
|
||
printf("\r\n重启原因 : %.*s", VERSION_LEN, gateApp.rstReason) ;
|
||
printf("\r\n**************************************************************" ) ;
|
||
}
|
||
|
||
/**************************************************************************************************
|
||
* 名 称: void DeviceRstReason(uint8_t *reason, uint8_t maxLen)
|
||
* 功能说明: 判断硬件重启原因
|
||
**************************************************************************************************/
|
||
void DeviceRstReason(uint8_t *reason, uint8_t maxLen)
|
||
{
|
||
if( SET == RCC_GetFlagStatus( RCC_FLAG_PORRST) )
|
||
{
|
||
strncpy((char*)reason, "重上电启动", maxLen) ;
|
||
}
|
||
if( SET == RCC_GetFlagStatus(RCC_FLAG_SFTRST) )
|
||
{
|
||
strncpy((char*)reason, "软复位启动", maxLen) ;
|
||
}
|
||
if( SET == RCC_GetFlagStatus(RCC_FLAG_IWDGRST) )
|
||
{
|
||
strncpy((char*)reason, "独立看门狗启动", maxLen) ;
|
||
}
|
||
if( SET == RCC_GetFlagStatus(RCC_FLAG_WWDGRST) )
|
||
{
|
||
strncpy((char*)reason, "窗口看门狗启动", maxLen) ;
|
||
}
|
||
if( (RESET == RCC_GetFlagStatus(RCC_FLAG_SFTRST)) &&
|
||
(RESET == RCC_GetFlagStatus(RCC_FLAG_IWDGRST)) &&
|
||
(RESET == RCC_GetFlagStatus(RCC_FLAG_WWDGRST)) &&
|
||
(SET == RCC_GetFlagStatus(RCC_FLAG_PINRST))
|
||
)
|
||
{
|
||
strncpy((char*)reason, "硬复位启动", maxLen) ;
|
||
}
|
||
RCC_ClearFlag() ;
|
||
}
|
||
|
||
/**************************************************************************************************
|
||
* 名 称: void InitApplictationState(Application *appPointer)
|
||
* 功能说明: 对Application类型数据进行初始化
|
||
* 入口参数: @param *appPointer Application结构指针
|
||
*************************************************************************************************/
|
||
void InitApplictationState(Application *appPointer)
|
||
{
|
||
memset(appPointer->appVers, 0, VERSION_LEN+1) ;
|
||
memset(appPointer->bootVers, 0, VERSION_LEN+1) ;
|
||
memset(appPointer->macId, 0, MAC_BYTES_LEN+1) ;
|
||
}
|
||
|
||
|
||
void SetAppVersion(Application *appPointer, char *version)
|
||
{
|
||
strncpy((char*)appPointer->appVers, version, VERSION_LEN) ;
|
||
*(appPointer->appVers+VERSION_LEN+1) = 0 ;
|
||
}
|
||
|
||
void SetBootVersion(Application *appPointer, char *version)
|
||
{
|
||
strncpy((char*)appPointer->bootVers, version, VERSION_LEN) ;
|
||
*(appPointer->bootVers+VERSION_LEN+1) = 0 ;
|
||
}
|