Merge branch 'feature/partition_api_example' into 'master'

Add partition API examples

See merge request idf/esp-idf!3427
This commit is contained in:
Ivan Grokhotkov 2018-11-06 12:24:27 +08:00
commit 85d63871ab
24 changed files with 465 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(partition_find)

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 := partition_find
include $(IDF_PATH)/make/project.mk

View file

@ -0,0 +1,57 @@
# Finding Partitions Example
This example demonstrates how to use the partition API functions `esp_partition_find` and `esp_partition_find_first` to search the device partition table.
These functions return the matching partitions given a set of constraints. By constraints we simply mean
properties that returned results should match - notably partition type, subtype and label/name. In the case of `esp_partition_find_first`, the first matching instance is returned;
for `esp_partition_find`, an iterator is returned iterating over matching instances.
# Example Flow
The example uses a [custom partition table](./partitions_example.csv). The first part uses `esp_partition_find_first` to search for partition instances
using two constraints - type and subtype. However, the partition table contains partitions with same type/subtype combination. In order to differentiate these partitions,
a third constraint - the label, is specified.
The second part shows how to iterate over partitions that match certain constraints, manually checking the properties of each iterated partition.
The iterator is obtained using `esp_partition_find` and is released after its use to avoid memory leaks.
### Output
```
I (310) example: Printing partition table csv file contents for reference...
# Name, Type, SubType, Offset, Size, Flags
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1M,
storage1, data, fat, , 0x40000,
storage2, data, fat, , 0x40000,
I (350) example: ----------------Find partitions---------------
I (350) example: Find partition with type ESP_PARTITION_TYPE_DATA, subtype ESP_PARTITION_SUBTYPE_DATA_NVS, label NULL (unspecified)...
I (370) example: found partition 'nvs' at offset 0x9000 with size 0x6000
I (370) example: Find partition with type ESP_PARTITION_TYPE_DATA, subtype ESP_PARTITION_SUBTYPE_DATA_PHY, label NULL (unspecified)...
I (390) example: found partition 'phy_init' at offset 0xf000 with size 0x1000
I (390) example: Find partition with type ESP_PARTITION_TYPE_APP, subtype ESP_PARTITION_SUBTYPE_APP_FACTORY, label NULL (unspecified)...
I (410) example: found partition 'factory' at offset 0x10000 with size 0x100000
I (410) example: Find partition with type ESP_PARTITION_TYPE_DATA, subtype ESP_PARTITION_SUBTYPE_DATA_FAT, label NULL (unspecified)...
I (430) example: found partition 'storage1' at offset 0x110000 with size 0x40000
I (440) example: Find second FAT partition by specifying the label
I (440) example: Find partition with type ESP_PARTITION_TYPE_DATA, subtype ESP_PARTITION_SUBTYPE_DATA_FAT, label storage2...
I (450) example: found partition 'storage2' at offset 0x150000 with size 0x40000
I (460) example: ----------------Iterate through partitions---------------
I (470) example: Iterating through app partitions...
I (480) example: found partition 'factory' at offset 0x10000 with size 0x100000
I (480) example: Iterating through data partitions...
I (490) example: found partition 'nvs' at offset 0x9000 with size 0x6000
I (500) example: found partition 'phy_init' at offset 0xf000 with size 0x1000
I (500) example: found partition 'storage1' at offset 0x110000 with size 0x40000
I (510) example: found partition 'storage2' at offset 0x150000 with size 0x40000
I (520) example: Example end
```
# Others
Detailed functional description of partition API is provided in [documentation](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/storage/spi_flash.html).
See the README.md file in the upper level 'examples' directory for more information about examples.

View file

@ -0,0 +1,6 @@
set(COMPONENT_SRCS "main.c")
set(COMPONENT_ADD_INCLUDEDIRS ".")
set(COMPONENT_EMBED_TXTFILES ../partitions_example.csv)
register_component()

View file

@ -0,0 +1,10 @@
#
# Main component makefile.
#
# This Makefile can be left empty. By default, it will take the sources in the
# src/ directory, compile them and link them into lib(subdirectory_name).a
# in the build directory. This behaviour is entirely configurable,
# please read the ESP-IDF documents if you need to do this.
#
COMPONENT_EMBED_TXTFILES := ../partitions_example.csv

View file

@ -0,0 +1,120 @@
/* Finding Partitions 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 <string.h>
#include <assert.h>
#include "esp_partition.h"
#include "esp_log.h"
static const char *TAG = "example";
// Get the string name of type enum values used in this example
static const char* get_type_str(esp_partition_type_t type)
{
switch(type) {
case ESP_PARTITION_TYPE_APP:
return "ESP_PARTITION_TYPE_APP";
case ESP_PARTITION_TYPE_DATA:
return "ESP_PARTITION_TYPE_DATA";
default:
return "UNKNOWN_PARTITION_TYPE"; // type not used in this example
}
}
// Get the string name of subtype enum values used in this example
static const char* get_subtype_str(esp_partition_subtype_t subtype)
{
switch(subtype) {
case ESP_PARTITION_SUBTYPE_DATA_NVS:
return "ESP_PARTITION_SUBTYPE_DATA_NVS";
case ESP_PARTITION_SUBTYPE_DATA_PHY:
return "ESP_PARTITION_SUBTYPE_DATA_PHY";
case ESP_PARTITION_SUBTYPE_APP_FACTORY:
return "ESP_PARTITION_SUBTYPE_APP_FACTORY";
case ESP_PARTITION_SUBTYPE_DATA_FAT:
return "ESP_PARTITION_SUBTYPE_DATA_FAT";
default:
return "UNKNOWN_PARTITION_SUBTYPE"; // subtype not used in this example
}
}
// Find the partition using given parameters
static void find_partition(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* name)
{
ESP_LOGI(TAG, "Find partition with type %s, subtype %s, label %s...", get_type_str(type), get_subtype_str(subtype),
name == NULL ? "NULL (unspecified)" : name);
const esp_partition_t * part = esp_partition_find_first(type, subtype, name);
ESP_LOGI(TAG, "\tfound partition '%s' at offset 0x%x with size 0x%x", part->label, part->address, part->size);
}
void app_main(void)
{
/*
* This example uses the partition table from ../partitions_example.csv. For reference, its contents are as follows:
*
* nvs, data, nvs, 0x9000, 0x6000,
* phy_init, data, phy, 0xf000, 0x1000,
* factory, app, factory, 0x10000, 1M,
* storage1, data, fat, , 0x40000,
* storage2, data, fat, , 0x40000,
*
* Display the partition table to the user for reference.
*/
extern const char csv_start[] asm("_binary_partitions_example_csv_start");
extern const char csv_end[] asm("_binary_partitions_example_csv_end");
ESP_LOGI(TAG, "Printing partition table csv file contents for reference...\n\n%.*s", csv_end - csv_start + 1, csv_start);
/* First Part - Finding partitions using esp_partition_find_first. */
ESP_LOGI(TAG, "----------------Find partitions---------------");
// Find partitions using esp_partition_find_first(). This returns the first partition matching the passed constraints.
find_partition(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL);
find_partition(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_PHY, NULL);
find_partition(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
find_partition(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, NULL);
ESP_LOGI(TAG, "Find second FAT partition by specifying the label");
// In case of multiple matches, `esp_partition_find_first` returns the first match.
find_partition(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_FAT, "storage2");
/* Second Part - Iterating over partitions */
ESP_LOGI(TAG, "----------------Iterate through partitions---------------");
esp_partition_iterator_t it;
ESP_LOGI(TAG, "Iterating through app partitions...");
it = esp_partition_find(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL);
// Loop through all matching partitions, in this case, all with the type 'data' until partition with desired
// label is found. Verify if its the same instance as the one found before.
for (; it != NULL; it = esp_partition_next(it)) {
const esp_partition_t *part = esp_partition_get(it);
ESP_LOGI(TAG, "\tfound partition '%s' at offset 0x%x with size 0x%x", part->label, part->address, part->size);
}
// Release the partition iterator to release memory allocated for it
esp_partition_iterator_release(it);
ESP_LOGI(TAG, "Iterating through data partitions...");
it = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, NULL);
// Loop through all matching partitions, in this case, all with the type 'data' until partition with desired
// label is found. Verify if its the same instance as the one found before.
for (; it != NULL; it = esp_partition_next(it)) {
const esp_partition_t *part = esp_partition_get(it);
ESP_LOGI(TAG, "\tfound partition '%s' at offset 0x%x with size 0x%x", part->label, part->address, part->size);
}
// Release the partition iterator to release memory allocated for it
esp_partition_iterator_release(it);
ESP_LOGI(TAG, "Example end");
}

View file

@ -0,0 +1,7 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1M,
storage1, data, fat, , 0x40000,
storage2, data, fat, , 0x40000,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
3 nvs, data, nvs, 0x9000, 0x6000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 1M,
6 storage1, data, fat, , 0x40000,
7 storage2, data, fat, , 0x40000,

View file

@ -0,0 +1,5 @@
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv"
CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000
CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv"
CONFIG_APP_OFFSET=0x10000

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(partition_mmap)

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 := partition_mmap
include $(IDF_PATH)/make/project.mk

View file

@ -0,0 +1,27 @@
# Partition Memory Map Example
This example demonstrates how to use `esp_partition_mmap` to configure MMU and map a partition into memory address space for read operations.
# Example Flow
The example uses a [custom partition table](./partitions_example.csv), with a data partition `storage` used for demonstration. Before mapping this partition to memory,
data is written to the partition used for verification.
The partition API function `esp_partition_mmap` is used to get a pointer to the mapped memory region and a handle to the mapping. The pointer is used to transparently read back the
verification data written previously. Once the data written and read are verified to be the same, the function `spi_flash_munmap` is used to release the mapping.
### Output
```
I (309) example: Written sample data to partition: ESP-IDF Partition Memory Map Example
I (309) example: Mapped partition to data memory address 0x3f410000
I (319) example: Read sample data from partition using mapped memory: ESP-IDF Partition Memory Map Example
I (329) example: Data matches
I (329) example: Unmapped partition from data memory
I (339) example: Example end
```
# Others
Detailed functional description of partition API is provided in [documentation](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/storage/spi_flash.html).
See the README.md file in the upper level 'examples' directory for more information about examples.

View file

@ -0,0 +1,4 @@
set(COMPONENT_SRCS "main.c")
set(COMPONENT_ADD_INCLUDEDIRS ".")
register_component()

View file

@ -0,0 +1,8 @@
#
# Main component makefile.
#
# This Makefile can be left empty. By default, it will take the sources in the
# src/ directory, compile them and link them into lib(subdirectory_name).a
# in the build directory. This behaviour is entirely configurable,
# please read the ESP-IDF documents if you need to do this.
#

View file

@ -0,0 +1,58 @@
/* Finding Partitions 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 <string.h>
#include <assert.h>
#include "esp_partition.h"
#include "esp_log.h"
static const char *TAG = "example";
void app_main(void)
{
/*
* This example uses the partition table from ../partitions_example.csv. For reference, its contents are as follows:
*
* nvs, data, nvs, 0x9000, 0x6000,
* phy_init, data, phy, 0xf000, 0x1000,
* factory, app, factory, 0x10000, 1M,
* storage, data, , , 0x40000,
*/
// Find the partition map in the partition table
const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
assert(partition != NULL);
static const char store_data[] = "ESP-IDF Partition Memory Map Example";
// Prepare data to be read later using the mapped address
ESP_ERROR_CHECK(esp_partition_erase_range(partition, 0, partition->size));
ESP_ERROR_CHECK(esp_partition_write(partition, 0, store_data, sizeof(store_data)));
ESP_LOGI(TAG, "Written sample data to partition: %s", store_data);
const void *map_ptr;
spi_flash_mmap_handle_t map_handle;
// Map the partition to data memory
ESP_ERROR_CHECK(esp_partition_mmap(partition, 0, partition->size, SPI_FLASH_MMAP_DATA, &map_ptr, &map_handle));
ESP_LOGI(TAG, "Mapped partition to data memory address %p", map_ptr);
// Read back the written verification data using the mapped memory pointer
char read_data[sizeof(store_data)];
memcpy(read_data, map_ptr, sizeof(read_data));
ESP_LOGI(TAG, "Read sample data from partition using mapped memory: %s", (char*) read_data);
assert(strcmp(store_data, read_data) == 0);
ESP_LOGI(TAG, "Data matches");
// Unmap mapped memory
spi_flash_munmap(map_handle);
ESP_LOGI(TAG, "Unmapped partition from data memory");
ESP_LOGI(TAG, "Example end");
}

View file

@ -0,0 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1M,
storage, data, , , 0x40000,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
3 nvs, data, nvs, 0x9000, 0x6000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 1M,
6 storage, data, , , 0x40000,

View file

@ -0,0 +1,5 @@
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv"
CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000
CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv"
CONFIG_APP_OFFSET=0x10000

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(partition_ops)

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 := partition_ops
include $(IDF_PATH)/make/project.mk

View file

@ -0,0 +1,25 @@
# Partition Read, Write, Erase Example
This example demonstrates how to perform partition read, write and erase operations using API functions `esp_partition_read`, `esp_partition_write` and `esp_partition_erase`.
# Example Flow
The example uses a [custom partition table](./partitions_example.csv), with a data partition `storage` used as the demo partition. For the most part the example code is well-commented so users should be able to follow along the code easily. Nevertheless, this section provides an overview of the code flow.
The partition table is searched for the `storage` partition. Once found, the entire partition is erased using `esp_partition_erase_range`. Sample data is written using `esp_partition_write`
and read back using `esp_partition_read`, verifying the read and written data match. The partition is erased once again using `esp_partition_erase_range`, limited to the sector the sample data was written to.
### Output
```
I (588) example: Written data: ESP-IDF Partition Operations Example (Read, Erase, Write)
I (588) example: Read data: ESP-IDF Partition Operations Example (Read, Erase, Write)
I (638) example: Erased data
I (638) example: Example end
```
# Others
Detailed functional description of partition API is provided in [documentation](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/storage/spi_flash.html).
See the README.md file in the upper level 'examples' directory for more information about examples.

View file

@ -0,0 +1,4 @@
set(COMPONENT_SRCS "main.c")
set(COMPONENT_ADD_INCLUDEDIRS ".")
register_component()

View file

@ -0,0 +1,8 @@
#
# Main component makefile.
#
# This Makefile can be left empty. By default, it will take the sources in the
# src/ directory, compile them and link them into lib(subdirectory_name).a
# in the build directory. This behaviour is entirely configurable,
# please read the ESP-IDF documents if you need to do this.
#

View file

@ -0,0 +1,59 @@
/* Finding Partitions 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 <string.h>
#include <assert.h>
#include "esp_partition.h"
#include "esp_log.h"
static const char *TAG = "example";
void app_main(void)
{
/*
* This example uses the partition table from ../partitions_example.csv. For reference, its contents are as follows:
*
* nvs, data, nvs, 0x9000, 0x6000,
* phy_init, data, phy, 0xf000, 0x1000,
* factory, app, factory, 0x10000, 1M,
* storage, data, , , 0x40000,
*/
// Find the partition map in the partition table
const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
assert(partition != NULL);
static char store_data[] = "ESP-IDF Partition Operations Example (Read, Erase, Write)";
static char read_data[sizeof(store_data)];
// Erase entire partition
memset(read_data, 0xFF, sizeof(read_data));
ESP_ERROR_CHECK(esp_partition_erase_range(partition, 0, partition->size));
// Write the data, starting from the beginning of the partition
ESP_ERROR_CHECK(esp_partition_write(partition, 0, store_data, sizeof(store_data)));
ESP_LOGI(TAG, "Written data: %s", store_data);
// Read back the data, checking that read data and written data match
ESP_ERROR_CHECK(esp_partition_read(partition, 0, read_data, sizeof(read_data)));
assert(memcmp(store_data, read_data, sizeof(read_data)) == 0);
ESP_LOGI(TAG, "Read data: %s", read_data);
// Erase the area where the data was written. Erase size shoud be a multiple of SPI_FLASH_SEC_SIZE
// and also be SPI_FLASH_SEC_SIZE aligned
ESP_ERROR_CHECK(esp_partition_erase_range(partition, 0, SPI_FLASH_SEC_SIZE));
// Read back the data (should all now be 0xFF's)
memset(store_data, 0xFF, sizeof(read_data));
ESP_ERROR_CHECK(esp_partition_read(partition, 0, read_data, sizeof(read_data)));
assert(memcmp(store_data, read_data, sizeof(read_data)) == 0);
ESP_LOGI(TAG, "Erased data");
ESP_LOGI(TAG, "Example end");
}

View file

@ -0,0 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1M,
storage, data, , , 0x40000,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
3 nvs, data, nvs, 0x9000, 0x6000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 1M,
6 storage, data, , , 0x40000,

View file

@ -0,0 +1,5 @@
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv"
CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000
CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv"
CONFIG_APP_OFFSET=0x10000