diff --git a/RTL00_SDKV35a/component/common/example/example_entry.c b/RTL00_SDKV35a/component/common/example/example_entry.c index f2fddb7..6be1629 100644 --- a/RTL00_SDKV35a/component/common/example/example_entry.c +++ b/RTL00_SDKV35a/component/common/example/example_entry.c @@ -6,10 +6,15 @@ ******************************************************************************/ #include #include "main.h" +#include "freertos_pmu.h" #if ATCMD_VER == ATVER_2 #include "flash_api.h" #include "device_lock.h" +#ifdef USE_FLASH_EEP +#include "flash_eep.h" +#include "feep_config.h" +#endif #endif #if CONFIG_EXAMPLE_MDNS @@ -189,15 +194,19 @@ */ void pre_example_entry(void) { +#if CONFIG_EXAMPLE_WLAN_FAST_CONNECT #if ATCMD_VER == ATVER_2 flash_t flash; struct wlan_fast_reconnect read_data = {0}; +#ifdef USE_FLASH_EEP + flash_read_cfg(data, FEEP_ID_WIFI_CFG, sizeof(struct wlan_fast_reconnect)); +#else device_mutex_lock(RT_DEV_LOCK_FLASH); - flash_stream_read(&flash, FAST_RECONNECT_DATA, sizeof(struct wlan_fast_reconnect), (u8 *) &read_data); + flash_stream_read(&flash, FAST_RECONNECT_DATA, sizeof(read_data), (u8 *) &read_data); device_mutex_unlock(RT_DEV_LOCK_FLASH); #endif +#endif -#if CONFIG_EXAMPLE_WLAN_FAST_CONNECT #if ATCMD_VER == ATVER_2 if(read_data.enable == 1) #endif diff --git a/RTL00_SDKV35a/component/os/freertos/freertos_pmu.h b/RTL00_SDKV35a/component/os/freertos/freertos_pmu.h index 2524fe2..258e9ac 100644 --- a/RTL00_SDKV35a/component/os/freertos/freertos_pmu.h +++ b/RTL00_SDKV35a/component/os/freertos/freertos_pmu.h @@ -117,5 +117,7 @@ void set_pll_reserved(unsigned char reserve); #define pmu_release_wakelock release_wakelock #define pmu_acquire_wakelock acquire_wakelock #define pmu_get_wakelock_status get_wakelock_status +#define pmu_set_pll_reserved set_pll_reserved +#define pmu_enable_wakelock_stats #endif diff --git a/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/hal_api.h b/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/hal_api.h index c50b6e7..a73106a 100644 --- a/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/hal_api.h +++ b/RTL00_SDKV35a/component/soc/realtek/8195a/fwlib/hal_api.h @@ -3,8 +3,6 @@ * * Copyright (c) 2013 Realtek Semiconductor Corp. * - * This module is a confidential and proprietary property of RealTek and - * possession or use of this module requires written permission of RealTek. */ #ifndef _HAL_API_H_ #define _HAL_API_H_ @@ -32,7 +30,7 @@ #define HAL_WRITE8(base, addr, value) \ ((*((volatile u8*)(base + addr))) = value) -#if 0 +#if 1 // These "extern _LONG_CALL_" function declaration are for RAM code building only // For ROM code building, thses code should be marked off extern _LONG_CALL_ u8 @@ -86,6 +84,49 @@ extern _LONG_CALL_ VOID VectorIrqDisRtl8195A( IN PIRQ_HANDLE pIrqHandle ); + +extern _LONG_CALL_ int HalUart0PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalUart1PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalUart2PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalSPI0PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalSPI1PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalSPI2PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalSPI0MCSPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalI2C0PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalI2C1PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalI2C2PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalI2C3PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalI2S0PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalI2S1PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalPCM0PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalPCM1PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalSDIODPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalSDIOHPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalMIIPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalWLLEDPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalWLANT0PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalWLANT1PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalWLBTCOEXPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalWLBTCMDPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalNFCPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalPWM0PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalPWM1PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalPWM2PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalPWM3PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalETE0PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalETE1PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalETE2PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalETE3PinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalEGTIMPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalSPIFlashPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalSDRPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalJTAGPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalTRACEPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalLOGUartPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalLOGUartIRPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalSICPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalEEPROMPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); +extern _LONG_CALL_ int HalDEBUGPinCtrlRtl8195A(IN u32 PinLocation, IN BOOL Operation); #endif extern BOOLEAN SpicFlashInitRtl8195A(u8 SpicBitMode); diff --git a/RTL00_SDKV35a/component/soc/realtek/8195a/misc/platform/gcc_wrap.c b/RTL00_SDKV35a/component/soc/realtek/8195a/misc/platform/gcc_wrap.c new file mode 100644 index 0000000..795a03e --- /dev/null +++ b/RTL00_SDKV35a/component/soc/realtek/8195a/misc/platform/gcc_wrap.c @@ -0,0 +1,22 @@ +/************************************************** + * malloc/free/realloc wrap for gcc compiler + * + **************************************************/ +#if defined(__GNUC__) +#include "FreeRTOS.h" + +void* __wrap_malloc( size_t size ) +{ + return pvPortMalloc(size); +} + +void* __wrap_realloc( void *p, size_t size ) +{ + return pvPortReAalloc(p, size); +} + +void __wrap_free( void *p ) +{ + vPortFree(p); +} +#endif \ No newline at end of file diff --git a/RTL00_SDKV35a/component/soc/realtek/8195a/misc/platform/ota_8195a.c b/RTL00_SDKV35a/component/soc/realtek/8195a/misc/platform/ota_8195a.c new file mode 100644 index 0000000..83b514d --- /dev/null +++ b/RTL00_SDKV35a/component/soc/realtek/8195a/misc/platform/ota_8195a.c @@ -0,0 +1,825 @@ +#include +#include +#include "ota_8195a.h" +#include "lwip/netdb.h" + +sys_thread_t TaskOTA = NULL; +#define STACK_SIZE 1024 +#define TASK_PRIORITY tskIDLE_PRIORITY + 1 +#if SWAP_UPDATE +static uint32_t OldImg2Addr; +#endif +static flash_t flash_ota; + +#if CONFIG_CUSTOM_SIGNATURE +/* --------------------------------------------------- + * Customized Signature + * ---------------------------------------------------*/ +// This signature can be used to verify the correctness of the image +// It will be located in fixed location in application image +#include "section_config.h" +SECTION(".custom.validate.rodata") +const unsigned char cus_sig_demo[32] = "Customer Signature-modelxxx"; +#endif + +void* update_malloc(unsigned int size){ + return pvPortMalloc(size); +} + +void update_free(void *buf){ + vPortFree(buf); +} + +void ota_platform_reset(void){ + // Set processor clock to default before system reset + HAL_WRITE32(SYSTEM_CTRL_BASE, 0x14, 0x00000021); + osDelay(100); + + // Cortex-M3 SCB->AIRCR + HAL_WRITE32(0xE000ED00, 0x0C, (0x5FA << 16) | // VECTKEY + (HAL_READ32(0xE000ED00, 0x0C) & (7 << 8)) | // PRIGROUP + (1 << 2)); // SYSRESETREQ + while(1) osDelay(1000); +} + +#if WRITE_OTA_ADDR +int write_ota_addr_to_system_data(flash_t *flash, uint32_t ota_addr) +{ + uint32_t data, i = 0; + //Get upgraded image 2 addr from offset + device_mutex_lock(RT_DEV_LOCK_FLASH); + flash_read_word(flash, OFFSET_DATA, &data); + printf("\n\r[%s] data 0x%x ota_addr 0x%x", __FUNCTION__, data, ota_addr); + if(~0x0 == data){ + flash_write_word(flash, OFFSET_DATA, ota_addr); + } + else{ + //erase backup sector + flash_erase_sector(flash, BACKUP_SECTOR); + //backup system data to backup sector + for(i = 0; i < 0x1000; i+= 4){ + flash_read_word(flash, OFFSET_DATA + i, &data); + if(0 == i) + data = ota_addr; + flash_write_word(flash, BACKUP_SECTOR + i,data); + } + //erase system data + flash_erase_sector(flash, OFFSET_DATA); + //write data back to system data + for(i = 0; i < 0x1000; i+= 4){ + flash_read_word(flash, BACKUP_SECTOR + i, &data); + flash_write_word(flash, OFFSET_DATA + i,data); + } + //erase backup sector + flash_erase_sector(flash, BACKUP_SECTOR); + } + device_mutex_unlock(RT_DEV_LOCK_FLASH); + return 0; +} +#endif + +int update_ota_connect_server(int server_socket, update_cfg_local_t *cfg){ + struct sockaddr_in server_addr; + + server_socket = socket(AF_INET, SOCK_STREAM, 0); + if(server_socket < 0){ + printf("\n\r[%s] Create socket failed", __FUNCTION__); + return -1; + } + + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = cfg->ip_addr; + server_addr.sin_port = cfg->port; + + if(connect(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1){ + printf("\n\r[%s] Socket connect failed", __FUNCTION__); + return -1; + } + + return server_socket; +} + +uint32_t update_ota_prepare_addr(void){ + + uint32_t Img2Len = 0; + uint32_t IMAGE_x = 0, ImgxLen = 0, ImgxAddr = 0; + uint32_t NewImg2Addr = 0; +#if WRITE_OTA_ADDR + uint32_t ota_addr = 0x80000; +#endif + + DBG_INFO_MSG_OFF(_DBG_SPI_FLASH_); + // The upgraded image2 pointer must 4K aligned and should not overlap with Default Image2 + device_mutex_lock(RT_DEV_LOCK_FLASH); + flash_read_word(&flash_ota, IMAGE_2, &Img2Len); + IMAGE_x = IMAGE_2 + Img2Len + 0x10; + flash_read_word(&flash_ota, IMAGE_x, &ImgxLen); + flash_read_word(&flash_ota, IMAGE_x+4, &ImgxAddr); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + + if(0x30000000 == ImgxAddr){ + printf("\n\r[%s] IMAGE_3 0x%x Img3Len 0x%x", __FUNCTION__, IMAGE_x, ImgxLen); + } + else{ + printf("\n\r[%s] There is no IMAGE_3", __FUNCTION__); + IMAGE_x = IMAGE_2; + ImgxLen = Img2Len; + } +#if WRITE_OTA_ADDR + if((ota_addr > IMAGE_x) && ((ota_addr < (IMAGE_x+ImgxLen))) || (ota_addr < IMAGE_x) || + ((ota_addr & 0xfff) != 0) || (ota_addr == ~0x0)){ + printf("\n\r[%s] illegal ota addr 0x%x", __FUNCTION__, ota_addr); + return -1; + } + else + write_ota_addr_to_system_data(&flash_ota, ota_addr); +#endif + + //Get upgraded image 2 addr from offset + device_mutex_lock(RT_DEV_LOCK_FLASH); + flash_read_word(&flash_ota, OFFSET_DATA, &NewImg2Addr); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + if((NewImg2Addr > IMAGE_x) && ((NewImg2Addr < (IMAGE_x+ImgxLen))) || (NewImg2Addr < IMAGE_x) || + ((NewImg2Addr & 0xfff) != 0) || (NewImg2Addr == ~0x0)){ + printf("\n\r[%s] Invalid OTA Address 0x%x", __FUNCTION__, NewImg2Addr); + return -1; + } + + return NewImg2Addr; +} + +#if SWAP_UPDATE +uint32_t update_ota_swap_addr(uint32_t img_len, uint32_t NewImg2Addr){ + uint32_t SigImage0,SigImage1; + uint32_t Part1Addr=0xFFFFFFFF, Part2Addr=0xFFFFFFFF; + device_mutex_lock(RT_DEV_LOCK_FLASH); + flash_read_word(&flash_ota, 0x18, &Part1Addr); + Part1Addr = (Part1Addr&0xFFFF)*1024; //PART1 : 0x0000B000 + Part2Addr = NewImg2Addr; //PART2 : 0x00080000 + + // read Part1 signature + flash_read_word(&flash_ota, Part1Addr+8, &SigImage0); + flash_read_word(&flash_ota, Part1Addr+12, &SigImage1); + printf("\n\r[%s] Part1 Sig %x", __FUNCTION__, SigImage0); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + if(SigImage0==0x35393138 && SigImage1==0x31313738)//Part1 is the new one with signature "81958711" + OldImg2Addr = Part1Addr; //Change Part1 to older version + else{ + // read Part2 signature + device_mutex_lock(RT_DEV_LOCK_FLASH); + flash_read_word(&flash_ota, Part2Addr+8, &SigImage0); + flash_read_word(&flash_ota, Part2Addr+12, &SigImage1); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + printf("\n\r[%s] Part2 Sig %x", __FUNCTION__, SigImage0); + if(SigImage0==0x30303030 && SigImage1==0x30303030){// ATSC signature "00000000" + OldImg2Addr = Part1Addr; //Store the new version to Part2 + } + else if(SigImage0==0x35393138 && SigImage1==0x31313738){//Part2 is the new one with signature "81958711" + OldImg2Addr = Part2Addr; //Change Part2 to older version + NewImg2Addr = Part1Addr; + if( img_len > (Part2Addr-Part1Addr) ){ // firmware size too large + printf("\n\r[%s] Part1 size < OTA size", __FUNCTION__); + return -1; + } + } + else + NewImg2Addr = Part2Addr; + } + + printf("\n\r[%s] New %x, Old %x", __FUNCTION__, NewImg2Addr, OldImg2Addr); + return NewImg2Addr; +} +#endif + +int update_ota_erase_upg_region(uint32_t img_len, uint32_t NewImg2Len, uint32_t NewImg2Addr){ + uint32_t NewImg2BlkSize = 0; + + if(NewImg2Len == 0){ + NewImg2Len = img_len; + printf("\n\r[%s] NewImg2Len %d ", __FUNCTION__, NewImg2Len); + if((int)NewImg2Len > 0){ + NewImg2BlkSize = ((NewImg2Len - 1)/4096) + 1; + printf("\n\r[%s] NewImg2BlkSize %d 0x%8x", __FUNCTION__, NewImg2BlkSize, NewImg2BlkSize); + device_mutex_lock(RT_DEV_LOCK_FLASH); + for(int i = 0; i < NewImg2BlkSize; i++) + flash_erase_sector(&flash_ota, NewImg2Addr + i * 4096); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + }else{ + printf("\n\r[%s] Size INVALID", __FUNCTION__); + return -1; + } + } + + printf("\n\r[%s] NewImg2Addr 0x%x", __FUNCTION__, NewImg2Addr); + return NewImg2Len; +} + +int update_ota_checksum(_file_checksum *file_checksum, uint32_t flash_checksum, uint32_t NewImg2Addr){ + +#if CONFIG_CUSTOM_SIGNATURE + char custom_sig[32] = "Customer Signature-modelxxx"; + uint32_t read_custom_sig[8]; + + device_mutex_lock(RT_DEV_LOCK_FLASH); + for(int i = 0; i < 8; i ++){ + flash_read_word(&flash_ota, NewImg2Addr + 0x28 + i *4, read_custom_sig + i); + } + device_mutex_unlock(RT_DEV_LOCK_FLASH); + printf("\n\r[%s] read_custom_sig %s", __FUNCTION__ , (char*)read_custom_sig); +#endif + + printf("\n\rflash checksum 0x%8x attached checksum 0x%8x", flash_checksum, file_checksum->u); + + // compare checksum with received checksum + if( (file_checksum->u == flash_checksum) +#if CONFIG_CUSTOM_SIGNATURE + && !strcmp((char*)read_custom_sig,custom_sig) +#endif + ){ + //Set signature in New Image 2 addr + 8 and + 12 + uint32_t sig_readback0,sig_readback1; + device_mutex_lock(RT_DEV_LOCK_FLASH); + flash_write_word(&flash_ota,NewImg2Addr + 8, 0x35393138); + flash_write_word(&flash_ota,NewImg2Addr + 12, 0x31313738); + flash_read_word(&flash_ota, NewImg2Addr + 8, &sig_readback0); + flash_read_word(&flash_ota, NewImg2Addr + 12, &sig_readback1); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + printf("\n\r[%s] signature %x,%x", __FUNCTION__ , sig_readback0, sig_readback1); +#if SWAP_UPDATE + if(OldImg2Addr != ~0x0){ + device_mutex_lock(RT_DEV_LOCK_FLASH); + flash_write_word(&flash_ota,OldImg2Addr + 8, 0x35393130); + flash_write_word(&flash_ota,OldImg2Addr + 12, 0x31313738); + flash_read_word(&flash_ota, OldImg2Addr + 8, &sig_readback0); + flash_read_word(&flash_ota, OldImg2Addr + 12, &sig_readback1); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + printf("\n\r[%s] old signature %x,%x", __FUNCTION__ , sig_readback0, sig_readback1); + } +#endif + printf("\n\r[%s] Update OTA success!", __FUNCTION__); + return 0; + } + return -1; +} + +static void update_ota_local_task(void *param) +{ + int server_socket; + unsigned char *buf, *alloc; + _file_checksum *file_checksum; + int read_bytes = 0, size = 0, i = 0; + update_cfg_local_t *cfg = (update_cfg_local_t *)param; + uint32_t address, flash_checksum=0; + uint32_t NewImg2Len = 0, NewImg2Addr = 0, file_info[3]; + int ret = -1 ; + + printf("\n\r[%s] Update task start", __FUNCTION__); + alloc = update_malloc(BUF_SIZE+4); + if(!alloc){ + printf("\n\r[%s] Alloc buffer failed", __FUNCTION__); + goto update_ota_exit; + } + buf = &alloc[4]; + file_checksum = (void*)alloc; + + // Connect server + server_socket = update_ota_connect_server(server_socket, cfg); + if(server_socket == -1){ + goto update_ota_exit; + } + + NewImg2Addr = update_ota_prepare_addr(); + if(NewImg2Addr == -1){ + goto update_ota_exit; + } + + //Clear file_info + memset(file_info, 0, sizeof(file_info)); + + if(file_info[0] == 0){ + printf("\n\r[%s] Read info first", __FUNCTION__); + read_bytes = read(server_socket, file_info, sizeof(file_info)); + // !X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X + // !W checksum !W padding 0 !W file size !W + // !X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X + printf("\n\r[%s] info %d bytes", __FUNCTION__, read_bytes); + printf("\n\r[%s] tx chechsum 0x%x, file size 0x%x", __FUNCTION__, file_info[0],file_info[2]); + if(file_info[2] == 0){ + printf("\n\r[%s] No checksum and file size", __FUNCTION__); + goto update_ota_exit; + } + } + +#if SWAP_UPDATE + NewImg2Addr = update_ota_swap_addr(file_info[2], NewImg2Addr); + if(NewImg2Addr == -1){ + goto update_ota_exit; + } +#endif + + NewImg2Len = update_ota_erase_upg_region(file_info[2], NewImg2Len, NewImg2Addr); + if(NewImg2Len == -1){ + goto update_ota_exit; + } + + // reset + file_checksum->u = 0; + // Write New Image 2 sector + if(NewImg2Addr != ~0x0){ + address = NewImg2Addr; + printf("\n\rStart to read data %d bytes\r\n", NewImg2Len); + while(1){ + memset(buf, 0, BUF_SIZE); + read_bytes = read(server_socket, buf, BUF_SIZE); + if(read_bytes == 0) + break; // Read end + if(read_bytes < 0){ + printf("\n\r[%s] Read socket failed", __FUNCTION__); + goto update_ota_exit; + } + + if(read_bytes<4) + printf("\n\r[%s] Recv small packet", __FUNCTION__); + printf("."); + + if((size+read_bytes)>NewImg2Len){ + printf("\n\r[%s] Redundant bytes received", __FUNCTION__); + read_bytes = NewImg2Len-size; + } + + device_mutex_lock(RT_DEV_LOCK_FLASH); + if(flash_stream_write(&flash_ota, address + size, read_bytes, buf) < 0){ + printf("\n\r[%s] Write stream failed", __FUNCTION__); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + goto update_ota_exit; + } + device_mutex_unlock(RT_DEV_LOCK_FLASH); + size += read_bytes; + + file_checksum->c[0] = alloc[4+read_bytes-4]; // checksum attached at file end + file_checksum->c[1] = alloc[4+read_bytes-3]; + file_checksum->c[2] = alloc[4+read_bytes-2]; + file_checksum->c[3] = alloc[4+read_bytes-1]; + + if(size == NewImg2Len) + break; + } + printf("\n\rRead data finished\r\n"); + + // read flash data back and calculate checksum + for(i = 0; i < size-4; i += BUF_SIZE){ + int k; + int rlen = (size-4-i) > BUF_SIZE ? BUF_SIZE : (size-4-i); + flash_stream_read(&flash_ota, NewImg2Addr+i, rlen, buf); + for(k = 0; k < rlen; k++) + flash_checksum+=buf[k]; + } + + ret = update_ota_checksum(file_checksum, flash_checksum, NewImg2Addr); + if(ret == -1){ + printf("\r\nThe checksume is wrong!\r\n"); + goto update_ota_exit; + } + } +update_ota_exit: + if(alloc) + update_free(alloc); + if(server_socket >= 0) + close(server_socket); + if(param) + update_free(param); + TaskOTA = NULL; + printf("\n\r[%s] Update task exit", __FUNCTION__); + if(!ret){ + printf("\n\r[%s] Ready to reboot", __FUNCTION__); + ota_platform_reset(); + } + vTaskDelete(NULL); + return; +} + +int update_ota_local(char *ip, int port){ + update_cfg_local_t *pUpdateCfg; + + if(TaskOTA){ + printf("\n\r[%s] Update task has created.", __FUNCTION__); + return 0; + } + pUpdateCfg = update_malloc(sizeof(update_cfg_local_t)); + if(pUpdateCfg == NULL){ + printf("\n\r[%s] Alloc update cfg failed", __FUNCTION__); + return -1; + } + pUpdateCfg->ip_addr = inet_addr(ip); + pUpdateCfg->port = ntohs(port); + + if(xTaskCreate(update_ota_local_task, "OTA_server", STACK_SIZE, pUpdateCfg, TASK_PRIORITY, &TaskOTA) != pdPASS){ + update_free(pUpdateCfg); + printf("\n\r[%s] Create update task failed", __FUNCTION__); + } + return 0; +} + +void cmd_update(int argc, char **argv){ + int port; + if(argc != 3){ + printf("\n\r[%s] Usage: update IP PORT", __FUNCTION__); + return; + } + port = atoi(argv[2]); + update_ota_local(argv[1], port); +} + +void cmd_ota_image(bool cmd){ + flash_t flash; + uint32_t Part1Addr = 0xFFFFFFFF,Part2Addr = 0xFFFFFFFF; + uint8_t *pbuf = NULL; + + device_mutex_lock(RT_DEV_LOCK_FLASH); + flash_read_word(&flash, 0x18, &Part1Addr); + Part1Addr = (Part1Addr&0xFFFF)*1024; // first partition + flash_read_word(&flash, OFFSET_DATA, &Part2Addr); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + + if(Part2Addr == ~0x0) + return; + + pbuf = update_malloc(FLASH_SECTOR_SIZE); + if(!pbuf) return; + + device_mutex_lock(RT_DEV_LOCK_FLASH); + flash_stream_read(&flash, Part2Addr, FLASH_SECTOR_SIZE, pbuf); + if (cmd == 1) + memcpy((char*)pbuf+8, "81958711", 8); + else + memcpy((char*)pbuf+8, "01958711", 8); + + flash_erase_sector(&flash, Part2Addr); + flash_stream_write(&flash, Part2Addr, FLASH_SECTOR_SIZE, pbuf); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + +#if SWAP_UPDATE + device_mutex_lock(RT_DEV_LOCK_FLASH); + flash_stream_read(&flash, Part1Addr, FLASH_SECTOR_SIZE, pbuf); + if (cmd == 1) + memcpy((char*)pbuf+8, "01958711", 8); + else + memcpy((char*)pbuf+8, "81958711", 8); + + flash_erase_sector(&flash, Part1Addr); + flash_stream_write(&flash, Part1Addr, FLASH_SECTOR_SIZE, pbuf); + device_mutex_unlock(RT_DEV_LOCK_FLASH); +#endif + update_free(pbuf); +} + +#ifdef HTTP_OTA_UPDATE +/****************************************************************************************************************** +** Function Name : update_ota_http_connect_server +** Description : connect to the OTA server +** Input : server_socket: the socket used +** host: host address of the OTA server +** port: port of the OTA server +** Return : connect ok: socket value +** Failed: -1 +*******************************************************************************************************************/ +int update_ota_http_connect_server(int server_socket, char *host, int port){ + struct sockaddr_in server_addr; + struct hostent *server; + + server_socket = socket(AF_INET, SOCK_STREAM, 0); + if(server_socket < 0){ + printf("\n\r[%s] Create socket failed", __FUNCTION__); + return -1; + } + + server = gethostbyname(host); + if(server == NULL){ + printf("[ERROR] Get host ip failed\n"); + return -1; + } + + memset(&server_addr,0,sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + memcpy(&server_addr.sin_addr.s_addr,server->h_addr,server->h_length); + + if (connect(server_socket,(struct sockaddr *)&server_addr, sizeof(server_addr)) < 0){ + printf("\n\r[%s] Socket connect failed", __FUNCTION__); + return -1; + } + + return server_socket; +} + +/****************************************************************************************************************** +** Function Name : parse_http_response +** Description : Parse the http response to get some useful parameters +** Input : response : The http response got from server +** response_len: The length of http response +** result : The struct that store the usful infor about the http response +** Return : Parse OK: 1 -> Only got the status code +** 3 -> Got the status code and content_length, but didn't get the full header +** 4 -> Got all the information needed +** Failed: -1 +*******************************************************************************************************************/ +int parse_http_response(uint8_t *response, uint32_t response_len, http_response_result_t *result) { + uint32_t i, p, q, m; + uint32_t header_end = 0; + + //Get status code + if(0 == result->parse_status){//didn't get the http response + uint8_t status[4] = {0}; + i = p = q = m = 0; + for (; i < response_len; ++i) { + if (' ' == response[i]) { + ++m; + if (1 == m) {//after HTTP/1.1 + p = i; + } + else if (2 == m) {//after status code + q = i; + break; + } + } + } + if (!p || !q || q-p != 4) {//Didn't get the status code + return -1; + } + memcpy(status, response+p+1, 3);//get the status code + result->status_code = atoi((char const *)status); + if(result->status_code == 200) + result->parse_status = 1; + else{ + printf("\n\r[%s] The http response status code is %d", __FUNCTION__, result->status_code); + return -1; + } + } + + //if didn't receive the full http header + if(3 == result->parse_status){//didn't get the http response + p = q = 0; + for (i = 0; i < response_len; ++i) { + if (response[i] == '\r' && response[i+1] == '\n' && + response[i+2] == '\r' && response[i+3] == '\n') {//the end of header + header_end = i+4; + result->parse_status = 4; + result->header_len = header_end; + result->body = response + header_end; + break; + } + } + if (3 == result->parse_status) {//Still didn't receive the full header + result->header_bak = update_malloc(HEADER_BAK_LEN + 1); + memset(result->header_bak, 0, strlen(result->header_bak)); + memcpy(result->header_bak, response + response_len - HEADER_BAK_LEN, HEADER_BAK_LEN); + } + } + + //Get Content-Length + if(1 == result->parse_status){//didn't get the content length + uint32_t content_length = 0; + const uint8_t *content_length_buf1 = "CONTENT-LENGTH"; + const uint8_t *content_length_buf2 = "Content-Length"; + const uint32_t content_length_buf_len = strlen(content_length_buf1); + p = q = 0; + + for (i = 0; i < response_len; ++i) { + if (response[i] == '\r' && response[i+1] == '\n') { + q = i;//the end of the line + if (!memcmp(response+p, content_length_buf1, content_length_buf_len) || + !memcmp(response+p, content_length_buf2, content_length_buf_len)) {//get the content length + int j1 = p+content_length_buf_len, j2 = q-1; + while ( j1 < q && (*(response+j1) == ':' || *(response+j1) == ' ') ) ++j1; + while ( j2 > j1 && *(response+j2) == ' ') --j2; + uint8_t len_buf[12] = {0}; + memcpy(len_buf, response+j1, j2-j1+1); + result->body_len = atoi((char const *)len_buf); + result->parse_status = 2; + } + p = i+2; + } + if (response[i] == '\r' && response[i+1] == '\n' && + response[i+2] == '\r' && response[i+3] == '\n') {//Get the end of header + header_end = i+4;//p is the start of the body + if(result->parse_status == 2){//get the full header and the content length + result->parse_status = 4; + result->header_len = header_end; + result->body = response + header_end; + } + else {//there are no content length in header + printf("\n\r[%s] No Content-Length in header", __FUNCTION__); + return -1; + } + break; + } + } + + if (1 == result->parse_status) {//didn't get the content length and the full header + result->header_bak = update_malloc(HEADER_BAK_LEN + 1); + memset(result->header_bak, 0, strlen(result->header_bak)); + memcpy(result->header_bak, response + response_len - HEADER_BAK_LEN, HEADER_BAK_LEN); + } + else if (2 == result->parse_status) {//didn't get the full header but get the content length + result->parse_status = 3; + result->header_bak = update_malloc(HEADER_BAK_LEN + 1); + memset(result->header_bak, 0, strlen(result->header_bak)); + memcpy(result->header_bak, response + response_len - HEADER_BAK_LEN, HEADER_BAK_LEN); + } + } + + return result->parse_status; +} + +int http_update_ota(char *host, int port, char *resource) +{ + int server_socket; + unsigned char *buf, *alloc, *request; + _file_checksum *file_checksum; + int read_bytes = 0, i = 0; + uint32_t address, flash_checksum = 0; + uint32_t NewImg2Len = 0, NewImg2Addr = 0; + int ret = -1; + http_response_result_t rsp_result = {0}; + + alloc = update_malloc(BUF_SIZE + 4); + if(!alloc){ + printf("\n\r[%s] Alloc buffer failed", __FUNCTION__); + goto update_ota_exit; + } + buf = &alloc[4]; + file_checksum = (void*)alloc; + + // Connect server + server_socket = update_ota_http_connect_server(server_socket, host, port); + if(server_socket == -1){ + goto update_ota_exit; + } + + NewImg2Addr = update_ota_prepare_addr(); + if(NewImg2Addr == -1){ + goto update_ota_exit; + } + + // reset + file_checksum->u = 0; + + // Write New Image 2 sector + if(NewImg2Addr != ~0x0){ + uint32_t idx = 0; + int data_len = 0; + printf("\n\r"); + + //send http request + request = (unsigned char *) update_malloc(strlen("GET /") + strlen(resource) + strlen(" HTTP/1.1\r\nHost: ") + + strlen(host) + strlen("\r\n\r\n") + 1); + sprintf(request, "GET /%s HTTP/1.1\r\nHost: %s\r\n\r\n", resource, host); + + ret = write(server_socket, request, strlen(request)); + if(ret < 0){ + printf("\n\r[%s] Send HTTP request failed", __FUNCTION__); + goto update_ota_exit; + } + + while (3 >= rsp_result.parse_status){//still read header + if(0 == rsp_result.parse_status){//didn't get the http response + memset(buf, 0, BUF_SIZE); + read_bytes = read(server_socket, buf, BUF_SIZE); + if(read_bytes == 0) + continue; + if(read_bytes < 0){ + printf("\n\r[%s] Read socket failed", __FUNCTION__); + goto update_ota_exit; + } + + idx = read_bytes; + memset(&rsp_result, 0, sizeof(rsp_result)); + if(parse_http_response(buf, idx, &rsp_result) == -1){ + goto update_ota_exit; + } + } + else if((1 == rsp_result.parse_status) || (3 == rsp_result.parse_status)){//just get the status code + memset(buf, 0, BUF_SIZE); + memcpy(buf, rsp_result.header_bak, HEADER_BAK_LEN); + update_free(rsp_result.header_bak); + rsp_result.header_bak = NULL; + read_bytes = read(server_socket, buf+ HEADER_BAK_LEN, (BUF_SIZE - HEADER_BAK_LEN)); + if(read_bytes == 0) + continue; + if(read_bytes < 0){ + printf("\n\r[%s] Read socket failed", __FUNCTION__); + goto update_ota_exit; + } + + idx = read_bytes + HEADER_BAK_LEN; + + if(parse_http_response(buf, read_bytes + HEADER_BAK_LEN, &rsp_result) == -1){ + goto update_ota_exit; + } + } + else if(3 == rsp_result.parse_status){ + printf("\n\r[%s] Get the content_length failed", __FUNCTION__); + goto update_ota_exit; + } + } + + if (0 == rsp_result.body_len){ + printf("\n\r[%s] New firmware size = 0 !", __FUNCTION__); + goto update_ota_exit; + } + else + printf("\n\r[%s] Download new firmware begin, total size : %d\n\r", __FUNCTION__, rsp_result.body_len); + +#if SWAP_UPDATE + NewImg2Addr = update_ota_swap_addr(rsp_result.body_len, NewImg2Addr); + if(NewImg2Addr == -1){ + goto update_ota_exit; + } +#endif + address = NewImg2Addr; + NewImg2Len = update_ota_erase_upg_region(rsp_result.body_len, NewImg2Len, NewImg2Addr); + if(NewImg2Len == -1){ + goto update_ota_exit; + } + + //Write the body of http response into flash + data_len = idx - rsp_result.header_len; + if(data_len > 0){ + file_checksum->c[0] = alloc[4+data_len-4]; // checksum attached at file end + file_checksum->c[1] = alloc[4+data_len-3]; + file_checksum->c[2] = alloc[4+data_len-2]; + file_checksum->c[3] = alloc[4+data_len-1]; + + device_mutex_lock(RT_DEV_LOCK_FLASH); + if(flash_stream_write(&flash_ota, address, data_len, (buf+rsp_result.header_len)) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + goto update_ota_exit; + } + device_mutex_unlock(RT_DEV_LOCK_FLASH); + } + + idx = 0; + idx += data_len; + while (idx < NewImg2Len){ + printf("."); + data_len = NewImg2Len - idx; + if(data_len > BUF_SIZE) + data_len = BUF_SIZE; + + memset(buf, 0, BUF_SIZE); + read_bytes = read(server_socket, buf, data_len); + if(read_bytes == 0) + continue; + if(read_bytes < 0){ + printf("\n\r[%s] Read socket failed", __FUNCTION__); + goto update_ota_exit; + } + + if(read_bytes<4) + printf("\n\r[%s] Recv small packet", __FUNCTION__); + + device_mutex_lock(RT_DEV_LOCK_FLASH); + if(flash_stream_write(&flash_ota, address + idx, read_bytes, buf) < 0){ + printf("\n\r[%s] Write sector failed", __FUNCTION__); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + goto update_ota_exit; + } + device_mutex_unlock(RT_DEV_LOCK_FLASH); + + file_checksum->c[0] = alloc[4+read_bytes-4]; // checksum attached at file end + file_checksum->c[1] = alloc[4+read_bytes-3]; + file_checksum->c[2] = alloc[4+read_bytes-2]; + file_checksum->c[3] = alloc[4+read_bytes-1]; + + idx += read_bytes; + } + printf("\n\r[%s] Download new firmware %d bytes completed\n\r", __FUNCTION__, idx); + + // read flash data back and calculate checksum + for(i = 0; i < idx-4; i += BUF_SIZE){ + int k; + int rlen = (idx-4-i)>BUF_SIZE?BUF_SIZE:(idx-4-i); + device_mutex_lock(RT_DEV_LOCK_FLASH); + flash_stream_read(&flash_ota, NewImg2Addr+i, rlen, buf); + device_mutex_unlock(RT_DEV_LOCK_FLASH); + for(k = 0; k < rlen; k++) + flash_checksum+=buf[k]; + } + + ret = update_ota_checksum(file_checksum, flash_checksum, NewImg2Addr); + if(ret == -1){ + printf("\n\r[%s] The checksume is wrong!\n\r", __FUNCTION__); + goto update_ota_exit; + } + } +update_ota_exit: + if(alloc) + update_free(alloc); + if(request) + update_free(request); + if(server_socket >= 0) + close(server_socket); + return ret; +} +#endif diff --git a/RTL00_SDKV35a/component/soc/realtek/8195a/misc/platform/ota_8195a.h b/RTL00_SDKV35a/component/soc/realtek/8195a/misc/platform/ota_8195a.h new file mode 100644 index 0000000..d474f62 --- /dev/null +++ b/RTL00_SDKV35a/component/soc/realtek/8195a/misc/platform/ota_8195a.h @@ -0,0 +1,97 @@ +#ifndef OTA_8195A_H +#define OTA_8195A_H + +#include +#include +#include +#include +#include + +/************************Related setting****************************/ +#define HTTP_OTA_UPDATE //if define, using http protocol, if not, will use socket +#define CONFIG_CUSTOM_SIGNATURE 0 //if verify the custom signature(define in ota_8195a.c cus_sig) +#define WRITE_OTA_ADDR 1 +#define SWAP_UPDATE 0 + + +#define BUF_SIZE 512 +#define HEADER_BAK_LEN 32 + +#define OFFSET_DATA FLASH_SYSTEM_DATA_ADDR +#define IMAGE_2 0x0000B000 +#if WRITE_OTA_ADDR +#define BACKUP_SECTOR (FLASH_SYSTEM_DATA_ADDR - 0x1000) +#endif +/*******************************************************************/ + + +/****************Define the structures used*************************/ +typedef struct{ + uint32_t ip_addr; + uint16_t port; +}update_cfg_local_t; + +typedef struct { + uint32_t status_code; + uint32_t header_len; + uint8_t *body; + uint32_t body_len; + uint8_t *header_bak; + uint32_t parse_status; +} http_response_result_t; + +typedef union { + uint32_t u; + unsigned char c[4]; +} _file_checksum; +/*******************************************************************/ + + +/****************General functions used by ota update***************/ +void *update_malloc(unsigned int size); +void update_free(void *buf); +void ota_platform_reset(void); +#if WRITE_OTA_ADDR +int write_ota_addr_to_system_data(flash_t *flash, uint32_t ota_addr); +#endif +int update_ota_connect_server(int server_socket, update_cfg_local_t *cfg); +uint32_t update_ota_prepare_addr(void); +#if SWAP_UPDATE +uint32_t update_ota_swap_addr(uint32_t img_len, uint32_t NewImg2Addr); +#endif +int update_ota_erase_upg_region(uint32_t img_len, uint32_t NewImg2Len, uint32_t NewImg2Addr); +int update_ota_checksum(_file_checksum *file_checksum, uint32_t flash_checksum, uint32_t NewImg2Addr); +/*******************************************************************/ + + +/*******************Functions called by AT CMD**********************/ +void cmd_update(int argc, char **argv); +void cmd_ota_image(bool cmd); +/*******************************************************************/ + + +/************************************************************************************************* +** Function Name : update_ota_local +** Description : Starting a thread of OTA updating through socket +** Input : ip:The IP address of OTA server +** port:The Port of OTA server +** Return : 0: Task created OK +** -1: Task created failed +**************************************************************************************************/ +int update_ota_local(char *ip, int port); + + +#ifdef HTTP_OTA_UPDATE +int parse_http_response(uint8_t *response, uint32_t response_len, http_response_result_t *result); +int update_ota_http_connect_server(int server_socket, char *host, int port); + +/************************************************************************************************* +** Function Name : http_update_ota +** Description : The process of OTA updating through http protocol +** Input : cfg:struct update_cfg_local_t +** Return : NULL +**************************************************************************************************/ +int http_update_ota(char *host, int port, char *resource); +#endif + +#endif