当前位置: 首页 > 图灵资讯 > 技术篇> 乐鑫esp8266基于freeRtos实现私有服务器本地远程OTA升级

乐鑫esp8266基于freeRtos实现私有服务器本地远程OTA升级

来源:图灵教育
时间:2023-06-01 09:41:50

文章目录
  • 一、前言;
  • 二、回顾下`OTA`的流程;
  • 三、`lwip`使用网络框架的知识;
  • 如何处理服务器返回的数据?
  • 五、风扇区域的擦除和烧写?
  • 六、如何调用?
  • 好好享受吧!
  • 八、下载:
  • 九、工程截图:

一、前言;
  • esp8266实现OTA这不再是一件奇怪的事情,主要是esp8266还支持裸跑非系统和裸跑非系统rtos实时系统的划分导致现在有两个版本的代码,我已经预料到了NONOS如何实现我们的固件的远程升级,所以这篇文章是基于freeRtos实时系统。
  • 主要涉及以下知识:
  • lwip基本使用网络框架、域名和DNS使用分析。
  • freeRtos基本理解。
  • http协议的理解和原则。
  • esp8266对内存划分的理解。
  • 实现的功能特征如下:
  • 支持本地服务器和远程广域网服务器。DNS解析)
  • 支持显示下载固件的进度。

二、回顾下OTA的流程;
  • 我们已经很清楚了,esp8266实现远程升级的原理如下:

Created with Raphaël 2.2.0 开始要求服务器资源,比如user2.4096.new.6.bin 良好的网络,正确的服务器响应。准备下载... ... 下载后,确认是否重启? 重启成功!根据 boot user2.4096执行信息.new.6.bin。 yes


  • 事实上,私人服务的放置也是如此。您只需在阿里巴巴云、京东云或腾讯云平台上建立服务器,放置编译固件并提供与当地相同的链接。
  • 注意两个固件的配置信息必须一致。

三、lwip使用网络框架的知识;
  • ①:lwip使用DNS对网站域名进行分析。

因为esp8266这种实时系统支持lwip,所以可以直接调用;首先,打开它DNS功能,在lwipopts.h第一个文件有宏定义LWIP_DNS把它放在一边。以下是调用代码:

//dns begindns_init(); ///初始化struct ip_addr addr;///你要分析的域名,比如 www.baidu.comchar name0[] = "www.baidu.com"; ///调用netcon_gethostbynameerr_t err = netconn_gethostbyname((char*) name0, &addr);///定义字符串接收IPcharr* ipAdress;if (err == ERR_OK) {    ///格式化IP    ipAdress = ip_ntoa(&addr);    /打印printf(”dns ok , the %s ip is:%s",name0, ipAdress);}else{return;}//dns over


  • ②:先通过socket一般来说,默认情况下,连接服务器端口80!其中http请求的格式内容如下:请注意此Host内容可以是域名或IP,根据服务器进行配置。

GET /api/download/user2.4096.new.6.bin HTTP/1.0Host: www.baidu.comConnection: keep-aliveCache-Control: no-cacheUser-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36 Accept: */*Accept-Encoding: gzip,deflate,sdchAccept-Language: zh-CN,zh;q=0.8


  • ③:如果响应正确,我们也应该遵循一定的规则,我们可以使用它postMan看看工具,显示下载的大小是296412,单位是Byte;然后,让我们根据这个尺寸来判断我们的下载进度!

如何处理服务器返回的数据?
  • 我们是采用http请求服务器,如果服务器响应正确,也会按照一定的协议返回给我们 。小徐尝试了几个服务器,一个是Tomcat,一个是用图灵构建的服务器返回的内容格式不同。最大的区别是:一是Accept-Length:指定内容大小,一是指定内容,Content-Length:指定尺寸,所以我的包装方法文件,可以完全兼容。详情请参见以下代码的一部分。

//判断 "Accept-Length" 或者 "Context-Length"bool isAccept = false;if((ptr = (char *)strstr(pusrdata, "Accept-Length")) != NULL)isAccept = true;elseisAccept = false;if (totallength == 0&& (ptr = (char *)strstr(pusrdata, "\r\n\r\n")) != NULL) {ptr = (char *) strstr(pusrdata, "\r\n\r\n");length -= ptr - pusrdata;length -= 4;printf("ota_start_download:upgrade file download pusrdata:%s\n\n",pusrdata);//返回"Accept-Length: iff首次出现在pusrdata中 (isAccept)ptr = (char *) strstr(pusrdata, "Accept-Length: ");elseptr = (char *) strstr(pusrdata, "Content-Length: ");if (ptr != NULL) {            ///注意这个”Accept-Length" 或者 "Context-Length“不同的if占用不同的字节 (isAccept)ptr += 15;elseptr += 16;ptmp2 = (char *) strstr(ptr, "\r\n");if (ptmp2 != NULL) 打印下收到的数据头///printf("ptr = %s \n", ptr);///清空lengthbufermeteter(lengthbuffer, 0, sizeof(lengthbuffer));memcpy(lengthbuffer, ptr, ptmp2 - ptr);sumlength = atoi(lengthbuffer);if (sumlength > 0) {if (false == system_upgrade(pusrdata, sumlength)) {system_upgrade_flag_set(UPGRADE_FLAG_IDLE);goto ota_recycle;}flash_erased = true;ptr = (char *) strstr(pusrdata, "\r\n\r\n");if (false == system_upgrade(ptr + 4, length)) {system_upgrade_flag_set(UPGRADE_FLAG_IDLE);goto ota_recycle;}totallength += length;return;}} else {system_upgrade_flag_set(UPGRADE_FLAG_IDLE);goto ota_recycle;}}


  • 我们上面得到了这个总数据,那么当我们下载固件时,我们如何判断我们是否提取了所有固件呢?事实上,通过比较我们提取的内容大小和总数,我们可以得到是否下载。

一般来说,除了总数据量,我们下载的数据量是百分比!因为esp8266不支持浮点类型,即不支持小数。 但是我们又要显示进度呢?yiban其实很简单,算法如下:

  • sumlength总数据量,totallength已下载的数据量!

int part =sumlength/100;int projress = (totallength / part);printf(”已下载: %d , 总数据: %d , 进度: %d\% \n", totallength, sumlength,projress);


五、风扇区域的擦除和烧写?
  • 要弄明白esp8266OTA,我们必须清楚地了解它的风扇区域。我们现在最常用的是esp8266-12f,它的容量大小是32Mbit,也就是说,最大代码是1M,2个分区:1024+1024!而大家玩的esp8266-018Mbit, 也即是512+512
  • 从下面官方给出的图片可以看出,一个支持OTA如果你的风扇分布是对称的,风扇区分布是对称的8Mbit那么最大的支持就是512K,而且32Mbit是最大的支持1M,其他空间用户数据!说白了,只加载了这两个空间的任何固件!

六、如何调用?
  • 因为个人小徐是一个喜欢包装代码以减少耦合的程序员,所以在做项目时应该明确划分功能。因此,这种包装也是基于面对象的想法。通过回调实现进度:

  • 判断目前在哪个分区,如果是分区一,那么我们拉的是分区二的代码,反而是一样的;

//注册回调函数system_ota_register_callBack(ota_call_back);//如果现在是这样 user1.bin,然后拉云 user2.bin 升级if(system_upgrade_userbin_check()==UPGRADE_FW_BIN1){printf("now is user1.bin\n");system_ota_config_start("www.baidu.com","api/v1/emq/download/iot?bin2.bin",80,true,true);//如果现在是这样 user2.bin,然后拉云 user1.bin 升级}else if(system_upgrade_userbin_check()==UPGRADE_FW_BIN2){printf("now is user2.bin.\n");system_ota_config_start("www.baidu.com","api/v1/emq/download/iot?bin1.bin",80,true,true);}else{    //不支持云升级printf(”now is not support FOTA..\n");}


  • 看看我们刚刚注册的回调函数:

void ota_call_back(int progress, ota_code code) {    ///下载时可以看到进度值。if (code == OTA_DOWNLOADING) {printf("ota_DowmLoading: %d%% \n",progress);///下载完毕} else if (code == OTA_SUCCEED) {printf("OTA_SUCCEED! \n");system_upgrade_deinit();// 下载后是否重启系统system_取决于您的需要upgrade_reboot();}}


  • 这是小徐专注于包装的函数和方法,可以直接调用:

typedef enum {OTA_FAIL = 0,    ///下载失败可能是网速问题OTA_SUCCEED ,  ///下载并成功烧录,请重启系统OTA_DOWNLOADING ,  ///下载时可以看到进度条OTA_INIT_ERROR , ///初始化失败,网站错误。OTA_INIT_OK , ///初始化成功。}ota_code;///progress是进度条,code是状态码typedeffe void (*ota_download_CallBack)(int progress,ota_code code);///注册下载服务器bin文件进度百分比回调函数:0-100% (整型);void system_ota_register_callBack(ota_download_CallBack callBack);/****************************************************************************** * FunctionName : system_ota_config_start * Description  : 传入网址,并开始下载 * Parameters   : char *domainName : 域名或ip地址 *                char* requestResource : 请求的资源地址 *                int port         : 端口号 *                bool isDNS       : DNS分析是否需要 *                bool isGet       : get请求或post提交 * Returns      : 是否成功 *******************************************************************************/bool system_ota_config_start(char *domainName, char* requestResource,int port,bool isDNS, bool isGet);


好好享受吧!
  • 以下是我串口打印的截图:

乐鑫esp8266基于freeRtos实现私有服务器本地远程OTA升级_DNS


乐鑫esp8266基于freeRtos实现私有服务器本地远程OTA升级_乐鑫esp8266_02


八、下载:
  • 这个demo需要注意的是,如果您的服务器地址是直接的IP的,就不用DNS分析;如果是域名,则需要DNS是的;还有一点需要啰嗦:注意你的网络好,服务器是否访问,以及最重要的分区说明。
  • 好吧,如果你确保上述问题,那么这个demo有趣的问题是来回升级,在两个分区跳跃。。哈哈。

九、工程截图:

乐信esp8266基于freertos实现私有服务器本地远程OTA升级_freeRtos_03'

基于freertos,乐信esp8266实现了私有服务器本地远程OTA升级