Merge branch 'feature/anti_rollback_exp' into 'master'
esp32: Add firmware version to app See merge request idf/esp-idf!3461
This commit is contained in:
commit
8a7b46aa90
|
@ -74,8 +74,8 @@ idf_get_git_revision()
|
||||||
# Check that the targets set in cache, sdkconfig, and in environment all match
|
# Check that the targets set in cache, sdkconfig, and in environment all match
|
||||||
idf_check_config_target()
|
idf_check_config_target()
|
||||||
|
|
||||||
## if project uses git, retrieve revision
|
## get PROJECT_VER
|
||||||
git_describe(PROJECT_VER "${CMAKE_CURRENT_SOURCE_DIR}")
|
app_get_revision("${CMAKE_SOURCE_DIR}")
|
||||||
|
|
||||||
# Add some idf-wide definitions
|
# Add some idf-wide definitions
|
||||||
idf_set_global_compile_options()
|
idf_set_global_compile_options()
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
set(COMPONENT_SRCS "esp_ota_ops.c")
|
set(COMPONENT_SRCS "esp_ota_ops.c"
|
||||||
|
"esp_app_desc.c")
|
||||||
set(COMPONENT_ADD_INCLUDEDIRS "include")
|
set(COMPONENT_ADD_INCLUDEDIRS "include")
|
||||||
|
|
||||||
set(COMPONENT_REQUIRES spi_flash partition_table)
|
set(COMPONENT_REQUIRES spi_flash partition_table bootloader_support)
|
||||||
set(COMPONENT_PRIV_REQUIRES bootloader_support)
|
|
||||||
|
|
||||||
register_component()
|
register_component()
|
||||||
|
|
||||||
|
set_source_files_properties(
|
||||||
|
SOURCE "esp_app_desc.c"
|
||||||
|
PROPERTIES COMPILE_DEFINITIONS
|
||||||
|
PROJECT_VER=\"${PROJECT_VER}\")
|
||||||
|
|
||||||
# Add custom target for generating empty otadata partition for flashing
|
# Add custom target for generating empty otadata partition for flashing
|
||||||
if(OTADATA_PARTITION_OFFSET AND OTADATA_PARTITION_SIZE)
|
if(OTADATA_PARTITION_OFFSET AND OTADATA_PARTITION_SIZE)
|
||||||
add_custom_command(OUTPUT "${IDF_BUILD_ARTIFACTS_DIR}/${BLANK_OTADATA_FILE}"
|
add_custom_command(OUTPUT "${IDF_BUILD_ARTIFACTS_DIR}/${BLANK_OTADATA_FILE}"
|
||||||
|
|
12
components/app_update/Kconfig.projbuild
Normal file
12
components/app_update/Kconfig.projbuild
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
menu "Application manager"
|
||||||
|
|
||||||
|
config APP_COMPILE_TIME_DATE
|
||||||
|
bool "Use time/date stamp for app"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
If set, then the app will be built with the current time/date stamp. It is stored in the app description structure.
|
||||||
|
If not set, time/date stamp will be excluded from app image.
|
||||||
|
This can be useful for getting the same binary image files made from the same source,
|
||||||
|
but at different times.
|
||||||
|
|
||||||
|
endmenu # "Application manager"
|
|
@ -34,5 +34,9 @@ erase_ota: erase_otadata
|
||||||
all: blank_ota_data
|
all: blank_ota_data
|
||||||
flash: blank_ota_data
|
flash: blank_ota_data
|
||||||
|
|
||||||
|
TMP_DEFINES := $(BUILD_DIR_BASE)/app_update/tmp_cppflags.txt
|
||||||
|
export TMP_DEFINES
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(BLANK_OTA_DATA_FILE)
|
rm -f $(BLANK_OTA_DATA_FILE)
|
||||||
|
rm -f $(TMP_DEFINES)
|
||||||
|
|
|
@ -3,3 +3,47 @@
|
||||||
#
|
#
|
||||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||||
|
|
||||||
|
# esp_app_desc structure is added as an undefined symbol because otherwise the
|
||||||
|
# linker will ignore this structure as it has no other files depending on it.
|
||||||
|
COMPONENT_ADD_LDFLAGS += -u esp_app_desc
|
||||||
|
|
||||||
|
ifndef IS_BOOTLOADER_BUILD
|
||||||
|
GET_PROJECT_VER ?=
|
||||||
|
ifeq ("${PROJECT_VER}", "")
|
||||||
|
ifeq ("$(wildcard ${PROJECT_PATH}/version.txt)","")
|
||||||
|
GET_PROJECT_VER := $(shell cd ${PROJECT_PATH} && git describe --always --tags --dirty || echo "Not found git repo")
|
||||||
|
ifeq ("${GET_PROJECT_VER}", "Not found git repo")
|
||||||
|
$(info Project do not have git repo, it needs to get PROJECT_VER from `git describe` command.)
|
||||||
|
GET_PROJECT_VER := ""
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
# read from version.txt
|
||||||
|
GET_PROJECT_VER := $(shell cat ${PROJECT_PATH}/version.txt)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
# If ``PROJECT_VER`` variable set in project Makefile file, its value will be used.
|
||||||
|
# Else, if the ``$PROJECT_PATH/version.txt`` exists, its contents will be used as ``PROJECT_VER``.
|
||||||
|
# Else, if the project is located inside a Git repository, the output of git describe will be used.
|
||||||
|
# Otherwise, ``PROJECT_VER`` will be empty.
|
||||||
|
|
||||||
|
ifeq ("${PROJECT_VER}", "")
|
||||||
|
PROJECT_VER:= $(GET_PROJECT_VER)
|
||||||
|
else
|
||||||
|
PROJECT_VER:= $(PROJECT_VER)
|
||||||
|
endif
|
||||||
|
$(info App "$(PROJECT_NAME)" version: $(PROJECT_VER))
|
||||||
|
|
||||||
|
NEW_DEFINES:= $(PROJECT_VER) $(PROJECT_NAME) $(IDF_VER)
|
||||||
|
ifeq ("$(wildcard ${TMP_DEFINES})","")
|
||||||
|
OLD_DEFINES:=
|
||||||
|
else
|
||||||
|
OLD_DEFINES:= $(shell cat $(TMP_DEFINES))
|
||||||
|
endif
|
||||||
|
|
||||||
|
# If NEW_DEFINES (PROJECT_VER, PROJECT_NAME) were changed then rebuild only esp_app_desc.
|
||||||
|
ifneq ("${NEW_DEFINES}", "${OLD_DEFINES}")
|
||||||
|
$(shell echo $(NEW_DEFINES) > $(TMP_DEFINES); rm -f esp_app_desc.o;)
|
||||||
|
endif
|
||||||
|
|
||||||
|
esp_app_desc.o: CPPFLAGS += -D PROJECT_VER=\"$(PROJECT_VER)\" -D PROJECT_NAME=\"$(PROJECT_NAME)\"
|
||||||
|
endif
|
||||||
|
|
49
components/app_update/esp_app_desc.c
Normal file
49
components/app_update/esp_app_desc.c
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright 2017-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.
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
// Application version info
|
||||||
|
const __attribute__((section(".rodata_desc"))) esp_app_desc_t esp_app_desc = {
|
||||||
|
.magic_word = ESP_APP_DESC_MAGIC_WORD,
|
||||||
|
.version = PROJECT_VER,
|
||||||
|
.project_name = PROJECT_NAME,
|
||||||
|
.idf_ver = IDF_VER,
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_SECURE_VERSION
|
||||||
|
.secure_version = CONFIG_APP_SECURE_VERSION,
|
||||||
|
#else
|
||||||
|
.secure_version = 0,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_APP_COMPILE_TIME_DATE
|
||||||
|
.time = __TIME__,
|
||||||
|
.date = __DATE__,
|
||||||
|
#else
|
||||||
|
.time = "",
|
||||||
|
.date = "",
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
_Static_assert(sizeof(PROJECT_VER) <= sizeof(esp_app_desc.version), "PROJECT_VER is longer than version field in structure");
|
||||||
|
_Static_assert(sizeof(IDF_VER) <= sizeof(esp_app_desc.idf_ver), "IDF_VER is longer than idf_ver field in structure");
|
||||||
|
_Static_assert(sizeof(PROJECT_NAME) <= sizeof(esp_app_desc.project_name), "PROJECT_NAME is longer than project_name field in structure");
|
||||||
|
|
||||||
|
const esp_app_desc_t *esp_ota_get_app_description(void)
|
||||||
|
{
|
||||||
|
return &esp_app_desc;
|
||||||
|
}
|
|
@ -576,3 +576,25 @@ const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t *
|
||||||
return default_ota;
|
return default_ota;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc)
|
||||||
|
{
|
||||||
|
if (partition == NULL || app_desc == NULL) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(partition->type != ESP_PARTITION_TYPE_APP) {
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t err = esp_partition_read(partition, sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t), app_desc, sizeof(esp_app_desc_t));
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (app_desc->magic_word != ESP_APP_DESC_MAGIC_WORD) {
|
||||||
|
return ESP_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_partition.h"
|
#include "esp_partition.h"
|
||||||
|
#include "esp_image_format.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@ -41,6 +42,14 @@ extern "C"
|
||||||
*/
|
*/
|
||||||
typedef uint32_t esp_ota_handle_t;
|
typedef uint32_t esp_ota_handle_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return esp_app_desc structure. This structure includes app version.
|
||||||
|
*
|
||||||
|
* Return description for running app.
|
||||||
|
* @return Pointer to esp_app_desc structure.
|
||||||
|
*/
|
||||||
|
const esp_app_desc_t *esp_ota_get_app_description(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Commence an OTA update writing to the specified partition.
|
* @brief Commence an OTA update writing to the specified partition.
|
||||||
|
|
||||||
|
@ -170,6 +179,22 @@ const esp_partition_t* esp_ota_get_running_partition(void);
|
||||||
*/
|
*/
|
||||||
const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t *start_from);
|
const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t *start_from);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns esp_app_desc structure for app partition. This structure includes app version.
|
||||||
|
*
|
||||||
|
* Returns a description for the requested app partition.
|
||||||
|
* @param[in] partition Pointer to app partition. (only app partition)
|
||||||
|
* @param[out] app_desc Structure of info about app.
|
||||||
|
* @return
|
||||||
|
* - ESP_OK Successful.
|
||||||
|
* - ESP_ERR_NOT_FOUND app_desc structure is not found. Magic word is incorrect.
|
||||||
|
* - ESP_ERR_NOT_SUPPORTED Partition is not application.
|
||||||
|
* - ESP_ERR_INVALID_ARG Arguments is NULL or if partition's offset exceeds partition size.
|
||||||
|
* - ESP_ERR_INVALID_SIZE Read would go out of bounds of the partition.
|
||||||
|
* - or one of error codes from lower-level flash driver.
|
||||||
|
*/
|
||||||
|
esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#include <unity.h>
|
#include <unity.h>
|
||||||
#include <test_utils.h>
|
#include <test_utils.h>
|
||||||
#include <esp_ota_ops.h>
|
#include <esp_ota_ops.h>
|
||||||
|
#include "bootloader_common.h"
|
||||||
|
|
||||||
/* These OTA tests currently don't assume an OTA partition exists
|
/* These OTA tests currently don't assume an OTA partition exists
|
||||||
on the device, so they're a bit limited
|
on the device, so they're a bit limited
|
||||||
|
@ -84,3 +84,26 @@ TEST_CASE("esp_ota_get_next_update_partition logic", "[ota]")
|
||||||
TEST_ASSERT_EQUAL_PTR(ota_0, p);
|
TEST_ASSERT_EQUAL_PTR(ota_0, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("esp_ota_get_partition_description ", "[ota]")
|
||||||
|
{
|
||||||
|
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||||
|
TEST_ASSERT_NOT_NULL(running);
|
||||||
|
esp_app_desc_t app_desc1, app_desc2;
|
||||||
|
TEST_ESP_OK(esp_ota_get_partition_description(running, &app_desc1));
|
||||||
|
const esp_partition_pos_t running_pos = {
|
||||||
|
.offset = running->address,
|
||||||
|
.size = running->size
|
||||||
|
};
|
||||||
|
TEST_ESP_OK(bootloader_common_get_partition_description(&running_pos, &app_desc2));
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_MEMORY_MESSAGE((uint8_t *)&app_desc1, (uint8_t *)&app_desc2, sizeof(app_desc1), "must be the same");
|
||||||
|
|
||||||
|
const esp_partition_t *not_app = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
||||||
|
TEST_ASSERT_NOT_NULL(not_app);
|
||||||
|
TEST_ESP_ERR(ESP_ERR_NOT_SUPPORTED, esp_ota_get_partition_description(not_app, &app_desc1));
|
||||||
|
const esp_partition_pos_t not_app_pos = {
|
||||||
|
.offset = not_app->address,
|
||||||
|
.size = not_app->size
|
||||||
|
};
|
||||||
|
TEST_ESP_ERR(ESP_ERR_NOT_FOUND, bootloader_common_get_partition_description(¬_app_pos, &app_desc1));
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "esp_flash_data_types.h"
|
#include "esp_flash_data_types.h"
|
||||||
|
#include "esp_image_format.h"
|
||||||
|
|
||||||
/// Type of hold a GPIO in low state
|
/// Type of hold a GPIO in low state
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -91,3 +92,17 @@ bool bootloader_common_label_search(const char *list, char *label);
|
||||||
* - ESP_FAIL: An allocation error occurred.
|
* - ESP_FAIL: An allocation error occurred.
|
||||||
*/
|
*/
|
||||||
esp_err_t bootloader_common_get_sha256_of_partition(uint32_t address, uint32_t size, int type, uint8_t *out_sha_256);
|
esp_err_t bootloader_common_get_sha256_of_partition(uint32_t address, uint32_t size, int type, uint8_t *out_sha_256);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns esp_app_desc structure for app partition. This structure includes app version.
|
||||||
|
*
|
||||||
|
* Returns a description for the requested app partition.
|
||||||
|
* @param[in] partition App partition description.
|
||||||
|
* @param[out] app_desc Structure of info about app.
|
||||||
|
* @return
|
||||||
|
* - ESP_OK: Successful.
|
||||||
|
* - ESP_ERR_INVALID_ARG: The arguments passed are not valid.
|
||||||
|
* - ESP_ERR_NOT_FOUND: app_desc structure is not found. Magic word is incorrect.
|
||||||
|
* - ESP_FAIL: mapping is fail.
|
||||||
|
*/
|
||||||
|
esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc);
|
||||||
|
|
|
@ -89,6 +89,25 @@ typedef struct {
|
||||||
uint32_t data_len;
|
uint32_t data_len;
|
||||||
} esp_image_segment_header_t;
|
} esp_image_segment_header_t;
|
||||||
|
|
||||||
|
#define ESP_APP_DESC_MAGIC_WORD 0xABCD5432 /*!< The magic word for the esp_app_desc structure that is in DROM. */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Description about application.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint32_t magic_word; /*!< Magic word ESP_APP_DESC_MAGIC_WORD */
|
||||||
|
uint32_t secure_version; /*!< Secure version */
|
||||||
|
uint32_t reserv1[2]; /*!< --- */
|
||||||
|
char version[32]; /*!< Application version */
|
||||||
|
char project_name[32]; /*!< Project name */
|
||||||
|
char time[16]; /*!< Compile time */
|
||||||
|
char date[16]; /*!< Compile date*/
|
||||||
|
char idf_ver[32]; /*!< Version IDF */
|
||||||
|
uint8_t app_elf_sha256[32]; /*!< sha256 of elf file */
|
||||||
|
uint32_t reserv2[20]; /*!< --- */
|
||||||
|
} esp_app_desc_t;
|
||||||
|
_Static_assert(sizeof(esp_app_desc_t) == 256, "esp_app_desc_t should be 256 bytes");
|
||||||
|
|
||||||
#define ESP_IMAGE_MAX_SEGMENTS 16
|
#define ESP_IMAGE_MAX_SEGMENTS 16
|
||||||
|
|
||||||
/* Structure to hold on-flash image metadata */
|
/* Structure to hold on-flash image metadata */
|
||||||
|
|
|
@ -192,3 +192,25 @@ esp_err_t bootloader_common_get_sha256_of_partition (uint32_t address, uint32_t
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc)
|
||||||
|
{
|
||||||
|
if (partition == NULL || app_desc == NULL || partition->offset == 0) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t *image = bootloader_mmap(partition->offset, partition->size);
|
||||||
|
if (image == NULL) {
|
||||||
|
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", partition->offset, partition->size);
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(app_desc, image + sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t), sizeof(esp_app_desc_t));
|
||||||
|
bootloader_munmap(image);
|
||||||
|
|
||||||
|
if (app_desc->magic_word != ESP_APP_DESC_MAGIC_WORD) {
|
||||||
|
return ESP_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -57,8 +57,9 @@ else()
|
||||||
set(COMPONENT_REQUIRES driver tcpip_adapter esp_event)
|
set(COMPONENT_REQUIRES driver tcpip_adapter esp_event)
|
||||||
# driver is a public requirement because esp_sleep.h uses gpio_num_t & touch_pad_t
|
# driver is a public requirement because esp_sleep.h uses gpio_num_t & touch_pad_t
|
||||||
# tcpip_adapter is a public requirement because esp_event.h uses tcpip_adapter types
|
# tcpip_adapter is a public requirement because esp_event.h uses tcpip_adapter types
|
||||||
|
# app_update is added here because cpu_start.c uses esp_ota_get_app_description() function.
|
||||||
set(COMPONENT_PRIV_REQUIRES
|
set(COMPONENT_PRIV_REQUIRES
|
||||||
app_trace bootloader_support ethernet log mbedtls nvs_flash
|
app_trace app_update bootloader_support ethernet log mbedtls nvs_flash
|
||||||
pthread smartconfig_ack spi_flash vfs wpa_supplicant xtensa-debug-module)
|
pthread smartconfig_ack spi_flash vfs wpa_supplicant xtensa-debug-module)
|
||||||
|
|
||||||
set(COMPONENT_ADD_LDFRAGMENTS linker.lf ld/esp32_fragments.lf)
|
set(COMPONENT_ADD_LDFRAGMENTS linker.lf ld/esp32_fragments.lf)
|
||||||
|
|
|
@ -71,6 +71,7 @@
|
||||||
#include "esp_pm.h"
|
#include "esp_pm.h"
|
||||||
#include "pm_impl.h"
|
#include "pm_impl.h"
|
||||||
#include "trax.h"
|
#include "trax.h"
|
||||||
|
#include "esp_ota_ops.h"
|
||||||
|
|
||||||
#define STRINGIFY(s) STRINGIFY2(s)
|
#define STRINGIFY(s) STRINGIFY2(s)
|
||||||
#define STRINGIFY2(s) #s
|
#define STRINGIFY2(s) #s
|
||||||
|
@ -175,6 +176,20 @@ void IRAM_ATTR call_start_cpu0()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ESP_EARLY_LOGI(TAG, "Pro cpu up.");
|
ESP_EARLY_LOGI(TAG, "Pro cpu up.");
|
||||||
|
#if LOG_LOCAL_LEVEL >= ESP_LOG_INFO
|
||||||
|
const esp_app_desc_t *app_desc = esp_ota_get_app_description();
|
||||||
|
ESP_EARLY_LOGI(TAG, "Application information:");
|
||||||
|
ESP_EARLY_LOGI(TAG, "Project name: %s", app_desc->project_name);
|
||||||
|
ESP_EARLY_LOGI(TAG, "App version: %s", app_desc->version);
|
||||||
|
#ifdef CONFIG_APP_SECURE_VERSION
|
||||||
|
ESP_EARLY_LOGI(TAG, "Secure version: %x", app_desc->secure_version);
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_APP_COMPILE_TIME_DATE
|
||||||
|
ESP_EARLY_LOGI(TAG, "Compile time: %s", app_desc->time);
|
||||||
|
ESP_EARLY_LOGI(TAG, "Compile date: %s", app_desc->date);
|
||||||
|
#endif
|
||||||
|
ESP_EARLY_LOGI(TAG, "ESP-IDF: %s", app_desc->idf_ver);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !CONFIG_FREERTOS_UNICORE
|
#if !CONFIG_FREERTOS_UNICORE
|
||||||
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_DIS_APP_CPU)) {
|
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_DIS_APP_CPU)) {
|
||||||
|
|
|
@ -252,6 +252,9 @@ SECTIONS
|
||||||
{
|
{
|
||||||
_rodata_start = ABSOLUTE(.);
|
_rodata_start = ABSOLUTE(.);
|
||||||
|
|
||||||
|
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
|
||||||
|
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
|
||||||
|
|
||||||
mapping[flash_rodata]
|
mapping[flash_rodata]
|
||||||
|
|
||||||
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
||||||
|
|
|
@ -319,12 +319,18 @@ The following component-specific variables are available for use inside componen
|
||||||
|
|
||||||
The following variables are set at the project level, but available for use in component CMakeLists:
|
The following variables are set at the project level, but available for use in component CMakeLists:
|
||||||
|
|
||||||
- ``PROJECT_NAME``: Name of the project, as set in project Makefile
|
- ``PROJECT_NAME``: Name of the project, as set in project CMakeLists.txt file.
|
||||||
- ``PROJECT_PATH``: Absolute path of the project directory containing the project Makefile. Same as the ``CMAKE_SOURCE_DIR`` variable.
|
- ``PROJECT_PATH``: Absolute path of the project directory containing the project Makefile. Same as the ``CMAKE_SOURCE_DIR`` variable.
|
||||||
- ``COMPONENTS``: Names of all components that are included in this build, formatted as a semicolon-delimited CMake list.
|
- ``COMPONENTS``: Names of all components that are included in this build, formatted as a semicolon-delimited CMake list.
|
||||||
- ``CONFIG_*``: Each value in the project configuration has a corresponding variable available in make. All names begin with ``CONFIG_``. :doc:`More information here </api-reference/kconfig>`.
|
- ``CONFIG_*``: Each value in the project configuration has a corresponding variable available in make. All names begin with ``CONFIG_``. :doc:`More information here </api-reference/kconfig>`.
|
||||||
- ``IDF_VER``: Git version of ESP-IDF (produced by ``git describe``)
|
- ``IDF_VER``: Git version of ESP-IDF (produced by ``git describe``)
|
||||||
- ``IDF_TARGET``: Name of the target for which the project is being built.
|
- ``IDF_TARGET``: Name of the target for which the project is being built.
|
||||||
|
- ``PROJECT_VER``: Project version.
|
||||||
|
|
||||||
|
* If ``PROJECT_VER`` variable set in project CMakeLists.txt file, its value will be used.
|
||||||
|
* Else, if the ``$PROJECT_PATH/version.txt`` exists, its contents will be used as ``PROJECT_VER``.
|
||||||
|
* Else, if the project is located inside a Git repository, the output of git describe will be used.
|
||||||
|
* Otherwise, ``PROJECT_VER`` will be empty.
|
||||||
|
|
||||||
If you modify any of these variables inside ``CMakeLists.txt`` then this will not prevent other components from building but it may make your component hard to build and/or debug.
|
If you modify any of these variables inside ``CMakeLists.txt`` then this will not prevent other components from building but it may make your component hard to build and/or debug.
|
||||||
|
|
||||||
|
@ -403,6 +409,8 @@ The ESP-IDF build system adds the following C preprocessor definitions on the co
|
||||||
|
|
||||||
- ``ESP_PLATFORM`` — Can be used to detect that build happens within ESP-IDF.
|
- ``ESP_PLATFORM`` — Can be used to detect that build happens within ESP-IDF.
|
||||||
- ``IDF_VER`` — Defined to a git version string. E.g. ``v2.0`` for a tagged release or ``v1.0-275-g0efaa4f`` for an arbitrary commit.
|
- ``IDF_VER`` — Defined to a git version string. E.g. ``v2.0`` for a tagged release or ``v1.0-275-g0efaa4f`` for an arbitrary commit.
|
||||||
|
- ``PROJECT_VER``: The project version, see `Preset Component Variables`_ for more details.
|
||||||
|
- ``PROJECT_NAME``: Name of the project, as set in project CMakeLists.txt file.
|
||||||
|
|
||||||
Component Requirements
|
Component Requirements
|
||||||
======================
|
======================
|
||||||
|
|
|
@ -187,6 +187,12 @@ The following variables are set at the project level, but exported for use in th
|
||||||
- ``CC``, ``LD``, ``AR``, ``OBJCOPY``: Full paths to each tool from the gcc xtensa cross-toolchain.
|
- ``CC``, ``LD``, ``AR``, ``OBJCOPY``: Full paths to each tool from the gcc xtensa cross-toolchain.
|
||||||
- ``HOSTCC``, ``HOSTLD``, ``HOSTAR``: Full names of each tool from the host native toolchain.
|
- ``HOSTCC``, ``HOSTLD``, ``HOSTAR``: Full names of each tool from the host native toolchain.
|
||||||
- ``IDF_VER``: ESP-IDF version, retrieved from either ``$(IDF_PATH)/version.txt`` file (if present) else using git command ``git describe``. Recommended format here is single liner that specifies major IDF release version, e.g. ``v2.0`` for a tagged release or ``v2.0-275-g0efaa4f`` for an arbitrary commit. Application can make use of this by calling :cpp:func:`esp_get_idf_version`.
|
- ``IDF_VER``: ESP-IDF version, retrieved from either ``$(IDF_PATH)/version.txt`` file (if present) else using git command ``git describe``. Recommended format here is single liner that specifies major IDF release version, e.g. ``v2.0`` for a tagged release or ``v2.0-275-g0efaa4f`` for an arbitrary commit. Application can make use of this by calling :cpp:func:`esp_get_idf_version`.
|
||||||
|
- ``PROJECT_VER``: Project version.
|
||||||
|
|
||||||
|
* If ``PROJECT_VER`` variable set in project Makefile file, its value will be used.
|
||||||
|
* Else, if the ``$PROJECT_PATH/version.txt`` exists, its contents will be used as ``PROJECT_VER``.
|
||||||
|
* Else, if the project is located inside a Git repository, the output of git describe will be used.
|
||||||
|
* Otherwise, ``PROJECT_VER`` will be empty.
|
||||||
|
|
||||||
If you modify any of these variables inside ``component.mk`` then this will not prevent other components from building but it may make your component hard to build and/or debug.
|
If you modify any of these variables inside ``component.mk`` then this will not prevent other components from building but it may make your component hard to build and/or debug.
|
||||||
|
|
||||||
|
@ -302,6 +308,8 @@ ESP-IDF build systems adds the following C preprocessor definitions on the comma
|
||||||
|
|
||||||
- ``ESP_PLATFORM`` — Can be used to detect that build happens within ESP-IDF.
|
- ``ESP_PLATFORM`` — Can be used to detect that build happens within ESP-IDF.
|
||||||
- ``IDF_VER`` — ESP-IDF version, see `Preset Component Variables`_ for more details.
|
- ``IDF_VER`` — ESP-IDF version, see `Preset Component Variables`_ for more details.
|
||||||
|
- ``PROJECT_VER``: The project version, see `Preset Component Variables`_ for more details.
|
||||||
|
- ``PROJECT_NAME``: Name of the project, as set in project Makefile.
|
||||||
|
|
||||||
Build Process Internals
|
Build Process Internals
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
|
@ -109,6 +109,17 @@ SDK version
|
||||||
|
|
||||||
:cpp:func:`esp_get_idf_version` returns a string describing the IDF version which was used to compile the application. This is the same value as the one available through ``IDF_VER`` variable of the build system. The version string generally has the format of ``git describe`` output.
|
:cpp:func:`esp_get_idf_version` returns a string describing the IDF version which was used to compile the application. This is the same value as the one available through ``IDF_VER`` variable of the build system. The version string generally has the format of ``git describe`` output.
|
||||||
|
|
||||||
|
App version
|
||||||
|
-----------
|
||||||
|
Application version is stored in :cpp:class:`esp_app_desc_t` structure. It is located in DROM sector and has a fixed offset from the beginning of the binary file.
|
||||||
|
The structure is located after :cpp:class:`esp_image_header_t` and :cpp:class:`esp_image_segment_header_t` structures. The field version has string type and max length 32 chars.
|
||||||
|
|
||||||
|
To set version in your project manually you need set ``PROJECT_VER`` varible in your project Makefile/CMakeLists.txt:
|
||||||
|
|
||||||
|
* For Make build system: in application Makefile put ``PROJECT_VER = "0.1.0.1"`` before including project.mk
|
||||||
|
* For Cmake build system: in application CMakeLists.txt put ``set(PROJECT_VER "0.1.0.1")`` before including project.cmake.
|
||||||
|
|
||||||
|
If ``PROJECT_VER`` variable did not set in project Makefile/CMakeLists.txt then it can retrieved from either ``$(PROJECT_PATH)/version.txt`` file (if present) else using git command ``git describe``. Application can make use of this by calling :cpp:func:`esp_ota_get_app_description` or :cpp:func:`esp_ota_get_partition_description` functions.
|
||||||
|
|
||||||
API Reference
|
API Reference
|
||||||
-------------
|
-------------
|
||||||
|
|
|
@ -278,6 +278,10 @@ LDFLAGS ?= -nostdlib \
|
||||||
CPPFLAGS ?=
|
CPPFLAGS ?=
|
||||||
EXTRA_CPPFLAGS ?=
|
EXTRA_CPPFLAGS ?=
|
||||||
CPPFLAGS := -DESP_PLATFORM -D IDF_VER=\"$(IDF_VER)\" -MMD -MP $(CPPFLAGS) $(EXTRA_CPPFLAGS)
|
CPPFLAGS := -DESP_PLATFORM -D IDF_VER=\"$(IDF_VER)\" -MMD -MP $(CPPFLAGS) $(EXTRA_CPPFLAGS)
|
||||||
|
PROJECT_VER ?=
|
||||||
|
export IDF_VER
|
||||||
|
export PROJECT_NAME
|
||||||
|
export PROJECT_VER
|
||||||
|
|
||||||
# Warnings-related flags relevant both for C and C++
|
# Warnings-related flags relevant both for C and C++
|
||||||
COMMON_WARNING_FLAGS = -Wall -Werror=all \
|
COMMON_WARNING_FLAGS = -Wall -Werror=all \
|
||||||
|
|
|
@ -224,6 +224,7 @@ function run_tests()
|
||||||
clean_build_dir
|
clean_build_dir
|
||||||
# Make provision for getting IDF version
|
# Make provision for getting IDF version
|
||||||
echo "custom-version-x.y" > ${IDF_PATH}/version.txt
|
echo "custom-version-x.y" > ${IDF_PATH}/version.txt
|
||||||
|
echo "project-version-w.z" > ${TESTDIR}/template/version.txt
|
||||||
# Hide .gitmodules so that submodule check is avoided
|
# Hide .gitmodules so that submodule check is avoided
|
||||||
[ -f ${IDF_PATH}/.gitmodules ] && mv ${IDF_PATH}/.gitmodules ${IDF_PATH}/.gitmodules_backup
|
[ -f ${IDF_PATH}/.gitmodules ] && mv ${IDF_PATH}/.gitmodules ${IDF_PATH}/.gitmodules_backup
|
||||||
# Overload `git` command
|
# Overload `git` command
|
||||||
|
@ -234,9 +235,24 @@ function run_tests()
|
||||||
make
|
make
|
||||||
[ -f ${IDF_PATH}/git_invoked ] && rm ${IDF_PATH}/git_invoked && failure "git should not have been invoked in this case"
|
[ -f ${IDF_PATH}/git_invoked ] && rm ${IDF_PATH}/git_invoked && failure "git should not have been invoked in this case"
|
||||||
rm -f ${IDF_PATH}/version.txt git
|
rm -f ${IDF_PATH}/version.txt git
|
||||||
|
rm -f ${TESTDIR}/template/version.txt
|
||||||
[ -f ${IDF_PATH}/.gitmodules_backup ] && mv ${IDF_PATH}/.gitmodules_backup ${IDF_PATH}/.gitmodules
|
[ -f ${IDF_PATH}/.gitmodules_backup ] && mv ${IDF_PATH}/.gitmodules_backup ${IDF_PATH}/.gitmodules
|
||||||
export PATH=$OLD_PATH
|
export PATH=$OLD_PATH
|
||||||
|
|
||||||
|
print_status "Rebuild when app version was changed"
|
||||||
|
take_build_snapshot
|
||||||
|
# App version
|
||||||
|
echo "project-version-1.0" > ${TESTDIR}/template/version.txt
|
||||||
|
make
|
||||||
|
assert_rebuilt ${APP_BINS}
|
||||||
|
print_status "Change app version"
|
||||||
|
take_build_snapshot
|
||||||
|
echo "project-version-2.0" > ${TESTDIR}/template/version.txt
|
||||||
|
make
|
||||||
|
assert_rebuilt ${APP_BINS}
|
||||||
|
assert_not_rebuilt ${BOOTLOADER_BINS} esp32/libesp32.a
|
||||||
|
rm -f ${TESTDIR}/template/version.txt
|
||||||
|
|
||||||
print_status "Build fails if partitions don't fit in flash"
|
print_status "Build fails if partitions don't fit in flash"
|
||||||
cp sdkconfig sdkconfig.bak
|
cp sdkconfig sdkconfig.bak
|
||||||
sed -i "s/CONFIG_ESPTOOLPY_FLASHSIZE.\+//" sdkconfig # remove all flashsize config
|
sed -i "s/CONFIG_ESPTOOLPY_FLASHSIZE.\+//" sdkconfig # remove all flashsize config
|
||||||
|
@ -278,7 +294,6 @@ mkdir -p ${TESTDIR}
|
||||||
SNAPSHOT=${TESTDIR}/snapshot
|
SNAPSHOT=${TESTDIR}/snapshot
|
||||||
BUILD=${TESTDIR}/template/build
|
BUILD=${TESTDIR}/template/build
|
||||||
|
|
||||||
|
|
||||||
# copy all the build output to a snapshot directory
|
# copy all the build output to a snapshot directory
|
||||||
function take_build_snapshot()
|
function take_build_snapshot()
|
||||||
{
|
{
|
||||||
|
|
|
@ -96,6 +96,19 @@ function run_tests()
|
||||||
idf.py build || failure "Partial build failed"
|
idf.py build || failure "Partial build failed"
|
||||||
assert_not_rebuilt ${ALL_BUILD_FILES}
|
assert_not_rebuilt ${ALL_BUILD_FILES}
|
||||||
|
|
||||||
|
print_status "Rebuild when app version was changed"
|
||||||
|
clean_build_dir
|
||||||
|
# App version
|
||||||
|
echo "project-version-1.0" > ${TESTDIR}/template/version.txt
|
||||||
|
idf.py build || failure "Failed to build with app version"
|
||||||
|
print_status "Change app version"
|
||||||
|
take_build_snapshot
|
||||||
|
echo "project-version-2.0" > ${TESTDIR}/template/version.txt
|
||||||
|
idf.py build || failure "Failed to rebuild with changed app version"
|
||||||
|
assert_rebuilt ${APP_BINS}
|
||||||
|
assert_not_rebuilt ${BOOTLOADER_BINS} esp-idf/esp32/libesp32.a
|
||||||
|
rm -f ${TESTDIR}/template/version.txt
|
||||||
|
|
||||||
print_status "Moving BUILD_DIR_BASE out of tree"
|
print_status "Moving BUILD_DIR_BASE out of tree"
|
||||||
clean_build_dir
|
clean_build_dir
|
||||||
OUTOFTREE_BUILD=${TESTDIR}/alt_build
|
OUTOFTREE_BUILD=${TESTDIR}/alt_build
|
||||||
|
|
|
@ -86,6 +86,7 @@ function(idf_set_global_compile_options)
|
||||||
list(APPEND compile_options "${CMAKE_C_FLAGS}")
|
list(APPEND compile_options "${CMAKE_C_FLAGS}")
|
||||||
list(APPEND c_compile_options "${CMAKE_C_FLAGS}")
|
list(APPEND c_compile_options "${CMAKE_C_FLAGS}")
|
||||||
list(APPEND cxx_compile_options "${CMAKE_CXX_FLAGS}")
|
list(APPEND cxx_compile_options "${CMAKE_CXX_FLAGS}")
|
||||||
|
add_definitions(-DPROJECT_NAME=\"${PROJECT_NAME}\")
|
||||||
|
|
||||||
if(CONFIG_OPTIMIZATION_LEVEL_RELEASE)
|
if(CONFIG_OPTIMIZATION_LEVEL_RELEASE)
|
||||||
list(APPEND compile_options "-Os")
|
list(APPEND compile_options "-Os")
|
||||||
|
@ -207,16 +208,42 @@ endfunction()
|
||||||
# Running git_describe() here automatically triggers rebuilds
|
# Running git_describe() here automatically triggers rebuilds
|
||||||
# if the ESP-IDF git version changes
|
# if the ESP-IDF git version changes
|
||||||
function(idf_get_git_revision)
|
function(idf_get_git_revision)
|
||||||
|
git_describe(IDF_VER_GIT "${IDF_PATH}")
|
||||||
if(EXISTS "${IDF_PATH}/version.txt")
|
if(EXISTS "${IDF_PATH}/version.txt")
|
||||||
file(STRINGS "${IDF_PATH}/version.txt" IDF_VER)
|
file(STRINGS "${IDF_PATH}/version.txt" IDF_VER)
|
||||||
|
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${IDF_PATH}/version.txt")
|
||||||
else()
|
else()
|
||||||
git_describe(IDF_VER "${IDF_PATH}")
|
set(IDF_VER ${IDF_VER_GIT})
|
||||||
endif()
|
endif()
|
||||||
|
message(STATUS "IDF_VER: ${IDF_VER}")
|
||||||
add_definitions(-DIDF_VER=\"${IDF_VER}\")
|
add_definitions(-DIDF_VER=\"${IDF_VER}\")
|
||||||
git_submodule_check("${IDF_PATH}")
|
git_submodule_check("${IDF_PATH}")
|
||||||
set(IDF_VER ${IDF_VER} PARENT_SCOPE)
|
set(IDF_VER ${IDF_VER} PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
# app_get_revision
|
||||||
|
#
|
||||||
|
# Set global PROJECT_VER
|
||||||
|
#
|
||||||
|
# If PROJECT_VER variable set in project CMakeLists.txt file, its value will be used.
|
||||||
|
# Else, if the _project_path/version.txt exists, its contents will be used as PROJECT_VER.
|
||||||
|
# Else, if the project is located inside a Git repository, the output of git describe will be used.
|
||||||
|
# Otherwise, PROJECT_VER will be empty.
|
||||||
|
function(app_get_revision _project_path)
|
||||||
|
git_describe(PROJECT_VER_GIT "${_project_path}")
|
||||||
|
if(NOT DEFINED PROJECT_VER)
|
||||||
|
if(EXISTS "${_project_path}/version.txt")
|
||||||
|
file(STRINGS "${_project_path}/version.txt" PROJECT_VER)
|
||||||
|
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${_project_path}/version.txt")
|
||||||
|
else()
|
||||||
|
set(PROJECT_VER ${PROJECT_VER_GIT})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
message(STATUS "Project version: ${PROJECT_VER}")
|
||||||
|
git_submodule_check("${_project_path}")
|
||||||
|
set(PROJECT_VER ${PROJECT_VER} PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
# idf_link_components
|
# idf_link_components
|
||||||
#
|
#
|
||||||
# Link library components to the target
|
# Link library components to the target
|
||||||
|
|
Loading…
Reference in a new issue