/******************************************************************************* * 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 /******************************************************************************* * 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; /******************************************************************************* * Local Variable * *******************************************************************************/ 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; /******************************************************************************* * 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ÈÕ *******************************************************************************/ 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) { l_eOTAState = OTA_STATE_IDLE; HIDO_TimerCancel(l_u32OTATimerID); // Ö´Ðе½ÕâÀÒѾ­Íê³ÉÎļþµÄÏÂÔØ£¬¿ÉÒÔÖ´ÐÐÏÂÒ»²½´¦ÀíÁË //#if 0 // HIDO_UINT16 tmp = 0xBBBB,result; // SPIFlash_Erase(SPI_FLASH_ID_0, APP_CONFIG_IAPFLAG_MAP,2, SPI_FLASH_SECTOR_ERASE_MODE_4K); // SPIFlash_Write(SPI_FLASH_ID_0, APP_CONFIG_IAPFLAG_MAP, (HIDO_UINT8*)&tmp, sizeof(tmp)); //#endif // HAL_Delay(10); // Reboot(0); uint32_t result = 0; uint16_t tmp = 0xCCCC; __disable_irq(); result = flash_open(FLASH_ID0,NULL); if(!result)//´ò¿ª³É¹¦ flash_erase(FLASH_ID0,APP_CONFIG_IAPFLAG_SECTOR_ADDR,FLASH_SECTOR_SIZE); result = flash_write_nbytes(FLASH_ID0,APP_CONFIG_IAPFLAG_MAP,(uint8_t*)&tmp,2); __enable_irq(); Serial0PutString("½øÈëÉý¼¶Ä£Ê½\r\n"); g_com_map[CNT_UPDATE]=0; save_com_map_to_flash(); delay_us(100000); 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; } /******************************************************************************* * Function Name : OTA_Failed * Description : * Input : * Output : * Return : * Author : www.hido-studio.com * Modified Date: : 2020Äê9ÔÂ13ÈÕ *******************************************************************************/ static HIDO_INT32 OTA_Failed(void) { /* Éý¼¶²ÎÊýÓÐÎó£¬È¡ÏûÉý¼¶ */ HIDO_UINT16 tmp = 0xFFFF; // HIDO_Debug("goto app application\r\n"); // Ö´Ðе½ÕâÀ˵Ã÷ÎļþÏÂÔØÊ§°ÜÁË£¬ÐèÒª½øÒ»²½´¦Àí #if 0 SPIFlash_Erase(SPI_FLASH_ID_0, APP_CONFIG_IAPFLAG_MAP, 2, SPI_FLASH_SECTOR_ERASE_MODE_4K); SPIFlash_Write(SPI_FLASH_ID_0, APP_CONFIG_IAPFLAG_MAP, (HIDO_UINT8*)&tmp, sizeof(tmp)); SPIFlash_Erase(SPI_FLASH_ID_0, APP_CONFIG_IAP_PARAM_MAP, 256, SPI_FLASH_SECTOR_ERASE_MODE_4K); #endif // g_com_map[OTA_FLAG]=0; // save_com_map_to_flash(); // delay_us(100000); 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_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; HIDO_UtilSnprintf(l_acOTAUrl, sizeof(l_acOTAUrl), _pcUrl); /* ²Á³ýOTAÎļþ»º´æ´æ´¢¿Õ¼ä */ #if 0 SPIFlash_Erase(SPI_FLASH_ID_0, APP_CONFIG_APP_DOWN_LOAD_SPIFLASH_ADDRESS, APP_CONFIG_APP_DOWN_LOAD_SPIFLASH_SIZE, SPI_FLASH_SECTOR_ERASE_MODE_64K); #else flash_erase(FLASH_ID0,APP2_ADRESS,APP_SIZE); #endif /* ÇëÇóÉý¼¶Îļþ³¤¶È */ 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_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_CHAR *_pcUrl) { l_eOTAState = OTA_STATE_IDLE; HIDO_TimerCreate(&l_u32OTATimerID); OTA_SetUp(_pcUrl); return HIDO_OK; }