添加智能灯固件代码

This commit is contained in:
kerwincui
2021-07-13 17:14:51 +08:00
parent 332f74dd17
commit ecc0b91b8b
2568 changed files with 229441 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(otatool)

View File

@@ -0,0 +1,9 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := otatool
include $(IDF_PATH)/make/project.mk

View File

@@ -0,0 +1,77 @@
# OTA Tool Example
This example demonstrates common operations the OTA tool [otatool.py](../../../../components/app_update/otatool.py) allows the user to perform:
- reading, writing and erasing OTA partitions,
- switching boot partitions, and
- switching to factory partition.
Users taking a look at this example should focus on the contents of the Python script [otatool_example.py](otatool_example.py) or shell script [otatool_example.sh](otatool_example.sh). The scripts contain
programmatic invocation of the tool's functions via the Python API and command-line interface, respectively. Note
that on Windows, the shell script example requires a POSIX-compatible environment via MSYS2/Git Bash/WSL etc.
The built application in this example outputs the currently running partition, whose output is used to verify if the tool switched OTA
partitions succesfully. The built application binary is written to all OTA partitions at the start of the example to be able to determine the running
partition for all switches performed.
## How to use example
### Build and Flash
Before running either of the example scripts, it is necessary to build and flash the firmware using the usual means:
Make:
```bash
make build flash
```
CMake:
```bash
idf.py build flash
```
### Running [otatool_example.py](otatool_example.py)
The example can be executed by running the script [otatool_example.py](otatool_example.py) or [otatool_example.sh](otatool_example.sh).
Python script:
```bash
python otatool_example.py
```
Shell script:
```
./otatool_example.sh
```
The script searches for valid target devices connected to the host and performs the operations on the first one it finds. This could present problems if there
are multiple viable target devices attached to the host. To perform the operations on a specific device, specify the port it is attached to during script invocation ("/dev/ttyUSB2" for example):
Python script:
```bash
python otatool_example.py --port /dev/ttyUSB2
```
Shell script:
```
./otatool_example.sh /dev/ttyUSB2
```
## Example output
Running the script produces the following output:
```
Writing factory firmware to ota_0
Writing factory firmware to ota_1
Switching to factory app
Switching to OTA slot 0
Switching to OTA slot 1 (twice in a row)
Switching to OTA slot 0 (twice in a row)
Switching to factory app
Switching to OTA slot 1
Partition tool operations performed successfully
```

View File

@@ -0,0 +1,34 @@
from __future__ import print_function
import os
import sys
import subprocess
import ttfw_idf
@ttfw_idf.idf_example_test(env_tag='Example_WIFI')
def test_otatool_example(env, extra_data):
dut = env.get_dut('otatool', 'examples/system/ota/otatool', dut_class=ttfw_idf.ESP32DUT)
# Verify factory firmware
dut.start_app()
dut.expect("OTA Tool Example")
dut.expect("Example end")
# Close connection to DUT
dut.receive_thread.exit()
dut.port_inst.close()
script_path = os.path.join(os.getenv("IDF_PATH"), "examples", "system", "ota", "otatool", "otatool_example.py")
binary_path = ""
for flash_file in dut.app.flash_files:
if "otatool.bin" in flash_file[1]:
binary_path = flash_file[1]
break
subprocess.check_call([sys.executable, script_path, "--binary", binary_path])
if __name__ == '__main__':
test_otatool_example()

View File

@@ -0,0 +1,87 @@
#!/usr/bin/env python
#
# Demonstrates the use of otatool.py, a tool for performing ota partition level
# operations.
#
# Copyright 2018 Espressif Systems (Shanghai) PTE LTD
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http:#www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import sys
import serial
import subprocess
import re
import argparse
from subprocess import CalledProcessError
def get_running_partition(port=None):
# Monitor the serial output of target device. The firmware outputs the currently
# running partition
IDF_PATH = os.path.expandvars("$IDF_PATH")
sys.path.append(os.path.join(IDF_PATH, 'components', 'esptool_py', 'esptool'))
import esptool
ESPTOOL_PY = os.path.join(IDF_PATH, "components", "esptool_py", "esptool", "esptool.py")
baud = os.environ.get("ESPTOOL_BAUD", esptool.ESPLoader.ESP_ROM_BAUD)
if not port:
error_message = "Unable to obtain default target device port.\nSerial log:\n\n"
try:
# Check what esptool.py finds on what port the device is connected to
output = subprocess.check_output([sys.executable, ESPTOOL_PY, "chip_id"]) # may raise CalledProcessError
pattern = r"Serial port ([\S]+)"
pattern = re.compile(pattern.encode())
port = re.search(pattern, output).group(1) # may raise AttributeError
except CalledProcessError as e:
raise Exception(error_message + e.output)
except AttributeError:
raise Exception(error_message + output)
serial_instance = serial.serial_for_url(port.decode("utf-8"), baud, do_not_open=True)
serial_instance.dtr = False
serial_instance.rts = False
serial_instance.rts = True
serial_instance.open()
serial_instance.rts = False
# Read until example end and find the currently running partition string
content = serial_instance.read_until(b"Example end")
pattern = re.compile(b"Running partition: ([a-z0-9_]+)")
running = re.search(pattern, content).group(1)
return running.decode("utf-8")
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--port", default=None)
args = parser.parse_args()
try:
res = get_running_partition(args.port)
except Exception as e:
print(e.message)
sys.exit(1)
print(res)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,2 @@
idf_component_register(SRCS "otatool_main.c"
INCLUDE_DIRS ".")

View File

@@ -0,0 +1,4 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View File

@@ -0,0 +1,26 @@
/* OTA Tool example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include "esp_system.h"
#include "esp_log.h"
#include "esp_ota_ops.h"
#include "esp_partition.h"
static const char *TAG = "example";
void app_main(void)
{
ESP_LOGI(TAG, "OTA Tool Example");
const esp_partition_t *running = esp_ota_get_running_partition();
// Display the running partition
ESP_LOGI(TAG, "Running partition: %s", running->label);
ESP_LOGI(TAG, "Example end");
}

View File

@@ -0,0 +1,118 @@
#!/usr/bin/env python
#
# Demonstrates the use of otatool.py, a tool for performing ota partition level
# operations.
#
# Copyright 2018 Espressif Systems (Shanghai) PTE LTD
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http:#www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import sys
import argparse
from get_running_partition import get_running_partition
def assert_file_same(file1, file2, err):
with open(file1, "rb") as f1:
with open(file2, "rb") as f2:
f1 = f1.read()
f2 = f2.read()
if len(f1) < len(f2):
f2 = f2[:len(f1)]
else:
f1 = f1[:len(f2)]
if not f1 == f2:
raise Exception(err)
def assert_running_partition(expected, port=None):
running = get_running_partition(port)
if running != expected:
raise Exception("Running partition %s does not match expected %s" % (running, expected))
def main():
COMPONENTS_PATH = os.path.expandvars(os.path.join("$IDF_PATH", "components"))
OTATOOL_DIR = os.path.join(COMPONENTS_PATH, "app_update")
sys.path.append(OTATOOL_DIR)
from otatool import OtatoolTarget
parser = argparse.ArgumentParser("ESP-IDF OTA Tool Example")
parser.add_argument("--port", "-p", help="port where the device to perform operations on is connected")
parser.add_argument("--binary", "-b", help="path to built example binary", default=os.path.join("build", "otatool.bin"))
args = parser.parse_args()
target = OtatoolTarget(args.port)
print("Writing factory firmware to ota_0")
target.write_ota_partition(0, args.binary)
print("Writing factory firmware to ota_1")
target.write_ota_partition("ota_1", args.binary)
# Verify that the contents of the two ota slots are the same as that of the factory partition
print("Checking written firmware to ota_0 and ota_1 match factory firmware")
target.read_ota_partition("ota_0", "app0.bin")
target.read_ota_partition(1, "app1.bin")
assert_file_same("app0.bin", args.binary, "Slot 0 app does not match factory app")
assert_file_same("app1.bin", args.binary, "Slot 1 app does not match factory app")
# Switch to factory app
print("Switching to factory app")
target.erase_otadata()
assert_running_partition("factory")
# Switch to slot 0
print("Switching to OTA slot 0")
target.switch_ota_partition(0)
assert_running_partition("ota_0")
# Switch to slot 1 twice in a row
print("Switching to OTA slot 1 (twice in a row)")
target.switch_ota_partition(1)
assert_running_partition("ota_1")
target.switch_ota_partition("ota_1")
assert_running_partition("ota_1")
# Switch to slot 0 twice in a row
print("Switching to OTA slot 0 (twice in a row)")
target.switch_ota_partition(0)
assert_running_partition("ota_0")
target.switch_ota_partition("ota_0")
assert_running_partition("ota_0")
# Switch to factory app
print("Switching to factory app")
target.erase_otadata()
assert_running_partition("factory")
# Switch to slot 1
print("Switching to OTA slot 1")
target.switch_ota_partition(1)
assert_running_partition("ota_1")
# Example end and cleanup
print("\nOTA tool operations executed successfully!")
clean_files = ["app0.bin", "app1.bin"]
for clean_file in clean_files:
os.unlink(clean_file)
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,95 @@
#!/usr/bin/env bash
#
# Demonstrates command-line interface of OTA Partitions Tool, otatool.py
#
#
# $1 - serial port where target device to operate on is connnected to, by default the first found valid serial port
# $2 - path to this example's built binary file (parttool.bin), by default $PWD/build/otatool.bin
PORT=$1
OTATOOL_PY="python $IDF_PATH/components/app_update/otatool.py -q"
if [[ "$PORT" != "" ]]; then
OTATOOL_PY="$OTATOOL_PY --port $PORT"
fi
BINARY=$2
if [[ "$BINARY" == "" ]]; then
BINARY=build/otatool.bin
fi
function assert_file_same()
{
sz_a=$(stat -c %s $1)
sz_b=$(stat -c %s $2)
sz=$((sz_a < sz_b ? sz_a : sz_b))
res=$(cmp -s -n $sz $1 $2) ||
(echo "!!!!!!!!!!!!!!!!!!!"
echo "FAILURE: $3"
echo "!!!!!!!!!!!!!!!!!!!")
}
function assert_running_partition()
{
running=$(python get_running_partition.py)
if [[ "$running" != "$1" ]]; then
echo "!!!!!!!!!!!!!!!!!!!"
echo "FAILURE: Running partition '$running' does not match expected '$1'"
echo "!!!!!!!!!!!!!!!!!!!"
exit 1
fi
}
# Flash the example firmware to OTA partitions. The first write uses slot number to identify OTA
# partition, the second one uses the name.
echo "Writing factory firmware to ota_0"
$OTATOOL_PY write_ota_partition --slot 0 --input $BINARY
echo "Writing factory firmware to ota_1"
$OTATOOL_PY write_ota_partition --name ota_1 --input $BINARY
# Read back the written firmware
$OTATOOL_PY read_ota_partition --name ota_0 --output app0.bin
$OTATOOL_PY read_ota_partition --slot 1 --output app1.bin
assert_file_same $BINARY app0.bin "Slot 0 app does not match factory app"
assert_file_same $BINARY app1.bin "Slot 1 app does not match factory app"
# Switch to factory app
echo "Switching to factory app"
$OTATOOL_PY erase_otadata
assert_running_partition factory
# Switch to slot 0
echo "Switching to OTA slot 0"
$OTATOOL_PY switch_ota_partition --slot 0
assert_running_partition ota_0
# Switch to slot 1 twice in a row
echo "Switching to OTA slot 1 (twice in a row)"
$OTATOOL_PY switch_ota_partition --slot 1
assert_running_partition ota_1
$OTATOOL_PY switch_ota_partition --name ota_1
assert_running_partition ota_1
# Switch to slot 0 twice in a row
echo "Switching to OTA slot 0 (twice in a row)"
$OTATOOL_PY switch_ota_partition --slot 0
assert_running_partition ota_0
$OTATOOL_PY switch_ota_partition --name ota_0
assert_running_partition ota_0
# Switch to factory app
echo "Switching to factory app"
$OTATOOL_PY erase_otadata
assert_running_partition factory
# Switch to slot 1
echo "Switching to OTA slot 1"
$OTATOOL_PY switch_ota_partition --slot 1
assert_running_partition ota_1
# Example end and cleanup
printf "\nPartition tool operations performed successfully\n"
rm -rf app0.bin app1.bin

View File

@@ -0,0 +1,4 @@
# Default sdkconfig parameters to use the OTA
# partition table layout, with a 4MB flash size
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_PARTITION_TABLE_TWO_OTA=y