/******************************************************************************* * File Name : OTA.c * Description : * Created on : 2020Äê9ÔÂ13ÈÕ * Author : www.hido-studio.com *******************************************************************************/ /******************************************************************************* * Include Files * *******************************************************************************/ #include "string.h" #include "HIDO_TypeDef.h" #include "HIDO_Timer.h" #include "OTA.h" #include "HIDO_Debug.h" #include "HIDO_Timer.h" #include "HIDO_Util.h" #include "HTTPClient.h" #include "Internet.h" #include "mk_flash.h" #include "mk_trace.h" #include #include /******************************************************************************* * Macro * *******************************************************************************/ #define MAX_REQUEST_SIZE (5 * 1024) #define APP2_ADRESS 0x0402f000 //#define APP_SIZE 0x04080000-APP2_ADRESS #define APP_CONFIG_APPLICATION_SIZE 0x19000 //4K¶ÔÆë /******************************************************************************* * Type Definition * *******************************************************************************/ typedef enum { OTA_STATE_IDLE, OTA_STATE_HTTP_REQUEST_FILE_LEN, OTA_STATE_HTTP_REQUEST_DATA, OTA_STATE_WAIT_HTTP_RESPONSE, }E_OTAState; typedef enum { OTA_TYPE_MCU, OTA_TYPE_MUSIC, } E_OTAType; /******************************************************************************* * Local Variable * *******************************************************************************/ static HIDO_UINT8 l_u8OTAType; static HIDO_CHAR l_acOTAUrl[256]; static HIDO_UINT32 l_u32OTATimerID = 0; static volatile E_OTAState l_eOTAState = OTA_STATE_IDLE; static HIDO_UINT32 l_u32OTARetryCnt = 0; static HIDO_UINT32 l_u32OTAFileRecvLen = 0; static HIDO_UINT32 l_u32OTAFileSize = 0; static HIDO_UINT32 l_u32MusicWriteLen = 0; static E_OTAType l_eOTAType = OTA_TYPE_MCU; /******************************************************************************* * Local Function Declaration * *******************************************************************************/ static HIDO_VOID OTA_TimerCallBack(HIDO_VOID *_pArg); static HIDO_INT32 OTA_HTTPGetFileCallBack(HIDO_UINT32 _u32RespCode, ST_HTTPGetFileResponse *_pstResponse, HIDO_UINT8 *_pu8Data, HIDO_UINT32 _u32Len, HIDO_VOID *_pArg); /******************************************************************************* * Local Function * *******************************************************************************/ /******************************************************************************* * Function Name : OTA_RequestFileLen * Description : * Input : * Output : * Return : * Author : www.hido-studio.com * Modified Date: : 2020Äê9ÔÂ13ÈÕ *******************************************************************************/ static HIDO_INT32 OTA_RequestFileLen(HIDO_VOID) { ST_HTTPGetFileOpt stFileOpt; memset(&stFileOpt, 0, sizeof(stFileOpt)); stFileOpt.m_u32RangeBegin = 0; stFileOpt.m_u32RangeEnd = 0; if (HTTPClient_GetFile(l_acOTAUrl, OTA_HTTPGetFileCallBack, &stFileOpt, HIDO_NULL) != HIDO_OK) { return HIDO_ERR; } return HIDO_OK; } /******************************************************************************* * Function Name : OTA_RequestFileData * Description : * Input : * Output : * Return : * Author : www.hido-studio.com * Modified Date: : 2020Äê9ÔÂ13ÈÕ *******************************************************************************/ static HIDO_INT32 OTA_RequestFileData(HIDO_UINT32 _u32Offset) { ST_HTTPGetFileOpt stFileOpt; memset(&stFileOpt, 0, sizeof(stFileOpt)); stFileOpt.m_u32RangeBegin = _u32Offset; if ((l_u32OTAFileSize - l_u32OTAFileRecvLen) < MAX_REQUEST_SIZE) { stFileOpt.m_u32RangeEnd = _u32Offset + l_u32OTAFileSize - l_u32OTAFileRecvLen - 1; } else { stFileOpt.m_u32RangeEnd = _u32Offset + MAX_REQUEST_SIZE - 1; } if(HTTPClient_GetFile(l_acOTAUrl, OTA_HTTPGetFileCallBack, &stFileOpt, HIDO_NULL) != HIDO_OK) { return HIDO_ERR; } return HIDO_OK; } /******************************************************************************* * Function Name : OTA_HTTPGetFileCallBack * Description : * Input : * Output : * Return : * Author : www.hido-studio.com * Modified Date: : 2020Äê9ÔÂ13ÈÕ *******************************************************************************/ uint8_t result1; static HIDO_INT32 OTA_HTTPGetFileCallBack(HIDO_UINT32 _u32RespCode, ST_HTTPGetFileResponse *_pstResponse, HIDO_UINT8 *_pu8Data, HIDO_UINT32 _u32Len, HIDO_VOID *_pArg) { if (200 == _u32RespCode) { LOG_INFO(TRACE_MODULE_APP,"HTTPGetFileCallBack:200\r\n"); } else if (206 == _u32RespCode) { switch (l_eOTAState) { case OTA_STATE_HTTP_REQUEST_FILE_LEN: { l_u32OTAFileRecvLen = 0; l_u32OTAFileSize = _pstResponse->m_u32RangeTotal; if(0 == l_u32OTAFileSize) { LOG_INFO(TRACE_MODULE_APP,"OTAFileSize error\r\n"); } LOG_INFO(TRACE_MODULE_APP,"OTAFileSize %u\r\n", l_u32OTAFileSize); l_eOTAState = OTA_STATE_HTTP_REQUEST_DATA; OTA_RequestFileData(l_u32OTAFileRecvLen); HIDO_TimerStart(l_u32OTATimerID, HIDO_TIMER_TYPE_ONCE, HIDO_TIMER_TICK_S(30), OTA_TimerCallBack, HIDO_NULL); break; } case OTA_STATE_HTTP_REQUEST_DATA: { if(_pstResponse->m_u32RangeBegin != l_u32OTAFileRecvLen) { break; } /* дÈëÎļþ */ #if 0 SPIFlash_Write(SPI_FLASH_ID_0, APP_CONFIG_APP_DOWN_LOAD_SPIFLASH_ADDRESS + l_u32OTAFileRecvLen, _pu8Data, _u32Len); #else flash_write_nbytes(FLASH_ID0, APP2_ADRESS + l_u32OTAFileRecvLen, _pu8Data, _u32Len); #endif l_u32OTAFileRecvLen += _u32Len; LOG_INFO(TRACE_MODULE_APP,"OTAFileDownload %u/%u\r\n", l_u32OTAFileRecvLen, l_u32OTAFileSize); /* Îļþ½ÓÊÕÍê³É */ if (l_u32OTAFileRecvLen == l_u32OTAFileSize) { uint16_t tmp = 0; l_eOTAState = OTA_STATE_IDLE; HIDO_TimerCancel(l_u32OTATimerID); // Ö´Ðе½ÕâÀÒѾ­Íê³ÉÎļþµÄÏÂÔØ£¬¿ÉÒÔÖ´ÐÐÏÂÒ»²½´¦ÀíÁË if (OTA_TYPE_MUSIC == l_eOTAType) { tmp = 0xFFFF; l_u32MusicWriteLen = 0; DATA_CHANGE(); } else { tmp = 0xBBBB; } __disable_irq(); result1=flash_open(FLASH_ID0,NULL); if(!result1) { flash_erase(FLASH_ID0, APP_CONFIG_IAPFLAG_SECTOR_ADDR, FLASH_SECTOR_SIZE);//²Á³ýAPPFLAG flash_write_nbytes(FLASH_ID0, APP_CONFIG_IAPFLAG_MAP, (uint8_t*)&tmp, sizeof(tmp)); flash_erase(FLASH_ID0, APP_CONFIG_IAP_PARAM_MAP, FLASH_SECTOR_SIZE);//²Á³ýAPPFLAG } __enable_irq(); delay_us(1000000); NVIC_SystemReset(); //Èí¸´Î»»Øµ½bootloader break; } OTA_RequestFileData(l_u32OTAFileRecvLen); HIDO_TimerStart(l_u32OTATimerID, HIDO_TIMER_TYPE_ONCE, HIDO_TIMER_TICK_S(30), OTA_TimerCallBack, HIDO_NULL); break; } default: { break; } } } else { // l_eOTAState = OTA_STATE_IDLE; /* ÇëÇóʧ°Ü */ } return HIDO_OK; } HIDO_VOID OTA_GetMusicPackData(HIDO_UINT8 *_pu8Data) { flash_read(FLASH_ID0, APP2_ADRESS + l_u32MusicWriteLen, _pu8Data, 512); l_u32MusicWriteLen += 512; } HIDO_UINT16 OTA_GetMusicPackNum() { if ((l_u32OTAFileSize % 512) != 0) { return (l_u32OTAFileSize / 512) + 1; } else { return l_u32OTAFileSize / 512; } } /******************************************************************************* * Function Name : OTA_Failed * Description : * Input : * Output : * Return : * Author : www.hido-studio.com * Modified Date: : 2020Äê9ÔÂ13ÈÕ *******************************************************************************/ static HIDO_INT32 OTA_Failed(void) { uint16_t tmp = 0xFFFF; __disable_irq(); result1=flash_open(FLASH_ID0,NULL); if(!result1) { flash_erase(FLASH_ID0, APP_CONFIG_IAPFLAG_SECTOR_ADDR, FLASH_SECTOR_SIZE);//²Á³ýAPPFLAG flash_write_nbytes(FLASH_ID0, APP_CONFIG_IAPFLAG_MAP, (uint8_t*)&tmp, sizeof(tmp)); flash_erase(FLASH_ID0, APP_CONFIG_IAP_PARAM_MAP, FLASH_SECTOR_SIZE);//²Á³ýAPPFLAG } __enable_irq(); delay_us(1000000); NVIC_SystemReset(); //Èí¸´Î»»Øµ½bootloader return HIDO_OK; } /******************************************************************************* * Function Name : OTA_TimerCallBack * Description : OTA¶¨Ê±Æ÷³¬Ê±»Øµ÷ * Input : ¶¨Ê±Æ÷²ÎÊý * Output : * Return : * Author : www.hido-studio.com * Modified Date: : 2020Äê9ÔÂ13ÈÕ *******************************************************************************/ static HIDO_VOID OTA_TimerCallBack(HIDO_VOID *_pArg) { LOG_INFO(TRACE_MODULE_APP,"l_eOTAState = %u @%s\r\n", l_eOTAState, __FUNCTION__); switch (l_eOTAState) { case OTA_STATE_HTTP_REQUEST_FILE_LEN: { l_u32OTARetryCnt++; if(l_u32OTARetryCnt >= 3) { OTA_Failed(); } OTA_RequestFileLen(); HIDO_TimerStart(l_u32OTATimerID, HIDO_TIMER_TYPE_ONCE, HIDO_TIMER_TICK_S(30), OTA_TimerCallBack, HIDO_NULL); break; } case OTA_STATE_HTTP_REQUEST_DATA: { l_u32OTARetryCnt++; if(l_u32OTARetryCnt >= 3) { OTA_Failed(); } OTA_RequestFileData(l_u32OTAFileRecvLen); HIDO_TimerStart(l_u32OTATimerID, HIDO_TIMER_TYPE_ONCE, HIDO_TIMER_TICK_S(30), OTA_TimerCallBack, HIDO_NULL); break; } default: { break; } } } /******************************************************************************* * Global Function * *******************************************************************************/ /******************************************************************************* * Function Name : OTA_SetUp * Description : OTAÆô¶¯ * Input : _pcUrl OTAÉý¼¶Îļþ·¾¶ * Output : None * Return : HIDO_OK ³É¹¦,HIDO_ERR ʧ°Ü * Author : www.hido-studio.com * Modified Date: : 2020Äê9ÔÂ13ÈÕ *******************************************************************************/ HIDO_INT32 OTA_SetUp(HIDO_UINT8 _u8Type, HIDO_CHAR *_pcUrl) { if(HIDO_NULL == _pcUrl) { return HIDO_ERR; } if(l_eOTAState != OTA_STATE_IDLE) { return HIDO_ERR; } /* ³õʼ»¯²ÎÊý */ l_u32OTARetryCnt = 0; l_u32OTAFileSize = 0; l_u32OTAFileRecvLen = 0; l_u8OTAType = _u8Type; HIDO_UtilSnprintf(l_acOTAUrl, sizeof(l_acOTAUrl), _pcUrl); /* ²Á³ýOTAÎļþ»º´æ´æ´¢¿Õ¼ä */ if (_u8Type == 0) { l_eOTAType = OTA_TYPE_MCU; flash_erase(FLASH_ID0, APP2_ADRESS, APP_CONFIG_APPLICATION_SIZE); } else { l_eOTAType = OTA_TYPE_MUSIC; } /* ÇëÇóÉý¼¶Îļþ³¤¶È */ if(OTA_RequestFileLen() != HIDO_OK) { return HIDO_ERR; } l_eOTAState = OTA_STATE_HTTP_REQUEST_FILE_LEN; HIDO_TimerStart(l_u32OTATimerID, HIDO_TIMER_TYPE_ONCE, HIDO_TIMER_TICK_S(30), OTA_TimerCallBack, HIDO_NULL); return HIDO_OK; } /******************************************************************************* * Function Name : OTA_Cancel * Description : * Input : * Output : * Return : * Author : www.hido-studio.com * Modified Date: : 2020Äê9ÔÂ13ÈÕ *******************************************************************************/ HIDO_INT32 OTA_Cancel(HIDO_VOID) { HIDO_TimerCancel(l_u32OTATimerID); l_eOTAState = OTA_STATE_IDLE; return HIDO_OK; } /******************************************************************************* * Function Name : OTA_Poll * Description : * Input : * Output : * Return : * Author : www.hido-studio.com * Modified Date: : 2020Äê9ÔÂ13ÈÕ *******************************************************************************/ HIDO_INT32 OTA_Poll(void) { if (Internet_IsIPReady() != HIDO_TRUE) { return HIDO_ERR; } if (l_eOTAState == OTA_STATE_IDLE) { OTA_SetUp(l_u8OTAType, l_acOTAUrl); } return HIDO_OK; } /******************************************************************************* * Function Name : OTA_Start * Description : * Input : * Output : * Return : * Author : www.hido-studio.com * Modified Date: : 2020Äê9ÔÂ13ÈÕ *******************************************************************************/ HIDO_INT32 OTA_Start(HIDO_UINT8 _u8Type, HIDO_CHAR *_pcUrl) { l_eOTAState = OTA_STATE_IDLE; HIDO_TimerCreate(&l_u32OTATimerID); OTA_SetUp(_u8Type, _pcUrl); return HIDO_OK; }