Skip to content

Commit 0a4ff80

Browse files
committed
Merge pull request #2020 from pguyot/w49/esp_partition_mmap
Add `esp:partition_mmap/3` Continuation of: - #2019 - #2015 These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license). SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
2 parents 8e8bb7c + 68767c0 commit 0a4ff80

File tree

5 files changed

+102
-3
lines changed

5 files changed

+102
-3
lines changed

src/platforms/esp32/components/avm_sys/include/esp32_sys.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ struct ESP32PlatformData
8484
#ifdef CONFIG_AVM_ENABLE_STORAGE_NIFS
8585
ErlNifResourceType *mounted_fs_resource_type;
8686
#endif
87+
ErlNifResourceType *partition_mmap_resource_type;
8788
};
8889

8990
extern QueueSetHandle_t event_set;

src/platforms/esp32/components/avm_sys/platform_nifs.c

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "atom.h"
2626
#include "defaultatoms.h"
2727
#include "esp32_sys.h"
28+
#include "erl_nif.h"
29+
#include "erl_nif_priv.h"
2830
#include "interop.h"
2931
#include "memory.h"
3032
#include "nifs.h"
@@ -270,7 +272,7 @@ static term nif_esp_partition_read(Context *ctx, int argc, term argv[])
270272
RAISE_ERROR(BADARG_ATOM);
271273
}
272274

273-
if (UNLIKELY(memory_ensure_free_opt(ctx, term_binary_data_size_in_terms(size) + BINARY_HEADER_SIZE, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
275+
if (UNLIKELY(memory_ensure_free_opt(ctx, term_binary_data_size_in_terms(size) + BINARY_HEADER_SIZE + TUPLE_SIZE(2), MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
274276
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
275277
}
276278

@@ -289,6 +291,52 @@ static term nif_esp_partition_read(Context *ctx, int argc, term argv[])
289291
return result;
290292
}
291293

294+
static term nif_esp_partition_mmap(Context *ctx, int argc, term argv[])
295+
{
296+
UNUSED(argc);
297+
298+
bool valid_partition_string;
299+
const esp_partition_t *partition = get_partition(argv[0], &valid_partition_string);
300+
if (UNLIKELY(!valid_partition_string)) {
301+
RAISE_ERROR(BADARG_ATOM);
302+
}
303+
if (IS_NULL_PTR(partition)) {
304+
return ERROR_ATOM;
305+
}
306+
307+
VALIDATE_VALUE(argv[1], term_is_integer);
308+
avm_int_t offset = term_to_int(argv[1]);
309+
310+
VALIDATE_VALUE(argv[2], term_is_integer);
311+
avm_int_t size = term_to_int(argv[2]);
312+
if (UNLIKELY(size < 0)) {
313+
RAISE_ERROR(BADARG_ATOM);
314+
}
315+
316+
struct ESP32PlatformData *platform = ctx->global->platform_data;
317+
esp_partition_mmap_handle_t *handle = enif_alloc_resource(platform->partition_mmap_resource_type, sizeof(esp_partition_mmap_handle_t));
318+
const void *mmap_ptr;
319+
esp_err_t res = esp_partition_mmap(partition, offset, size, ESP_PARTITION_MMAP_DATA, &mmap_ptr, handle);
320+
if (UNLIKELY(res != ESP_OK)) {
321+
enif_release_resource(handle);
322+
return ERROR_ATOM;
323+
}
324+
325+
ErlNifEnv *env = erl_nif_env_from_context(ctx);
326+
ERL_NIF_TERM binary = enif_make_resource_binary(env, handle, mmap_ptr, size);
327+
enif_release_resource(handle);
328+
329+
if (UNLIKELY(memory_ensure_free_with_roots(ctx, TUPLE_SIZE(2), 1, &binary, MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
330+
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
331+
}
332+
333+
term result = term_alloc_tuple(2, &ctx->heap);
334+
term_put_tuple_element(result, 0, OK_ATOM);
335+
term_put_tuple_element(result, 1, binary);
336+
337+
return result;
338+
}
339+
292340
static term nif_esp_partition_write(Context *ctx, int argc, term argv[])
293341
{
294342
UNUSED(argc);
@@ -881,6 +929,10 @@ static const struct Nif esp_partition_read_nif = {
881929
.base.type = NIFFunctionType,
882930
.nif_ptr = nif_esp_partition_read
883931
};
932+
static const struct Nif esp_partition_mmap_nif = {
933+
.base.type = NIFFunctionType,
934+
.nif_ptr = nif_esp_partition_mmap
935+
};
884936
static const struct Nif esp_partition_write_nif =
885937
{
886938
.base.type = NIFFunctionType,
@@ -1029,6 +1081,10 @@ const struct Nif *platform_nifs_get_nif(const char *nifname)
10291081
TRACE("Resolved platform nif %s ...\n", nifname);
10301082
return &esp_partition_read_nif;
10311083
}
1084+
if (strcmp("esp:partition_mmap/3", nifname) == 0) {
1085+
TRACE("Resolved platform nif %s ...\n", nifname);
1086+
return &esp_partition_mmap_nif;
1087+
}
10321088
if (strcmp("esp:partition_write/3", nifname) == 0) {
10331089
TRACE("Resolved platform nif %s ...\n", nifname);
10341090
return &esp_partition_write_nif;

src/platforms/esp32/components/avm_sys/sys.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323

2424
#include "avmpack.h"
2525
#include "defaultatoms.h"
26+
#include "erl_nif.h"
27+
#include "erl_nif_priv.h"
2628
#include "globalcontext.h"
2729
#include "otp_socket.h"
2830
#include "scheduler.h"
@@ -206,6 +208,18 @@ uint64_t sys_monotonic_time_u64_to_ms(uint64_t t)
206208
return t / 1000;
207209
}
208210

211+
static void partition_mmap_dtor(ErlNifEnv *caller_env, void *obj)
212+
{
213+
UNUSED(caller_env);
214+
esp_partition_mmap_handle_t *handle = (esp_partition_mmap_handle_t *) obj;
215+
esp_partition_munmap(*handle);
216+
}
217+
218+
const ErlNifResourceTypeInit partition_mmap_resource_type_init = {
219+
.members = 1,
220+
.dtor = partition_mmap_dtor,
221+
};
222+
209223
void sys_init_platform(GlobalContext *glb)
210224
{
211225
struct ESP32PlatformData *platform = malloc(sizeof(struct ESP32PlatformData));
@@ -270,6 +284,17 @@ void sys_init_platform(GlobalContext *glb)
270284

271285
platform->entropy_is_initialized = false;
272286
platform->random_is_initialized = false;
287+
288+
ErlNifResourceFlags flags;
289+
ErlNifEnv env;
290+
erl_nif_env_partial_init_from_globalcontext(&env, glb);
291+
platform->partition_mmap_resource_type = enif_init_resource_type(&env, "partition_mmap", &partition_mmap_resource_type_init, ERL_NIF_RT_CREATE, &flags);
292+
if (UNLIKELY(flags != ERL_NIF_RT_CREATE)) {
293+
AVM_ABORT();
294+
}
295+
if (IS_NULL_PTR(platform->partition_mmap_resource_type)) {
296+
AVM_ABORT();
297+
}
273298
}
274299

275300
void sys_free_platform(GlobalContext *glb)
@@ -360,6 +385,13 @@ enum OpenAVMResult sys_open_avm_from_file(GlobalContext *global, const char *pat
360385
spi_flash_mmap_handle_t part_handle;
361386
int size;
362387
const char *part_name = path + parts_by_name_len;
388+
const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, part_name);
389+
if (!partition) {
390+
ESP_LOGW(TAG, "AVM partition not found for %s", part_name);
391+
return AVM_OPEN_CANNOT_OPEN;
392+
}
393+
size = partition->size;
394+
363395
const void *part_data = esp32_sys_mmap_partition(part_name, &part_handle, &size);
364396
if (IS_NULL_PTR(part_data)) {
365397
return AVM_OPEN_CANNOT_OPEN;

src/platforms/esp32/test/main/test_erl_sources/test_esp_partition.erl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ start() ->
2727
{<<"phy_init">>, 1, 1, 16#f000, 16#1000, []},
2828
{<<"factory">>, 0, 0, 16#10000, 16#2C0000, []},
2929
{<<"lib.avm">>, 1, 1, 16#2D0000, 16#40000, []},
30-
{<<"main.avm">>, 1, 1, 16#310000, 16#40000, []}
30+
{<<"main.avm">>, 1, 1, 16#310000, 16#40000, []},
31+
{<<"data">>, 1, 1, 16#350000, 16#10000, []}
3132
] = esp:partition_list(),
33+
ok = esp:partition_erase_range(<<"data">>, 0),
34+
ok = esp:partition_write(<<"data">>, 0, <<"hello">>),
35+
{ok, <<"hello">>} = esp:partition_read(<<"data">>, 0, 5),
36+
{ok, <<"hello">>} = esp:partition_mmap(<<"data">>, 0, 5),
37+
ok = esp:partition_erase_range(<<"data">>, 0, 4096),
38+
ok = esp:partition_write(<<"data">>, 0, <<"world">>),
39+
{ok, <<"world">>} = esp:partition_read(<<"data">>, 0, 5),
40+
{ok, <<"world">>} = esp:partition_mmap(<<"data">>, 0, 5),
3241
0.

src/platforms/esp32/test/partitions.csv

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ nvs, data, nvs, 0x9000, 0x6000,
1212
phy_init, data, phy, 0xf000, 0x1000,
1313
factory, app, factory, 0x10000, 0x2C0000,
1414
lib.avm, data, phy, 0x2D0000, 0x40000,
15-
main.avm, data, phy, 0x310000, 0x40000
15+
main.avm, data, phy, 0x310000, 0x40000,
16+
data, data, phy, 0x350000, 0x10000

0 commit comments

Comments
 (0)