Skip to content

Commit

Permalink
Merge branch 'atomvm:master' into w23/add-enif_monitor
Browse files Browse the repository at this point in the history
  • Loading branch information
pguyot authored Jul 22, 2023
2 parents 452ed0a + ea8fa33 commit d8f52ea
Show file tree
Hide file tree
Showing 18 changed files with 395 additions and 19 deletions.
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
4 changes: 2 additions & 2 deletions src/libAtomVM/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,15 @@ typedef struct Heap Heap;
*
* @param heap heap to initialize.
* @param root fragment root.
* @param size capacity of the heap to create, including the mso_list.
* @param size capacity of the heap to create, not including the mso_list.
*/
void memory_init_heap_root_fragment(Heap *heap, HeapFragment *root, size_t size);

/**
* @brief Initialize a root heap.
*
* @param heap heap to initialize.
* @param size capacity of the heap to create, including the mso_list.
* @param size capacity of the heap to create, not including the mso_list.
* @returns MEMORY_GC_OK or MEMORY_GC_ERROR_FAILED_ALLOCATION depending on the outcome.
*/
enum MemoryGCResult memory_init_heap(Heap *heap, size_t size) MUST_CHECK;
Expand Down
41 changes: 26 additions & 15 deletions src/libAtomVM/nifs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2295,29 +2295,40 @@ static term nif_erlang_list_to_binary_1(Context *ctx, int argc, term argv[])
RAISE_ERROR(BADARG_ATOM);
}

char *bin_buf = malloc(bin_size);
if (IS_NULL_PTR(bin_buf)) {
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
}

switch (interop_write_iolist(t, bin_buf)) {
case InteropOk:
break;
case InteropMemoryAllocFail:
free(bin_buf);
char *bin_buf = NULL;
bool buf_allocated = true;
if (bin_size > 0) {
bin_buf = malloc(bin_size);
if (IS_NULL_PTR(bin_buf)) {
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
case InteropBadArg:
free(bin_buf);
RAISE_ERROR(BADARG_ATOM);
}

switch (interop_write_iolist(t, bin_buf)) {
case InteropOk:
break;
case InteropMemoryAllocFail:
free(bin_buf);
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
case InteropBadArg:
free(bin_buf);
RAISE_ERROR(BADARG_ATOM);
}
} else {
bin_buf = "";
buf_allocated = false;
}

if (UNLIKELY(memory_ensure_free_opt(ctx, term_binary_heap_size(bin_size), MEMORY_CAN_SHRINK) != MEMORY_GC_OK)) {
free(bin_buf);
if (buf_allocated) {
free(bin_buf);
}
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
}
term bin_res = term_from_literal_binary(bin_buf, bin_size, &ctx->heap, ctx->global);

free(bin_buf);
if (buf_allocated) {
free(bin_buf);
}

return bin_res;
}
Expand Down
24 changes: 24 additions & 0 deletions src/platforms/emscripten/src/lib/platform_nifs.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <erl_nif_priv.h>
#include <globalcontext.h>
#include <interop.h>
#include <memory.h>
#include <nifs.h>
#include <term.h>
#include <term_typedef.h>
Expand All @@ -32,6 +33,8 @@
#include <emscripten/proxying.h>
#include <emscripten/threading.h>

#include <math.h>

//#define ENABLE_TRACE
#include <trace.h>

Expand All @@ -47,6 +50,20 @@ static term nif_atomvm_platform(Context *ctx, int argc, term argv[])
return EMSCRIPTEN_ATOM;
}

static term nif_atomvm_random(Context *ctx, int argc, term argv[])
{
UNUSED(ctx);
UNUSED(argc);
UNUSED(argv);
float val1 = emscripten_random();
float val2 = emscripten_random();
uint32_t result = ((uint32_t) floor(val1 * (1 << 16))) << 16 | ((uint32_t) floor(val2 * (1 << 16)));
if (UNLIKELY(memory_ensure_free(ctx, BOXED_INT64_SIZE) != MEMORY_GC_OK)) {
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
}
return term_make_maybe_boxed_int64(result, &ctx->heap);
}

static void do_run_script(GlobalContext *global, char *script, int sync, int sync_caller_pid)
{
emscripten_run_script(script);
Expand Down Expand Up @@ -143,6 +160,10 @@ static const struct Nif atomvm_platform_nif = {
.base.type = NIFFunctionType,
.nif_ptr = nif_atomvm_platform
};
static const struct Nif atomvm_random_nif = {
.base.type = NIFFunctionType,
.nif_ptr = nif_atomvm_random
};
static const struct Nif emscripten_run_script_nif = {
.base.type = NIFFunctionType,
.nif_ptr = nif_emscripten_run_script
Expand All @@ -162,6 +183,9 @@ const struct Nif *platform_nifs_get_nif(const char *nifname)
TRACE("Resolved platform nif %s ...\n", nifname);
return &atomvm_platform_nif;
}
if (strcmp("atomvm:random/0", nifname) == 0) {
return &atomvm_random_nif;
}
if (strcmp("emscripten:run_script/1", nifname) == 0) {
TRACE("Resolved platform nif %s ...\n", nifname);
return &emscripten_run_script_nif;
Expand Down
31 changes: 31 additions & 0 deletions src/platforms/emscripten/tests/cypress/e2e/atomvm.spec.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* This file is part of AtomVM.
*
* Copyright 2023 by Paul Guyot <[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
*/
describe("atomvm", () => {
beforeEach(() => {
cy.visit("/tests/src/test_atomvm.html");
});

it("should return platform", () => {
cy.get("#platform").should("contain", "emscripten");
});
it("should compute pi with a reasonable error", () => {
cy.get("#pierror").should("contain", "true");
});
});
2 changes: 2 additions & 0 deletions src/platforms/emscripten/tests/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ function(compile_erlang module_name)
)
endfunction()

compile_erlang(test_atomvm)
compile_erlang(test_call)

add_custom_target(emscripten_erlang_test_modules DEPENDS
test_atomvm.beam
test_call.beam
)
72 changes: 72 additions & 0 deletions src/platforms/emscripten/tests/src/test_atomvm.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
%
% This file is part of AtomVM.
%
% Copyright 2023 Paul Guyot <[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_atomvm).
-export([start/0]).

start() ->
erlang:display({?MODULE, ?LINE}),
Platform = atomvm:platform(),
erlang:display({?MODULE, ?LINE}),
Random = atomvm:random(),
erlang:display({?MODULE, ?LINE}),
PI = pi_by_random(),
PIError = abs((PI - 3.141592653589793) / 3.141592653589793),
PIErrorThreshold = PIError < 0.01,
erlang:display({?MODULE, ?LINE}),
emscripten:run_script(
[
<<"document.querySelector('#platform').append('">>,
atom_to_list(Platform),
<<"');">>,
<<"document.querySelector('#random').append('">>,
integer_to_list(Random),
<<"');">>,
<<"document.querySelector('#pi').append('">>,
float_to_list(PI),
<<"');">>,
<<"document.querySelector('#pierror').append('">>,
atom_to_list(PIErrorThreshold),
<<"');">>
],
[main_thread, async]
),
loop().

loop() ->
receive
after infinity -> ok
end.

pi_by_random() ->
pi_by_random(100000, 0, 0).

pi_by_random(0, AccHit, AccTotal) ->
4 * AccHit / AccTotal;
pi_by_random(N, AccHit, AccTotal) ->
X = atomvm:random(),
Y = atomvm:random(),
SqDistance = (X - 16#80000000) * (X - 16#80000000) + (Y - 16#80000000) * (Y - 16#80000000),
NewAccHit =
case SqDistance > (16#80000000 * 16#80000000) of
true -> AccHit;
false -> AccHit + 1
end,
pi_by_random(N - 1, NewAccHit, AccTotal + 1).
44 changes: 44 additions & 0 deletions src/platforms/emscripten/tests/src/test_atomvm.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<!--
This file is part of AtomVM.
Copyright 2023 Paul Guyot <[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
-->
<!doctype html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8" />
</head>
<body>
<div id="platform"></div>
<div id="random"></div>
<div id="pi"></div>
<div id="pierror"></div>
<script>
// Arguments are loaded using fetch API.
// wasm_webserver serves under /tests/build/ files in src/platform/escripten/build/tests/src subdirectory
// and under /build/ files in build/ subdirectory.
var Module = {
arguments: [
"/tests/build/test_atomvm.beam",
"/build/libs/estdlib/src/estdlib.avm",
"/build/libs/eavmlib/src/eavmlib.avm",
],
};
</script>
<script async src="/AtomVM.js"></script>
</body>
</html>
Loading

0 comments on commit d8f52ea

Please sign in to comment.