@mikrojs/firmware 0.13.0 → 0.14.0-pr-229.g46bcbe2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -7
- package/components/mikrojs/mik_http.cpp +14 -0
- package/components/mikrojs/mik_sntp.cpp +9 -0
- package/components/mikrojs/mik_wifi.cpp +19 -0
- package/package.json +3 -7
- package/prebuilds/esp32/bootloader/bootloader.bin +0 -0
- package/prebuilds/esp32/mikrojs.bin +0 -0
- package/prebuilds/esp32c3/bootloader/bootloader.bin +0 -0
- package/prebuilds/esp32c3/mikrojs.bin +0 -0
- package/prebuilds/esp32c5/bootloader/bootloader.bin +0 -0
- package/prebuilds/esp32c5/mikrojs.bin +0 -0
- package/prebuilds/esp32c6/bootloader/bootloader.bin +0 -0
- package/prebuilds/esp32c6/mikrojs.bin +0 -0
- package/prebuilds/esp32s3/bootloader/bootloader.bin +0 -0
- package/prebuilds/esp32s3/mikrojs.bin +0 -0
- package/sdkconfig.defaults +4 -4
- package/bin/idf.py +0 -7
package/README.md
CHANGED
|
@@ -6,20 +6,19 @@ ESP32 firmware package for Mikro.js. Provides the ESP-IDF integration, build sys
|
|
|
6
6
|
|
|
7
7
|
- **`project.cmake`** - CMake module that integrates with ESP-IDF. Handles component discovery, SDK config merging, and partition table defaults.
|
|
8
8
|
- **`components/mikrojs/`** - ESP-IDF component that compiles the Mikro.js runtime, QuickJS engine, and platform-specific C modules.
|
|
9
|
-
- **`idf.py` wrapper** - Runs `idf.py` through `eim run`, so you don't need to manually activate ESP-IDF.
|
|
10
9
|
- **Default configs** - `sdkconfig.defaults` and `partitions.csv` for common setups.
|
|
11
10
|
|
|
12
11
|
## Usage
|
|
13
12
|
|
|
14
|
-
A custom firmware project depends on this package and includes `project.cmake
|
|
13
|
+
A custom firmware project depends on this package and includes `project.cmake` (resolved via `resolve.js`, see the docs below for the CMakeLists boilerplate):
|
|
15
14
|
|
|
16
15
|
```
|
|
17
16
|
my-firmware/
|
|
18
17
|
├── package.json # depends on @mikrojs/firmware
|
|
19
|
-
├── CMakeLists.txt #
|
|
20
|
-
└── main/
|
|
21
|
-
├── CMakeLists.txt
|
|
22
|
-
└── main.cpp
|
|
18
|
+
├── CMakeLists.txt # resolves and includes project.cmake via resolve.js
|
|
19
|
+
└── main/ # optional: omit it and the package's default main
|
|
20
|
+
├── CMakeLists.txt # (which calls MIK_Main()) is used automatically
|
|
21
|
+
└── main.cpp
|
|
23
22
|
```
|
|
24
23
|
|
|
25
24
|
See the [Custom Firmware](https://mikrojs.dev/develop/custom-firmware) docs for details.
|
|
@@ -27,4 +26,6 @@ See the [Custom Firmware](https://mikrojs.dev/develop/custom-firmware) docs for
|
|
|
27
26
|
## Requirements
|
|
28
27
|
|
|
29
28
|
- Node.js >= 24
|
|
30
|
-
- ESP-IDF >= 6.0.1 (installed via [EIM](https://docs.espressif.com/projects/
|
|
29
|
+
- ESP-IDF >= 6.0.1 (installed via [EIM](https://docs.espressif.com/projects/idf-im-ui/en/latest/))
|
|
30
|
+
|
|
31
|
+
To build, activate ESP-IDF in your shell first: run `eim select` and source the activation script it prints, then use `idf.py` as usual.
|
|
@@ -581,6 +581,14 @@ static JSValue mik__http_request(JSContext* ctx, JSValue this_val, int argc, JSV
|
|
|
581
581
|
MIKHttpPending pending = {};
|
|
582
582
|
pending.id = mik__http_st(mik_rt)->next_id++;
|
|
583
583
|
JSValue headers_promise = MIK_InitPromise(ctx, &pending.headers_promise);
|
|
584
|
+
if (JS_IsException(headers_promise)) {
|
|
585
|
+
/* OOM building the promise. Nothing is registered yet, so just free the
|
|
586
|
+
* request and propagate. Do NOT register this pending entry: its
|
|
587
|
+
* headers_promise.rfuncs are unwritten on failure, and a later
|
|
588
|
+
* consume/destroy would free dangling values (gc_decref underflow). */
|
|
589
|
+
mik__http_free_request(&req);
|
|
590
|
+
return JS_EXCEPTION;
|
|
591
|
+
}
|
|
584
592
|
|
|
585
593
|
auto* cancelled = new std::atomic<bool>(false);
|
|
586
594
|
pending.cancelled = cancelled;
|
|
@@ -672,6 +680,12 @@ static JSValue mik__http_next_message(JSContext* ctx, JSValue this_val, int argc
|
|
|
672
680
|
|
|
673
681
|
/* Slow path: wait. Create a new promise stored on the pending entry. */
|
|
674
682
|
JSValue promise = MIK_InitPromise(ctx, &p->next_promise);
|
|
683
|
+
if (JS_IsException(promise)) {
|
|
684
|
+
/* OOM building the promise. Do NOT mark next_promise_active: rfuncs are
|
|
685
|
+
* unwritten on failure, so a later resolve/destroy would free dangling
|
|
686
|
+
* values (gc_decref underflow). */
|
|
687
|
+
return JS_EXCEPTION;
|
|
688
|
+
}
|
|
675
689
|
p->next_promise_active = true;
|
|
676
690
|
return promise;
|
|
677
691
|
}
|
|
@@ -144,6 +144,15 @@ static JSValue mik__sntp_sync(JSContext* ctx, JSValue this_val, int argc, JSValu
|
|
|
144
144
|
|
|
145
145
|
/* Create and return promise wrapped in result */
|
|
146
146
|
JSValue promise = MIK_InitPromise(ctx, &state->sync_promise);
|
|
147
|
+
if (JS_IsException(promise)) {
|
|
148
|
+
/* OOM building the promise. Tear down so we don't leave a half-started
|
|
149
|
+
* sync, and crucially do NOT set sync_pending: MIK_InitPromise leaves
|
|
150
|
+
* sync_promise.rfuncs unwritten on failure, so a later consume/destroy
|
|
151
|
+
* would free dangling values (gc_decref refcount underflow). */
|
|
152
|
+
esp_netif_sntp_deinit();
|
|
153
|
+
state->running = false;
|
|
154
|
+
return JS_EXCEPTION;
|
|
155
|
+
}
|
|
147
156
|
state->sync_pending = true;
|
|
148
157
|
|
|
149
158
|
return mik__result_ok(ctx, promise);
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
#include <vector>
|
|
3
3
|
|
|
4
4
|
#include "esp_event.h"
|
|
5
|
+
#include "esp_heap_caps.h"
|
|
5
6
|
#include "esp_log.h"
|
|
6
7
|
#include "esp_mac.h"
|
|
7
8
|
#include "esp_netif.h"
|
|
@@ -332,6 +333,17 @@ fail_after_init:
|
|
|
332
333
|
return err;
|
|
333
334
|
}
|
|
334
335
|
|
|
336
|
+
/* Minimum free internal (DMA-capable) RAM required before bringing up the
|
|
337
|
+
* radio. esp_wifi_start() enables the PHY, which calloc()s its RF
|
|
338
|
+
* calibration data from internal RAM and calls abort() on failure
|
|
339
|
+
* (esp_phy/src/phy_init.c: "failed to allocate memory for RF calibration
|
|
340
|
+
* data"). That hard-abort reboots the device instead of surfacing a
|
|
341
|
+
* catchable error, so we pre-flight the heap here and refuse gracefully
|
|
342
|
+
* when it's too low. The figure covers the PHY cal buffers plus the WiFi
|
|
343
|
+
* driver's start-time internal allocations with margin; it is a heuristic,
|
|
344
|
+
* not an exact bound. Tune if a healthy device ever trips it. */
|
|
345
|
+
static constexpr size_t MIK_WIFI_MIN_INTERNAL_HEAP = 40 * 1024;
|
|
346
|
+
|
|
335
347
|
/* Start the WiFi radio. Deferred from init so the radio is not active
|
|
336
348
|
* until connect() or scan() is actually called. */
|
|
337
349
|
static esp_err_t mik__wifi_ensure_started(JSContext* ctx) {
|
|
@@ -339,6 +351,13 @@ static esp_err_t mik__wifi_ensure_started(JSContext* ctx) {
|
|
|
339
351
|
if (err != ESP_OK) return err;
|
|
340
352
|
if (s_wifi_started) return ESP_OK;
|
|
341
353
|
|
|
354
|
+
/* Refuse to start under low internal RAM rather than let the PHY init
|
|
355
|
+
* abort() the whole device. The caller turns ESP_ERR_NO_MEM into a
|
|
356
|
+
* catchable StartFailed result. */
|
|
357
|
+
if (heap_caps_get_free_size(MALLOC_CAP_INTERNAL) < MIK_WIFI_MIN_INTERNAL_HEAP) {
|
|
358
|
+
return ESP_ERR_NO_MEM;
|
|
359
|
+
}
|
|
360
|
+
|
|
342
361
|
err = esp_wifi_start();
|
|
343
362
|
if (err != ESP_OK) return err;
|
|
344
363
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikrojs/firmware",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0-pr-229.g46bcbe2",
|
|
4
4
|
"description": "Mikro.js ESP32 firmware: ESP-IDF component, build tools, and project template",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"esp-idf",
|
|
@@ -18,9 +18,6 @@
|
|
|
18
18
|
"type": "git",
|
|
19
19
|
"url": "git+https://github.com/mikrojs/mikro.git"
|
|
20
20
|
},
|
|
21
|
-
"bin": {
|
|
22
|
-
"idf.py": "./bin/idf.py"
|
|
23
|
-
},
|
|
24
21
|
"files": [
|
|
25
22
|
"components",
|
|
26
23
|
"default-app",
|
|
@@ -28,7 +25,6 @@
|
|
|
28
25
|
"sdkconfig.defaults",
|
|
29
26
|
"sdkconfig.defaults.*",
|
|
30
27
|
"partitions.csv",
|
|
31
|
-
"bin",
|
|
32
28
|
"chips.json",
|
|
33
29
|
"cmake.js",
|
|
34
30
|
"discover.js",
|
|
@@ -51,8 +47,8 @@
|
|
|
51
47
|
},
|
|
52
48
|
"dependencies": {
|
|
53
49
|
"esbuild": "^0.28.0",
|
|
54
|
-
"@mikrojs/native": "0.
|
|
55
|
-
"@mikrojs/quickjs": "0.
|
|
50
|
+
"@mikrojs/native": "0.14.0-pr-229.g46bcbe2",
|
|
51
|
+
"@mikrojs/quickjs": "0.14.0-pr-229.g46bcbe2"
|
|
56
52
|
},
|
|
57
53
|
"engines": {
|
|
58
54
|
"node": ">=24.0.0"
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/sdkconfig.defaults
CHANGED
|
@@ -21,11 +21,11 @@ CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
|
|
21
21
|
# Use -Os to reduce code size (less IRAM pressure, smaller function frames)
|
|
22
22
|
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
|
23
23
|
|
|
24
|
-
# Move
|
|
25
|
-
# SRAM on single-core chips like C3/C6, so freeing IRAM also frees DRAM)
|
|
24
|
+
# Move heap functions from IRAM to flash (IRAM and DRAM share the same
|
|
25
|
+
# SRAM on single-core chips like C3/C6, so freeing IRAM also frees DRAM).
|
|
26
|
+
# FreeRTOS and esp_ringbuf functions are placed in flash by default since
|
|
27
|
+
# ESP-IDF 6.0; their *_PLACE_FUNCTIONS_INTO_FLASH options were removed.
|
|
26
28
|
CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH=y
|
|
27
|
-
CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
|
|
28
|
-
CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y
|
|
29
29
|
|
|
30
30
|
# Trade WiFi throughput for ~15-20KB IRAM savings. Fine for mikrojs
|
|
31
31
|
# workloads (HTTP requests, small payloads — not high-throughput streaming).
|