@mikrojs/firmware 0.20.0 → 0.20.2-next.20260907205905
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/components/mikrojs/CMakeLists.txt +16 -2
- package/components/mikrojs/Kconfig +26 -0
- package/components/mikrojs/mik_main.cpp +11 -14
- package/components/mikrojs/mik_ota_client_module.cpp +14 -5
- package/components/mikrojs/mik_ota_env.cpp +9 -6
- package/components/mikrojs/test/CMakeLists.txt +6 -2
- package/components/mikrojs/test/ota_host/.gitignore +2 -0
- package/package.json +4 -4
- 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
|
@@ -41,6 +41,17 @@ if(CONFIG_BT_ENABLED)
|
|
|
41
41
|
list(APPEND _MIK_BLE_SRCS "mik_ble.cpp" "mik_ble_c_shim.c")
|
|
42
42
|
endif()
|
|
43
43
|
|
|
44
|
+
# The WiFi driver and the `wifi` native module only compile under
|
|
45
|
+
# CONFIG_MIKROJS_WIFI. Nothing else references esp_wifi, so leaving
|
|
46
|
+
# mik_wifi.cpp out is what drops net80211, pp and wpa_supplicant from the
|
|
47
|
+
# link (about 20 KB of static RAM). `esp_wifi` stays in REQUIRES
|
|
48
|
+
# unconditionally: IDF expands REQUIRES before sdkconfig is loaded, so a
|
|
49
|
+
# CONFIG_-gated entry would always be empty there.
|
|
50
|
+
set(_MIK_WIFI_SRCS "")
|
|
51
|
+
if(CONFIG_MIKROJS_WIFI)
|
|
52
|
+
list(APPEND _MIK_WIFI_SRCS "mik_wifi.cpp")
|
|
53
|
+
endif()
|
|
54
|
+
|
|
44
55
|
# mik_ota.cpp includes <miniz.h> for tinfl (gunzip). On the esp32c6 the
|
|
45
56
|
# implementation is in the chip mask ROM and the header comes from the
|
|
46
57
|
# always-available `esp_rom` common dependency, so no REQUIRES entry is needed.
|
|
@@ -118,7 +129,7 @@ idf_component_register(
|
|
|
118
129
|
"mik_spi.cpp"
|
|
119
130
|
"mik_sntp.cpp"
|
|
120
131
|
"mik_uart.cpp"
|
|
121
|
-
|
|
132
|
+
${_MIK_WIFI_SRCS}
|
|
122
133
|
)
|
|
123
134
|
|
|
124
135
|
# QuickJS headers as SYSTEM includes (suppresses warnings)
|
|
@@ -195,8 +206,11 @@ endif()
|
|
|
195
206
|
include("${MIK_BYTECODE_CMAKE}")
|
|
196
207
|
|
|
197
208
|
# Force linker to include self-registering native modules
|
|
198
|
-
set(_MIK_MODULES cbor pin i2c i2s spi http http_server
|
|
209
|
+
set(_MIK_MODULES cbor pin i2c i2s spi http http_server rtc nvs_kv sntp sleep neopixel pwm uart ota)
|
|
199
210
|
list(APPEND _MIK_MODULES ota_client)
|
|
211
|
+
if(CONFIG_MIKROJS_WIFI)
|
|
212
|
+
list(APPEND _MIK_MODULES wifi)
|
|
213
|
+
endif()
|
|
200
214
|
set(_MIK_BYTECODE_MODULES abort cbor env result schema fs http/server i2c i2s kv/nvs kv/rtc kv/shared module neopixel observable observable/lazy observable/operators ota ota/client ota/config pin pwm reader sleep spi sntp stdio stream sys test uart udp watchdog)
|
|
201
215
|
if(CONFIG_BT_ENABLED)
|
|
202
216
|
list(APPEND _MIK_MODULES ble)
|
|
@@ -22,6 +22,32 @@ menu "mikrojs console"
|
|
|
22
22
|
|
|
23
23
|
endmenu
|
|
24
24
|
|
|
25
|
+
menu "mikrojs WiFi"
|
|
26
|
+
|
|
27
|
+
config MIKROJS_WIFI
|
|
28
|
+
bool "Compile the WiFi driver and the mikro/wifi module"
|
|
29
|
+
default y
|
|
30
|
+
depends on SOC_WIFI_SUPPORTED
|
|
31
|
+
help
|
|
32
|
+
When enabled, the firmware links the ESP-IDF WiFi driver
|
|
33
|
+
(net80211, pp, wpa_supplicant) and provides the `mikro/wifi`
|
|
34
|
+
module. The driver takes about 20 KB of internal RAM at boot
|
|
35
|
+
whether or not the radio is ever started.
|
|
36
|
+
|
|
37
|
+
Disable for apps that do all their networking over another
|
|
38
|
+
link (a cellular modem on a UART, for instance) to get that
|
|
39
|
+
RAM back. `import 'mikro/wifi'` then throws ReferenceError:
|
|
40
|
+
Native module 'native:mikro/wifi' is not available, the boot
|
|
41
|
+
banner lists no WiFi radio and BoardInfo.features omits
|
|
42
|
+
"wifi". HTTP and SNTP still compile; they need a network
|
|
43
|
+
interface from elsewhere.
|
|
44
|
+
|
|
45
|
+
IDF's own CONFIG_ESP_WIFI_ENABLED cannot do this: it has no
|
|
46
|
+
prompt on WiFi-capable chips, so setting it to n in
|
|
47
|
+
sdkconfig.defaults is silently reverted to y.
|
|
48
|
+
|
|
49
|
+
endmenu
|
|
50
|
+
|
|
25
51
|
menu "mikrojs runtime memory"
|
|
26
52
|
|
|
27
53
|
config MIKROJS_QUICKJS_HEAP_PSRAM
|
|
@@ -320,12 +320,14 @@ void MIK_Main(void) {
|
|
|
320
320
|
* the low-level radio driver is linked, even when no higher-level
|
|
321
321
|
* stack is compiled in. WiFi and BLE each require both silicon support
|
|
322
322
|
* and a corresponding `mikrojs/wifi`/`mikrojs/ble` JS module — we gate
|
|
323
|
-
* on the
|
|
324
|
-
*
|
|
323
|
+
* on the flags that compile those modules in: CONFIG_MIKROJS_WIFI (the
|
|
324
|
+
* component's own switch, since IDF forces CONFIG_ESP_WIFI_ENABLED on
|
|
325
|
+
* for capable silicon) and CONFIG_BT_ENABLED. 802.15.4 is deliberately
|
|
326
|
+
* omitted until a `mikrojs/zigbee` or `mikrojs/thread` module ships. */
|
|
325
327
|
esp_chip_info_t chip_info;
|
|
326
328
|
esp_chip_info(&chip_info);
|
|
327
329
|
|
|
328
|
-
#if
|
|
330
|
+
#if CONFIG_MIKROJS_WIFI
|
|
329
331
|
bool has_wifi = (chip_info.features & CHIP_FEATURE_WIFI_BGN) != 0;
|
|
330
332
|
#else
|
|
331
333
|
bool has_wifi = false;
|
|
@@ -744,24 +746,19 @@ void MIK_Main(void) {
|
|
|
744
746
|
if (safe_mode) {
|
|
745
747
|
ESP_LOGW(TAG, "Safe mode: skipping entry point %s", app_config.entry_point);
|
|
746
748
|
} else {
|
|
747
|
-
/* Catch
|
|
749
|
+
/* Catch fatals during an OTA trial: MIK_RunEntry hands a synchronous
|
|
750
|
+
* throw to this handler itself, the loop's rejection flush hands it
|
|
751
|
+
* unhandled rejections. Both note the failure and arm the panic
|
|
752
|
+
* restart so reconcile reverts on the next (clean-looking) boot. */
|
|
748
753
|
MIK_SetErrorHandler(mik_rt, ota_trial_error_handler, nullptr);
|
|
749
|
-
|
|
750
|
-
int rc = MIK_RunEntryErr(mik_rt, app_config.entry_point, entry_err, sizeof(entry_err));
|
|
754
|
+
int rc = MIK_RunEntry(mik_rt, app_config.entry_point);
|
|
751
755
|
if (rc == -EINVAL) {
|
|
752
756
|
ESP_LOGW(TAG, "No entry point configured (no \"main\" field in package.json)");
|
|
753
757
|
} else if (rc == -ENOENT) {
|
|
754
758
|
ESP_LOGW(TAG, "Entry point not found: %s", app_config.entry_point);
|
|
755
759
|
} else if (rc == -EFAULT) {
|
|
760
|
+
/* Already reported to the console by the runtime. */
|
|
756
761
|
ESP_LOGE(TAG, "Failed to evaluate %s", app_config.entry_point);
|
|
757
|
-
/* A synchronous top-level throw doesn't reach the rejection handler
|
|
758
|
-
* above. If this is a trial build, flag it and arm the panic restart
|
|
759
|
-
* so reconcile reverts on the next (clean-looking) boot. */
|
|
760
|
-
if (mik__ota_in_trial()) {
|
|
761
|
-
mik__ota_note_trial_failure(entry_err[0] ? entry_err
|
|
762
|
-
: "entry failed to evaluate");
|
|
763
|
-
MIK_Stop(mik_rt);
|
|
764
|
-
}
|
|
765
762
|
}
|
|
766
763
|
}
|
|
767
764
|
}
|
|
@@ -75,6 +75,10 @@ struct MIKOtaClientState {
|
|
|
75
75
|
* only copy left after ota.reconcile() ran. settle() marks it delivered. */
|
|
76
76
|
bool has_last_install = false;
|
|
77
77
|
MIKOtaDiagnostic last_install = {};
|
|
78
|
+
/* Set by report() when the stored decline made it into the body, so settle()
|
|
79
|
+
* clears only a record the registry has seen. A read that failed leaves the
|
|
80
|
+
* record for the next round. */
|
|
81
|
+
bool decline_reported = false;
|
|
78
82
|
};
|
|
79
83
|
|
|
80
84
|
int mik__ota_client_slot = -1;
|
|
@@ -350,7 +354,8 @@ JSValue kv_string_or_undefined(JSContext* ctx, const char* key) {
|
|
|
350
354
|
MIKOtaClientState* state = state_of(ctx);
|
|
351
355
|
if (!state || !state->env || !state->env->kv_get_str) return JS_UNDEFINED;
|
|
352
356
|
char buf[256] = {};
|
|
353
|
-
if (
|
|
357
|
+
if (state->env->kv_get_str(state->env->opaque, key, buf, sizeof(buf)) != MIK_OTA_KV_OK ||
|
|
358
|
+
buf[0] == '\0') {
|
|
354
359
|
return JS_UNDEFINED;
|
|
355
360
|
}
|
|
356
361
|
return JS_NewString(ctx, buf);
|
|
@@ -911,7 +916,8 @@ JSValue ota_report(JSContext* ctx, JSValue, int, JSValue*) {
|
|
|
911
916
|
* decline(). Without it a registry cannot tell a device still working
|
|
912
917
|
* through a download from one that has stopped. */
|
|
913
918
|
MIKOtaDeclineRecord declined;
|
|
914
|
-
|
|
919
|
+
state->decline_reported = mikrojs::MIKOtaStore(env).GetDecline(&declined);
|
|
920
|
+
if (state->decline_reported) {
|
|
915
921
|
JSValue last = JS_NewObject(ctx);
|
|
916
922
|
JS_SetPropertyStr(ctx, last, "checksum", JS_NewString(ctx, declined.checksum));
|
|
917
923
|
JS_SetPropertyStr(ctx, last, "reason", JS_NewString(ctx, declined.reason));
|
|
@@ -960,10 +966,13 @@ JSValue ota_settle(JSContext* ctx, JSValue, int argc, JSValue* argv) {
|
|
|
960
966
|
/* Confirm before the deliveries, as the built-in does: it must settle the
|
|
961
967
|
* document held BEFORE this round, never the one about to be armed. */
|
|
962
968
|
mikrojs::mik__ota_policy_confirm(state->env);
|
|
963
|
-
/* The round completed, so the cached install report
|
|
964
|
-
* record
|
|
969
|
+
/* The round completed, so the cached install report was delivered, and so
|
|
970
|
+
* was the stored decline record if report() carried it. */
|
|
965
971
|
state->has_last_install = false;
|
|
966
|
-
|
|
972
|
+
if (state->decline_reported) {
|
|
973
|
+
mikrojs::MIKOtaStore(state->env).ClearDecline();
|
|
974
|
+
state->decline_reported = false;
|
|
975
|
+
}
|
|
967
976
|
|
|
968
977
|
bool renamed = false;
|
|
969
978
|
if (usable) {
|
|
@@ -105,11 +105,13 @@ bool env_kv_set_blob(void*, const char* key, const uint8_t* data, size_t len) {
|
|
|
105
105
|
return kv_write_blob(key, data, len);
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
MIKOtaKvStatus env_kv_get_str(void*, const char* key, char* out, size_t max_len) {
|
|
109
109
|
uint8_t buf[320];
|
|
110
110
|
size_t len = sizeof(buf);
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
MIKOtaKvStatus status = kv_read_blob(key, buf, &len);
|
|
112
|
+
if (status != MIK_OTA_KV_OK) return status;
|
|
113
|
+
/* Stored bytes that will not decode are corruption, not absence. */
|
|
114
|
+
return mik__kv_decode_str(buf, len, out, max_len) ? MIK_OTA_KV_OK : MIK_OTA_KV_ERROR;
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
bool env_kv_set_str(void*, const char* key, const char* value) {
|
|
@@ -119,11 +121,12 @@ bool env_kv_set_str(void*, const char* key, const char* value) {
|
|
|
119
121
|
return kv_write_blob(key, buf, needed);
|
|
120
122
|
}
|
|
121
123
|
|
|
122
|
-
|
|
124
|
+
MIKOtaKvStatus env_kv_get_i32(void*, const char* key, int32_t* out) {
|
|
123
125
|
uint8_t buf[16];
|
|
124
126
|
size_t len = sizeof(buf);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
+
MIKOtaKvStatus status = kv_read_blob(key, buf, &len);
|
|
128
|
+
if (status != MIK_OTA_KV_OK) return status;
|
|
129
|
+
return mik__kv_decode_i32(buf, len, out) ? MIK_OTA_KV_OK : MIK_OTA_KV_ERROR;
|
|
127
130
|
}
|
|
128
131
|
|
|
129
132
|
bool env_kv_set_i32(void*, const char* key, int32_t value) {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# ble_test.cpp references mik__ble_consume which is only defined when
|
|
2
|
-
# NimBLE (CONFIG_BT_ENABLED) is available
|
|
2
|
+
# NimBLE (CONFIG_BT_ENABLED) is available, and wifi_test.cpp references
|
|
3
|
+
# mik__wifi_consume which needs CONFIG_MIKROJS_WIFI. Exclude each for
|
|
4
|
+
# builds without its stack.
|
|
3
5
|
set(_MIK_TEST_SRCS
|
|
4
6
|
abort_test.cpp
|
|
5
7
|
fs_js_test.cpp
|
|
@@ -25,11 +27,13 @@ set(_MIK_TEST_SRCS
|
|
|
25
27
|
timers_test.cpp
|
|
26
28
|
udp_test.cpp
|
|
27
29
|
watchdog_test.cpp
|
|
28
|
-
wifi_test.cpp
|
|
29
30
|
)
|
|
30
31
|
if(CONFIG_BT_ENABLED)
|
|
31
32
|
list(APPEND _MIK_TEST_SRCS ble_test.cpp)
|
|
32
33
|
endif()
|
|
34
|
+
if(CONFIG_MIKROJS_WIFI)
|
|
35
|
+
list(APPEND _MIK_TEST_SRCS wifi_test.cpp)
|
|
36
|
+
endif()
|
|
33
37
|
|
|
34
38
|
idf_component_register(SRCS ${_MIK_TEST_SRCS}
|
|
35
39
|
INCLUDE_DIRS "."
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikrojs/firmware",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.2-next.20260907205905",
|
|
4
4
|
"description": "Mikro.js ESP32 firmware: ESP-IDF component, build tools, and project template",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"esp-idf",
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
"./package.json": "./package.json"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"
|
|
50
|
-
"@mikrojs/
|
|
51
|
-
"
|
|
49
|
+
"@mikrojs/native": "0.20.2-next.20260907205905+8b6f502",
|
|
50
|
+
"@mikrojs/quickjs": "0.20.2-next.20260907205905+8b6f502",
|
|
51
|
+
"esbuild": "^0.28.2"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
|
54
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
|