ESP8285 RTOS SDK OTA
一、官方资源说明
官方指南:空中升级 (OTA) - ESP32 - — ESP-IDF 编程指南 v4.3.6 文档,虽然是正对ESP32的,但是原理是一样的。
官方参考例程:esp-idf\ESP8266_RTOS_SDK\examples\system\ota\,其中包含两个例程,一个是simple_ota_example,另一个是native_ota。simple_ota_example例程调用的是封装之后函数,只需要将固件的下载地址传入函数即可自动完成升级,而native_ota调用的是原生的函数,有更多的过程,详细展示了OTA的下载、存储过程以及校验。这里以simple_ota_example为例进行讲解。
二、修改配置文件
1、修改Partition Table
使用带ota分区的Partition Table,在flash区域中划出两块app存储空间,一块区域是当前运行的app区,另一块区域是新下载的app存放的区域。进入到工程目录中,执行make menuconfig,然后选择
Partition Table --->
Partition Table (Single factory app, no OTA) --->
(X) Factory app, two OTA definitions
2、允许http方式进行ota
此方式不需要证书,更简单。
Component config --->
ESP HTTPS OTA --->
[*] Allow HTTP for OTA (WARNING: ONLY FOR TESTING PURPOSE, READ HELP)
三、编写代码
1、升级流程
上电->进入app_main()->创建升级任务(simple_ota_example_task)->执行任务->等待wifi连接并获取IP地址->http请求服务器上的固件版本号->与当前运行版本号进行比较->如果服务器上的固件版本号更高->下载新的固件->下载完成之后重启设备。
2、代码
版本比较函数
/*** @brief None.* @param None.* @retval None.*/
int edition_compare(const char* pszStr1, const char* pszStr2)
{if (pszStr1 == NULL || pszStr2 == NULL) {return 0;}int nCurPos = 0, nCapPos=-1;const char* pszTmp1 = pszStr1;const char* pszTmp2 = pszStr2;while ((*pszTmp1 != '\0') && (*pszTmp2 != '\0') && (*pszTmp1 == *pszTmp2)) { nCurPos++; //找到第一个处不相同出现的位置pszTmp1++;pszTmp2++;if (*pszTmp1 == '.') {nCapPos = nCurPos; //记录最近的‘.’的位置}}if (*pszTmp1 == '\0' && *pszTmp2 == '\0') { // 两个字符串相等return 0;} else if(*pszTmp1 == '\0'){return -1;} else if(*pszTmp2 == '\0'){return 1;}else{ // 两个字符串不相等,比较大小pszTmp1 = pszStr1 + nCapPos + 1;pszTmp2 = pszStr2 + nCapPos + 1;int pszNub1=strtol(pszTmp1,NULL,10);int pszNub2=strtol(pszTmp2,NULL,10);return (pszNub1 - pszNub2);}
}
创建设备事件,用于等待网络连接
const int CONNECTED_BIT = BIT0;s_device_event_group = xEventGroupCreate();
event_handler()函数中加入s_device_event_group的设置
/*** @brief event_handler.* @param None.* @retval None.*/
static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
{if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {esp_wifi_connect();}else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);xEventGroupClearBits(s_device_event_group, WIFI_CONNECTED_BIT);esp_wifi_connect();}else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);xEventGroupSetBits(s_device_event_group, WIFI_CONNECTED_BIT);}else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE) {ESP_LOGI(TAG, "Scan done");}else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL) {ESP_LOGI(TAG, "Found channel");} else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD) {ESP_LOGI(TAG, "Got SSID and password");smartconfig_event_got_ssid_pswd_t* evt = (smartconfig_event_got_ssid_pswd_t*)event_data;wifi_config_t wifi_config;uint8_t ssid[33] = { 0 };uint8_t password[65] = { 0 };uint8_t rvd_data[33] = { 0 };bzero(&wifi_config, sizeof(wifi_config_t));memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid));memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password));wifi_config.sta.bssid_set = evt->bssid_set;if (wifi_config.sta.bssid_set == true) {memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));}memcpy(ssid, evt->ssid, sizeof(evt->ssid));memcpy(password, evt->password, sizeof(evt->password));ESP_LOGI(TAG, "SSID:%s", ssid);ESP_LOGI(TAG, "PASSWORD:%s", password);if (evt->type == SC_TYPE_ESPTOUCH_V2) {ESP_ERROR_CHECK( esp_smartconfig_get_rvd_data(rvd_data, sizeof(rvd_data)) );ESP_LOGI(TAG, "RVD_DATA:%s", rvd_data);}ESP_ERROR_CHECK(esp_wifi_disconnect());ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));ESP_ERROR_CHECK(esp_wifi_connect());} else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE) {xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT);}
}
任务函数
/*** @brief None.* @param None.* @retval None.*/
static void simple_ota_example_task(void * pvParameter)
{EventBits_t uxBits = xEventGroupWaitBits(s_device_event_group, WIFI_CONNECTED_BIT, pdFALSE, false, portMAX_DELAY ); if( (uxBits & WIFI_CONNECTED_BIT) == WIFI_CONNECTED_BIT ){ESP_LOGI(TAG, "Starting OTA example...");char local_response_buffer[101] = {0};esp_http_client_config_t config0 = {.url = "http://www.huochaigun.top/hello-world/version.html",.event_handler = _http_event_handler,
// .user_data = local_response_buffer, // Pass address of local buffer to get response.buffer_size = 100};esp_http_client_handle_t client = esp_http_client_init(&config0); // GETesp_err_t err = esp_http_client_perform(client);if (err == ESP_OK) {ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d",esp_http_client_get_status_code(client),esp_http_client_get_content_length(client));} else {ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));}esp_http_client_read_response( client, local_response_buffer, 100 );local_response_buffer[ esp_http_client_get_content_length(client) ] = '\0';ESP_LOGI(TAG,"http response:%s\n", local_response_buffer );esp_http_client_cleanup(client);if( edition_compare(local_response_buffer, AppVer) > 0 ){esp_http_client_config_t config = {.url = "http://www.huochaigun.top/hello-world/hello-world.bin",.event_handler = _http_event_handler,};esp_err_t ret = esp_https_ota(&config);if (ret == ESP_OK) {esp_restart();} else {ESP_LOGE(TAG, "Firmware Upgrades Failed");}}else{ESP_LOGI(TAG, "The current software is the latest version");}}vTaskDelete( NULL );
}
app_main()中加入以下代码创建任务
xTaskCreate(simple_ota_example_task, "ota_example_task", 8192, NULL, 5, NULL);
四、编译固件
执行make之后,会新生成4个bin文件,将4个bin文件下载到设备即可。
0xd000 ota_data_initial.bin
0x0 bootloader.bin
0x10000 hello-world.bin
0x8000 partitions_two_ota.bin
可提供有偿技术支持。
相关文章:
ESP8285 RTOS SDK OTA
一、官方资源说明 官方指南:空中升级 (OTA) - ESP32 - — ESP-IDF 编程指南 v4.3.6 文档,虽然是正对ESP32的,但是原理是一样的。 官方参考例程:esp-idf\ESP8266_RTOS_SDK\examples\system\ota\,其中包含两个例程&…...

Hadoop3教程(四):HDFS的读写流程及节点距离计算
文章目录 (55)HDFS 写数据流程(56) 节点距离计算(57)机架感知(副本存储节点选择)(58)HDFS 读数据流程参考文献 (55)HDFS 写数据流程 …...

[0xGameCTF 2023] web题解
文章目录 [Week 1]signinbaby_phphello_httprepo_leakping [Week 2]ez_sqli方法一(十六进制绕过)方法二(字符串拼接) ez_upload [Week 1] signin 打开题目,查看下js代码 在main.js里找到flag baby_php <?php /…...

Qt之submodule编译
工作中会遇到这样一种情况:qt应用程序在运行时提示找不到某个qt的动态库。我遇到的是缺少libQt5Websocket.so,因为应用程序是在x86平台银河麒麟v10上开发,能够正常编译运行,然后移植到rk3588(aarch64架构)上…...

Python实现带图形界面的计算器
Python实现带图形界面的计算器 在本文中,我们将使用Python编写一个带有图形用户界面的计算器程序。这个程序将允许用户通过点击按钮或键盘输入数字和操作符,并在显示屏上显示计算结果。 开发环境准备 要运行这个计算器程序,您需要安装Pyth…...

$ vue -Vbash: vue: command not found
$ vue -V bash: vue: command not found报这个错,我们需要找到vue安装路径,添加在环境变量的用户变量中: 1、vue安装路径 2、编辑环境变量 然后重新打开命令框,就可以了...

专业音视频领域中,Pro AV的崛起之路
编者按:在技术进步的加持下,AV行业发展得如何了?本文采访了两位深耕于广播电视行业的技术人,为我们介绍了专业音视频的进展:一位冉冉升起的新星:Pro AV以及FPGA在其中发挥的作用。 美国,拉斯维加…...

vscode 右侧滚动条标记不提示,问题解决纪录
问题描述 用vscode看代码时,我希望在右侧提示一个变量在文件下都在那里使用,在那里赋值,之前该功能是存在的,当我打开一个新的文件夹时这个功能消失了。 解决办法 在setting.json文件下输入 "C_Cpp.intelliSenseEngine&…...

【Java 进阶篇】JavaScript特殊语法详解
JavaScript是一门非常灵活的编程语言,允许开发人员使用多种不同的语法和技巧来解决各种问题。本篇博客将深入探讨JavaScript中的一些特殊语法,这些语法可能不是常规的JavaScript编程知识,但它们对于理解语言的强大之处以及在某些情况下解决问…...

PCL点云处理之配准中的匹配对连线可视化显示 Correspondences(二百一十九)
PCL点云处理之配准中的匹配对连线可视化显示 Correspondences(二百一十九) 一、算法介绍二、算法实现1.可视化代码2.完整代码(特征匹配+可视化)最终效果一、算法介绍 关于点云配准中的匹配对,如果能够可视化将极大提高实验的准确性,还好PCL提供了这样的可视化工具,做法…...
Vue el-table全表搜索,模糊匹配-前端静态查询
后端返回的数据是全部的数据,没有分页,前端需要做的是分页全表模糊查询 代码: //根据关键字对表全局搜索 globalSearch() {//为了拿到对象的列名let filterList Object.keys(this.tableData[0]);if (this.searchWord) {this.tableFilterDat…...

基于html5开发的Win12网页版,抢先体验
据 MSPoweruser 报道,Windows 11虽然刚刚开始步入正轨,但最新爆料称微软已经在开启下一个计划,Windows 12 的开发将在 去年3 月份开始。德国科技网站 Deskmodder.de 称,根据内部消息,微软将在 2022年3 月开始开发 Wind…...

Studio One6.5中文版本下载安装步骤
在唱歌效果调试当中,我们经常给客户安装的几款音频工作站。第一,Studio One 6是PreSonus公司开发的一款功能强大的音频工作平台,具有丰富的音频处理功能和灵活的工作流程。以下是Studio One6的一些主要特点: 1.多轨录音和编辑&…...

Java架构师缓存架构设计解决方案
目录 1 缓存常见的三大问题1.1 缓存雪崩1.2 缓存穿透1.3 缓存击穿2 缓存key的生成策略3 热点数据集中失效的问题4 如何提高缓存的命中率5 缓存和数据库双写不一致的问题6 如何对缓存数据进行分片想学习架构师构建流程请跳转:Java架构师系统架构设计 1 缓存常见的三大问题 缓…...
【玩转Redhat Linux 8.0系列 | 实验—使用Bash shell执行命令】
今天继续分享一些Redhat Linux 8.0的知识,记得关注,会一直更新~ 访问命令行 任务执行清单 在本实验中,您将使用Bash shell来执行命令。 成果 使用Bash shell命令行成功运行简单的程序。 执行用于识别文件类型并显示文本文件部分内容的命…...

Linux系统编程详解
Linux 多线程编程 什么是线程? 与线程类似,线程是允许应用程序并发执行多个任务的一种机制 线程是轻量级的进程(LWP:Light Weight Process),在 Linux 环境下线程的本 质仍是进程。 一个进程可以包含多个线…...

ios设备管理软件iMazing 2.17.11官方中文版新增功能介绍
iMazing 2.17.11官方中文版(ios设备管理软件)是一款管理苹果设备的软件, Windows 平台上的一款帮助用户管理 IOS 手机的应用程序,软件功能非常强大,界面简洁明晰、操作方便快捷,设计得非常人性化。iMazing官方版与苹果设备连接后&…...

算法通关村第18关【青铜】| 回溯
回溯算法是一种解决组合优化问题和搜索问题的算法。它通过尝试各种可能的选择来找到问题的解决方案。回溯算法通常用于问题的解空间非常大,而传统的穷举法会导致计算时间爆炸的情况。回溯算法可以帮助限制搜索空间,以提高效率。 回溯算法的核心思想是在…...

【环境搭建】linux docker-compose安装seata1.6.1,使用nacos注册、db模式
新建目录,挂载用 mkdir -p /data/docker/seata/resources mkdir -p /data/docker/seata/logs 给权限 chmod -R 777 /data/docker/seata 先在/data/docker/seata目录编写一个使用file启动的docker-compose.yml文件(seata包目录的script文件夹有&#…...
20231008-20231013 读书笔记
计算机硬件 基本硬件系统:运算器、控制器、存储器、输入设备和输出设备中央处理单元(CPU):运算器、控制器、寄存器组和内部总线等部件组成 功能:程序控制、操作控制、时间控制、数据处理运算器:ALU、AC、DR、PSW控制器…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...