Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP32: add esp:partition_list/0 function #679

Merged
merged 3 commits into from
Jul 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/esp32-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ jobs:

matrix:
idf-version:
- 4.2.4
- 4.3.5
- 4.4.4
- 5.0.2
- 5.1-rc1
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added support for Raspberry Pi Pico
- Added support for nodejs with Wasm
- Added support for a subset of the OTP logger interface
- Added `esp:partition_list/0` function

### Fixed
- Fixed issue with formatting integers with io:format() on STM32 platform
Expand Down
17 changes: 17 additions & 0 deletions doc/src/programmers-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,23 @@ The `freq_hz` function can be used to retrieve the clock frequency of the chip.

* `esp:freq_hz/0`

The `esp:partition_list/0` function can be used to retrieve information about the paritions on an ESP32 flash.

The return type is a list of tuples, each of which contains the partition id (as a binary), partition type and sub-type (both of which are represented as integers), the start of the partition as an address along with its size, as well as a list of properties about the partition, as a properties list.

%% erlang
PartitionList = esp:partition_list(),
lists:foreach(
fun({PartitionId, PartitionType, PartitionSubtype, PartitionAddress, PartitionSize, PartitionProperties}) ->
%% ...
end,
PartitionList
)

> Note. The partition properties are currently empty (`[]`).

For information about the encoding of partition types and sub-types, see the IDF SDK partition [type definitions](https://docs.espressif.com/projects/esp-idf/en/v4.4.5/esp32/api-reference/storage/spi_flash.html?highlight=esp_partition_get#id13).

## Peripherals

The AtomVM virtual machine and libraries support APIs for interfacing with peripheral devices connected to the ESP32. This section provides information about these APIs.
Expand Down
27 changes: 27 additions & 0 deletions libs/eavmlib/src/esp.erl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
nvs_erase_key/1, nvs_erase_key/2,
nvs_erase_all/0, nvs_erase_all/1,
nvs_reformat/0,
partition_list/0,
rtc_slow_get_binary/0,
rtc_slow_set_binary/1,
freq_hz/0
Expand Down Expand Up @@ -68,6 +69,21 @@
| sleep_wakeup_cocpu_trap_trig
| sleep_wakeup_bt.

-type esp_partition_type() :: 0..254.
-type esp_partition_subtype() :: 0..254.
-type esp_partition_address() :: 0..134217728.
-type esp_partition_size() :: 0..134217728.
-type esp_partition_props() :: [].

-type esp_partition() :: {
binary(),
esp_partition_type(),
esp_partition_subtype(),
esp_partition_address(),
esp_partition_size(),
esp_partition_props()
}.

-define(ATOMVM_NVS_NS, atomvm).

%%-----------------------------------------------------------------------------
Expand Down Expand Up @@ -229,6 +245,17 @@ nvs_erase_all(Namespace) when is_atom(Namespace) ->
nvs_reformat() ->
throw(nif_error).

%%-----------------------------------------------------------------------------
%% @returns List of partitions
%% @doc Gets the list of partitions as tuples, such as {name, type, subtype,
%% offset, size, props}. Type and subtype are integers as described in
%% esp-idf documentation.
%% @end
%%-----------------------------------------------------------------------------
-spec partition_list() -> [esp_partition()].
partition_list() ->
throw(nif_error).

%%-----------------------------------------------------------------------------
%% @returns the currently stored binary in RTC slow memory.
%% @doc Get the binary currently stored in RTC slow memory. Must not be
Expand Down
57 changes: 57 additions & 0 deletions src/platforms/esp32/components/avm_sys/platform_nifs.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,54 @@ static term nif_esp_partition_write(Context *ctx, int argc, term argv[])
return OK_ATOM;
}

static term nif_esp_partition_list(Context *ctx, int argc, term argv[])
{
UNUSED(argc);

size_t needed = 0;

for (esp_partition_iterator_t it
= esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
it != NULL; it = esp_partition_next(it)) {
const esp_partition_t *partition = esp_partition_get(it);
// {name, type, subtype, offset, size, props}
// TODO: right now props is empty, so it doesn't take space
// all integers are < 27 bits, so we are safe
// * 2 is for accounting the reversed list
int label_len = strlen(partition->label);
needed += CONS_SIZE * 2 + TUPLE_SIZE(6) + TERM_BINARY_HEAP_SIZE(label_len);
}

if (UNLIKELY(memory_ensure_free(ctx, needed) != MEMORY_GC_OK)) {
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
}

term l = term_nil();
for (esp_partition_iterator_t it
= esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL);
it != NULL; it = esp_partition_next(it)) {
const esp_partition_t *partition = esp_partition_get(it);
// {name, type, subtype, offset, size, props}
int len = strlen(partition->label);
term label_bin = term_from_literal_binary(partition->label, len, &ctx->heap, ctx->global);
term t = term_alloc_tuple(6, &ctx->heap);
term_put_tuple_element(t, 0, label_bin);
term_put_tuple_element(t, 1, term_from_int(partition->type));
term_put_tuple_element(t, 2, term_from_int(partition->subtype));
term_put_tuple_element(t, 3, term_from_int(partition->address));
term_put_tuple_element(t, 4, term_from_int(partition->size));
term_put_tuple_element(t, 5, term_nil());
l = term_list_prepend(t, l, &ctx->heap);
}

term return_list = term_nil();
for (term li = l; li != term_nil(); li = term_get_list_tail(li)) {
return_list = term_list_prepend(term_get_list_head(li), return_list, &ctx->heap);
}

return return_list;
}

static term nif_esp_deep_sleep(Context *ctx, int argc, term argv[])
{
UNUSED(argc);
Expand Down Expand Up @@ -441,6 +489,11 @@ static const struct Nif esp_partition_write_nif =
.base.type = NIFFunctionType,
.nif_ptr = nif_esp_partition_write
};
static const struct Nif esp_partition_list_nif =
{
.base.type = NIFFunctionType,
.nif_ptr = nif_esp_partition_list
};
static const struct Nif esp_deep_sleep_nif =
{
.base.type = NIFFunctionType,
Expand Down Expand Up @@ -508,6 +561,10 @@ const struct Nif *platform_nifs_get_nif(const char *nifname)
TRACE("Resolved platform nif %s ...\n", nifname);
return &esp_partition_write_nif;
}
if (strcmp("esp:partition_list/0", nifname) == 0) {
TRACE("Resolved platform nif %s ...\n", nifname);
return &esp_partition_list_nif;
}
if (strcmp("esp:deep_sleep/1", nifname) == 0) {
TRACE("Resolved platform nif %s ...\n", nifname);
return &esp_deep_sleep_nif;
Expand Down
3 changes: 3 additions & 0 deletions src/platforms/esp32/test/main/test_erl_sources/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ function(compile_erlang module_name)
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/${module_name}.beam")
endfunction()

compile_erlang(test_esp_partition)
compile_erlang(test_file)
compile_erlang(test_md5)
compile_erlang(test_monotonic_time)
Expand All @@ -48,6 +49,7 @@ add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/esp32_test_modules.avm"
COMMAND HostAtomVM-prefix/src/HostAtomVM-build/tools/packbeam/PackBEAM -i esp32_test_modules.avm
HostAtomVM-prefix/src/HostAtomVM-build/libs/atomvmlib.avm
test_esp_partition.beam
test_file.beam
test_md5.beam
test_monotonic_time.beam
Expand All @@ -57,6 +59,7 @@ add_custom_command(
test_tz.beam
DEPENDS
HostAtomVM
"${CMAKE_CURRENT_BINARY_DIR}/test_esp_partition.beam"
"${CMAKE_CURRENT_BINARY_DIR}/test_file.beam"
"${CMAKE_CURRENT_BINARY_DIR}/test_md5.beam"
"${CMAKE_CURRENT_BINARY_DIR}/test_monotonic_time.beam"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
%
% This file is part of AtomVM.
%
% Copyright 2023 Davide Bettio <[email protected]>
%
% 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.
%
% SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
%

-module(test_esp_partition).
-export([start/0]).

start() ->
[
{<<"nvs">>, 1, 2, 16#9000, 16#6000, []},
{<<"phy_init">>, 1, 1, 16#f000, 16#1000, []},
{<<"factory">>, 0, 0, 16#10000, 16#1C0000, []},
{<<"lib.avm">>, 1, 1, 16#1D0000, 16#40000, []},
{<<"main.avm">>, 1, 1, 16#210000, 16#100000, []}
] = esp:partition_list(),
0.
6 changes: 6 additions & 0 deletions src/platforms/esp32/test/main/test_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,12 @@ term avm_test_case(const char *test_module)
return ret_value;
}

TEST_CASE("test_esp_partition", "[test_run]")
{
term ret_value = avm_test_case("test_esp_partition.beam");
TEST_ASSERT(term_to_int(ret_value) == 0);
}

TEST_CASE("test_file", "[test_run]")
{
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
Expand Down
3 changes: 3 additions & 0 deletions src/platforms/esp32/test/partitions.csv
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#
# SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later

# UPDATE ALSO "test_erl_sources/test_esp_partition.erl" WHEN UPDATING THIS FILE
# OTHERWISE "test_esp_partition.erl" TEST WILL ALWAYS FAIL.

# 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,
Expand Down
Loading