4.5http OTA远程升级

本节我们使用开发板的http来完成固件OTA远程升级,由于http协议处在tcp/ip协议的应用层,tcp协议工作在传输层,只需要在tcp传输层中按照http协议中的数据格式,发送数据就可以完成http传输数据。在SDK源码中打开宏定义 DEMO_HTTP 和 DEMO_CONNECT_NET。在程序中编写需要传入的http ota固件地址。
int t_http_fwup(char url)
{
HTTPParameters httpParams;
memset(&httpParams, 0, sizeof(HTTPParameters));
if (url == NULL)
{
httpParams.Uri = "http://192.168.1.100:8080/WM_W800_SEC.img";
}
else
{
httpParams.Uri = url;
}
printf("Location: %s\n",httpParams.Uri);
httpParams.Verbose = TRUE;
return http_fwup(httpParams);
}
接下来编写服务升级流程:
int http_fwup(HTTPParameters ClientParams)
{
char
Buffer = NULL;
char token[32];
char headRange[32] = {0};
int nRetCode = 0;
u32 content_length=0, size=32;
u32 partLen;
u32 totalLen = 0;
u32 recvLen = 0;
IMAGE_HEADER_PARAM_ST *booter;

if USE_BREAK_POINT_RESUME == 0

u32 breakFlag = 0;
u32 breakLen = 0;

endif

struct pbuf *p;
HTTP_SESSION_HANDLE  pHTTP;
enum ota_state now_state = PREPARE_PACKET;

Buffer = (char*)tls_mem_alloc(HTTP_CLIENT_BUFFER_SIZE + FWUP_MSG_SIZE);
if (!Buffer)
    return HTTP_CLIENT_ERROR_NO_MEMORY;
memset(Buffer, 0, HTTP_CLIENT_BUFFER_SIZE + FWUP_MSG_SIZE);    

while(1)
{
    switch(now_state)
    {
        case PREPARE_PACKET:
        {
            memset(token, 0, 32);
            size = 32;
            pHTTP = HTTPClientOpenRequest(0);

if USE_BREAK_POINT_RESUME

            HTTPClientSetVerb(pHTTP,VerbGet);
            sprintf(headRange, "bytes=%d-", recvLen);
            if((nRetCode = HTTPClientAddRequestHeaders(pHTTP,"Range", headRange, 1))!= HTTP_CLIENT_SUCCESS){
                now_state = QUIT_OTA;
            }

else

            if( recvLen != 0 ){
                breakFlag = 1;
                breakLen = 0;
            }

endif

            now_state = SETUP_LINK_AND_REQ;
        }
        break;
        
        case SETUP_LINK_AND_REQ:
        {
            if( (nRetCode = HTTPClientSendRequest(pHTTP,ClientParams.Uri,NULL,0,FALSE,0,0)) != HTTP_CLIENT_SUCCESS ){
                tls_os_time_delay(HZ*2);
                now_state = SHUTDOWN_LINK;
            }
            else
                now_state = RECV_RSP;
        }
        break;
        
        case RECV_RSP:
        {
            if((nRetCode = HTTPClientRecvResponse(pHTTP, RECV_TIMEOUT)) != HTTP_CLIENT_SUCCESS)
                now_state = SHUTDOWN_LINK;
            else
                now_state = HANDLE_HEADER;
        }
        break;
        
        case HANDLE_HEADER:
        {
            if((nRetCode = HTTPClientFindFirstHeader(pHTTP, "content-length", (CHAR *)token, &size)) != HTTP_CLIENT_SUCCESS){
                HTTPClientFindCloseHeader(pHTTP);
                now_state = SHUTDOWN_LINK;
            }
            else
            {
                HTTPClientFindCloseHeader(pHTTP);
                content_length = atol(strstr(token,":")+1);
                printf("content_length: %d\n", content_length);
                now_state = HANDLE_BODY;
                if(recvLen == 0){
                    nRetCode = socket_fwup_accept(0, ERR_OK);
                    if(nRetCode != ERR_OK)
                        now_state = QUIT_OTA;
                }
            }
        }
        break;
        
        case HANDLE_BODY:
        {
            partLen = 0;
            while(nRetCode != HTTP_CLIENT_EOS )
            {
                u32 nSize = HTTP_CLIENT_BUFFER_SIZE;
                nRetCode = HTTPClientReadData(pHTTP,Buffer+FWUP_MSG_SIZE,nSize,RECV_TIMEOUT,&nSize);
                if( recvLen == 0 ){
         
                    booter =(IMAGE_HEADER_PARAM_ST *) (Buffer+FWUP_MSG_SIZE);
					if (TRUE == tls_fwup_img_header_check(booter))
					{
						totalLen = booter->img_len + sizeof(IMAGE_HEADER_PARAM_ST);
						if (booter->img_attr.b.signature)
						{
							totalLen += 128;
						}
					}
					else
					{
						now_state = QUIT_OTA;
						break;
					}                        
                }

                if(nRetCode != HTTP_CLIENT_SUCCESS && nRetCode != HTTP_CLIENT_EOS){
                    now_state = SHUTDOWN_LINK;
                    break;
                }

if USE_BREAK_POINT_RESUME == 0

                if(breakFlag == 1){
                    breakLen += nSize;
                    if(breakLen <= recvLen){
                        continue;
                    }
                    else{
                        Buffer = Buffer+FWUP_MSG_SIZE+nSize-(breakLen-recvLen)-FWUP_MSG_SIZE;
                        nSize = (breakLen-recvLen);
                        breakFlag = 0;
                    }
                }

endif

                p = pbuf_alloc(PBUF_TRANSPORT, nSize + FWUP_MSG_SIZE, PBUF_REF);
                while( !p){
                    tls_os_time_delay(1);
                    p = pbuf_alloc(PBUF_TRANSPORT, nSize + FWUP_MSG_SIZE, PBUF_REF);
                }
                
                if(recvLen == 0)
                    *(Buffer+0) = SOCKET_FWUP_START;
                else if(nRetCode == HTTP_CLIENT_EOS && recvLen == (totalLen-nSize))
                    *(Buffer+0) = SOCKET_FWUP_END;
                else
                    *(Buffer+0) = SOCKET_FWUP_DATA;

                *(Buffer+1) = (nSize>>8) & 0xFF;
                *(Buffer+2) = nSize & 0xFF;	
                p->payload =  Buffer;
                p->len = p->tot_len = nSize + FWUP_MSG_SIZE;
                // Send received data to fwup thread and deal with socket issues.
                s8 ret = socket_fwup_recv(0, p, ERR_OK);
                if(ret != ERR_OK){
                    now_state = SHUTDOWN_LINK;
                    break;
                }
                else{
                    recvLen += nSize;
                    partLen += nSize;           
                    printf("download %d / %d\n", recvLen, totalLen);
                    if(partLen == content_length){
                        now_state = SHUTDOWN_LINK;
                        break;
                    }
                }
            }
			if (now_state == QUIT_OTA);
			else
            now_state = SHUTDOWN_LINK;
        }
        break;
        
        case SHUTDOWN_LINK:
        {
            if(pHTTP){
                HTTPClientCloseRequest(&pHTTP);
                (recvLen == totalLen)?(now_state = QUIT_OTA):(now_state = PREPARE_PACKET);
            }
        }
        break;
        
        default:
        break;
    }
    //printf("now_state %d\n", now_state);
    if(now_state == QUIT_OTA)
        break;
}

tls_mem_free(Buffer);
if(pHTTP)
    HTTPClientCloseRequest(&pHTTP);
if(ClientParams.Verbose == TRUE)
{
    printf("\n\nHTTP Client terminated %d (got %d kb)\n\n",nRetCode,(recvLen/ 1024));
}
if(nRetCode)
    socket_fwup_err(0, nRetCode);
return nRetCode;

}
程序的测试需要开启动一个hfs 服务器,hfs服务器下载:链接:https://pan.baidu.com/s/1N7gL9f-nj9Qr_HJv43FYAg 提取码:6666
打开hfs服务器后端口改为8080,同时放上我们需要升级的固件,这里我们放了hello_world的img固件。

程序编译并下载到开发板。先在串口输入配网指令联网。
指令如:t-connect("@snail","ss559550")

接下来输入升级指令t-httpfwup=(http://192.168.2.103:8080/w800_ota.img),串口可以看到升级进度,升级成功,自动运行新固件程序。

posted @ 2020-12-09 15:56  深圳四博智联科技有限公司  阅读(851)  评论(1编辑  收藏  举报