This commit is contained in:
pvvx 2017-06-09 00:42:34 +03:00
parent 5cd34b0c9f
commit fd4c492ea4
6 changed files with 1001 additions and 5 deletions

View file

@ -6,10 +6,15 @@
******************************************************************************/
#include <platform_opts.h>
#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

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -0,0 +1,825 @@
#include <sys.h>
#include <device_lock.h>
#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

View file

@ -0,0 +1,97 @@
#ifndef OTA_8195A_H
#define OTA_8195A_H
#include <FreeRTOS.h>
#include <task.h>
#include <platform_stdlib.h>
#include <flash_api.h>
#include <lwip/sockets.h>
/************************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