Add ability to reserve psram
.. the primary user of which will be the camera, since the framebuffers must be allocated via esp-idf allocation function and never from the gc heap. A board can have a default value, and the value can also be set in the /.env file using the key CIRCUITPY_RESERVED_PSRAM with the value being the reserved size in bytes. Co-authored-by: Dan Halbert <halbert@adafruit.com>
This commit is contained in:
parent
d659a3b457
commit
82be75adb5
|
@ -35,6 +35,12 @@ CIRCUITPY_BLE_NAME
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
Default BLE name the board advertises as, including for the BLE workflow.
|
Default BLE name the board advertises as, including for the BLE workflow.
|
||||||
|
|
||||||
|
CIRCUITPY_RESERVED_PSRAM
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
On boards with Espressif microcontrollers with PSRAM (also called SPIRAM), permanently reserve a portion of PSRAM for use by esp-idf.
|
||||||
|
This storage is removed from the CircuitPython "heap" and is available for allocation by esp-idf routines in the core instead.
|
||||||
|
Generally, only set this to a non-zero value when it is required by a specific core module.
|
||||||
|
|
||||||
CIRCUITPY_WEB_API_PASSWORD
|
CIRCUITPY_WEB_API_PASSWORD
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
Password required to make modifications to the board from the Web Workflow.
|
Password required to make modifications to the board from the Web Workflow.
|
||||||
|
|
|
@ -209,7 +209,7 @@ msgstr ""
|
||||||
msgid "%q=%q"
|
msgid "%q=%q"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ports/espressif/bindings/espidf/__init__.c ports/espressif/esp_error.c
|
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s error 0x%x"
|
msgid "%s error 0x%x"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -645,7 +645,7 @@ msgstr ""
|
||||||
msgid "CIRCUITPY drive could not be found or created."
|
msgid "CIRCUITPY drive could not be found or created."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ports/espressif/bindings/espidf/__init__.c ports/espressif/esp_error.c
|
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
|
||||||
msgid "CRC or checksum was invalid"
|
msgid "CRC or checksum was invalid"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1019,7 +1019,7 @@ msgstr ""
|
||||||
msgid "GNSS init"
|
msgid "GNSS init"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ports/espressif/bindings/espidf/__init__.c ports/espressif/esp_error.c
|
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
|
||||||
msgid "Generic Failure"
|
msgid "Generic Failure"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1188,7 +1188,7 @@ msgstr ""
|
||||||
msgid "Invalid MAC address"
|
msgid "Invalid MAC address"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ports/espressif/bindings/espidf/__init__.c ports/espressif/esp_error.c
|
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
|
||||||
#: py/moduerrno.c
|
#: py/moduerrno.c
|
||||||
msgid "Invalid argument"
|
msgid "Invalid argument"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1218,7 +1218,7 @@ msgstr ""
|
||||||
msgid "Invalid pins"
|
msgid "Invalid pins"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ports/espressif/bindings/espidf/__init__.c ports/espressif/esp_error.c
|
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
|
||||||
msgid "Invalid size"
|
msgid "Invalid size"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1226,7 +1226,7 @@ msgstr ""
|
||||||
msgid "Invalid socket for TLS"
|
msgid "Invalid socket for TLS"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ports/espressif/bindings/espidf/__init__.c ports/espressif/esp_error.c
|
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
|
||||||
msgid "Invalid state"
|
msgid "Invalid state"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1250,7 +1250,7 @@ msgstr ""
|
||||||
msgid "Layer must be a Group or TileGrid subclass"
|
msgid "Layer must be a Group or TileGrid subclass"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ports/espressif/bindings/espidf/__init__.c ports/espressif/esp_error.c
|
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
|
||||||
msgid "MAC address was invalid"
|
msgid "MAC address was invalid"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1600,15 +1600,15 @@ msgstr ""
|
||||||
msgid "Operation not permitted"
|
msgid "Operation not permitted"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ports/espressif/bindings/espidf/__init__.c ports/espressif/esp_error.c
|
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
|
||||||
msgid "Operation or feature not supported"
|
msgid "Operation or feature not supported"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ports/espressif/bindings/espidf/__init__.c ports/espressif/esp_error.c
|
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
|
||||||
msgid "Operation timed out"
|
msgid "Operation timed out"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ports/espressif/bindings/espidf/__init__.c ports/espressif/esp_error.c
|
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
|
||||||
msgid "Out of memory"
|
msgid "Out of memory"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1783,7 +1783,7 @@ msgstr ""
|
||||||
msgid "Read-only object"
|
msgid "Read-only object"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ports/espressif/bindings/espidf/__init__.c ports/espressif/esp_error.c
|
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
|
||||||
msgid "Received response was invalid"
|
msgid "Received response was invalid"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -1799,7 +1799,7 @@ msgstr ""
|
||||||
msgid "Requested AES mode is unsupported"
|
msgid "Requested AES mode is unsupported"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ports/espressif/bindings/espidf/__init__.c ports/espressif/esp_error.c
|
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
|
||||||
msgid "Requested resource not found"
|
msgid "Requested resource not found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -2221,7 +2221,7 @@ msgstr ""
|
||||||
msgid "Value length > max_length"
|
msgid "Value length > max_length"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: ports/espressif/bindings/espidf/__init__.c ports/espressif/esp_error.c
|
#: ports/espressif/common-hal/espidf/__init__.c ports/espressif/esp_error.c
|
||||||
msgid "Version was invalid"
|
msgid "Version was invalid"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
4
main.c
4
main.c
|
@ -792,8 +792,12 @@ STATIC void __attribute__ ((noinline)) run_boot_py(safe_mode_t safe_mode) {
|
||||||
usb_get_boot_py_data(usb_boot_py_data, size);
|
usb_get_boot_py_data(usb_boot_py_data, size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
port_post_boot_py(true);
|
||||||
|
|
||||||
cleanup_after_vm(heap, result.exception);
|
cleanup_after_vm(heap, result.exception);
|
||||||
|
|
||||||
|
port_post_boot_py(false);
|
||||||
|
|
||||||
#if CIRCUITPY_USB
|
#if CIRCUITPY_USB
|
||||||
// Now give back the data we saved from the heap going away.
|
// Now give back the data we saved from the heap going away.
|
||||||
usb_return_boot_py_data(usb_boot_py_data, size);
|
usb_return_boot_py_data(usb_boot_py_data, size);
|
||||||
|
|
|
@ -281,6 +281,8 @@ ifneq ($(CIRCUITPY_BLEIO),0)
|
||||||
SRC_C += common-hal/_bleio/ble_events.c
|
SRC_C += common-hal/_bleio/ble_events.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
SRC_C += $(wildcard common-hal/espidf/*.c)
|
||||||
|
|
||||||
SRC_COMMON_HAL_EXPANDED = \
|
SRC_COMMON_HAL_EXPANDED = \
|
||||||
$(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
|
$(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
|
||||||
$(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \
|
$(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \
|
||||||
|
|
|
@ -120,6 +120,20 @@ const mp_obj_type_t mp_type_espidf_MemoryError = {
|
||||||
.parent = &mp_type_MemoryError,
|
.parent = &mp_type_MemoryError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//| def get_total_psram() -> int:
|
||||||
|
//| """Returns the number of bytes of psram detected, or 0 if psram is not present or not configured"""
|
||||||
|
STATIC mp_obj_t espidf_get_total_psram(void) {
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(common_hal_espidf_get_total_psram());
|
||||||
|
}
|
||||||
|
MP_DEFINE_CONST_FUN_OBJ_0(espidf_get_total_psram_obj, espidf_get_total_psram);
|
||||||
|
|
||||||
|
//| def get_reserved_psram() -> int:
|
||||||
|
//| """Returns number of bytes of psram reserved for use by esp-idf, either a board-specific default value or the value defined in ``/.env``."""
|
||||||
|
STATIC mp_obj_t espidf_get_reserved_psram(void) {
|
||||||
|
return MP_OBJ_NEW_SMALL_INT(common_hal_espidf_get_reserved_psram());
|
||||||
|
}
|
||||||
|
MP_DEFINE_CONST_FUN_OBJ_0(espidf_get_reserved_psram_obj, espidf_get_reserved_psram);
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t espidf_module_globals_table[] = {
|
STATIC const mp_rom_map_elem_t espidf_module_globals_table[] = {
|
||||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_espidf) },
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_espidf) },
|
||||||
|
|
||||||
|
@ -129,6 +143,8 @@ STATIC const mp_rom_map_elem_t espidf_module_globals_table[] = {
|
||||||
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_erase_nvs), MP_ROM_PTR(&espidf_erase_nvs_obj)},
|
{ MP_ROM_QSTR(MP_QSTR_erase_nvs), MP_ROM_PTR(&espidf_erase_nvs_obj)},
|
||||||
|
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_get_total_psram), MP_ROM_PTR(&espidf_get_total_psram_obj)},
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_get_reserved_psram), MP_ROM_PTR(&espidf_get_reserved_psram_obj)},
|
||||||
{ MP_ROM_QSTR(MP_QSTR_IDFError), MP_ROM_PTR(&mp_type_espidf_IDFError) },
|
{ MP_ROM_QSTR(MP_QSTR_IDFError), MP_ROM_PTR(&mp_type_espidf_IDFError) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_MemoryError), MP_ROM_PTR(&mp_type_espidf_MemoryError) },
|
{ MP_ROM_QSTR(MP_QSTR_MemoryError), MP_ROM_PTR(&mp_type_espidf_MemoryError) },
|
||||||
};
|
};
|
||||||
|
@ -139,66 +155,3 @@ const mp_obj_module_t espidf_module = {
|
||||||
.base = { &mp_type_module },
|
.base = { &mp_type_module },
|
||||||
.globals = (mp_obj_dict_t *)&espidf_module_globals,
|
.globals = (mp_obj_dict_t *)&espidf_module_globals,
|
||||||
};
|
};
|
||||||
|
|
||||||
void raise_esp_error(esp_err_t err) {
|
|
||||||
const compressed_string_t *msg = NULL;
|
|
||||||
const mp_obj_type_t *exception_type = &mp_type_espidf_IDFError;
|
|
||||||
switch (err) {
|
|
||||||
case ESP_FAIL:
|
|
||||||
msg = translate("Generic Failure");
|
|
||||||
break;
|
|
||||||
case ESP_ERR_NO_MEM:
|
|
||||||
exception_type = &mp_type_espidf_MemoryError;
|
|
||||||
msg = translate("Out of memory");
|
|
||||||
break;
|
|
||||||
case ESP_ERR_INVALID_ARG:
|
|
||||||
msg = translate("Invalid argument");
|
|
||||||
break;
|
|
||||||
case ESP_ERR_INVALID_STATE:
|
|
||||||
msg = translate("Invalid state");
|
|
||||||
break;
|
|
||||||
case ESP_ERR_INVALID_SIZE:
|
|
||||||
msg = translate("Invalid size");
|
|
||||||
break;
|
|
||||||
case ESP_ERR_NOT_FOUND:
|
|
||||||
msg = translate("Requested resource not found");
|
|
||||||
break;
|
|
||||||
case ESP_ERR_NOT_SUPPORTED:
|
|
||||||
msg = translate("Operation or feature not supported");
|
|
||||||
break;
|
|
||||||
case ESP_ERR_TIMEOUT:
|
|
||||||
msg = translate("Operation timed out");
|
|
||||||
break;
|
|
||||||
case ESP_ERR_INVALID_RESPONSE:
|
|
||||||
msg = translate("Received response was invalid");
|
|
||||||
break;
|
|
||||||
case ESP_ERR_INVALID_CRC:
|
|
||||||
msg = translate("CRC or checksum was invalid");
|
|
||||||
break;
|
|
||||||
case ESP_ERR_INVALID_VERSION:
|
|
||||||
msg = translate("Version was invalid");
|
|
||||||
break;
|
|
||||||
case ESP_ERR_INVALID_MAC:
|
|
||||||
msg = translate("MAC address was invalid");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (msg) {
|
|
||||||
mp_raise_msg(exception_type, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *group = "ESP-IDF";
|
|
||||||
|
|
||||||
// tests must be in descending order
|
|
||||||
MP_STATIC_ASSERT(ESP_ERR_FLASH_BASE > ESP_ERR_MESH_BASE);
|
|
||||||
MP_STATIC_ASSERT(ESP_ERR_MESH_BASE > ESP_ERR_WIFI_BASE);
|
|
||||||
if (err >= ESP_ERR_FLASH_BASE) {
|
|
||||||
group = "Flash";
|
|
||||||
} else if (err >= ESP_ERR_MESH_BASE) {
|
|
||||||
group = "Mesh";
|
|
||||||
} else if (err >= ESP_ERR_WIFI_BASE) {
|
|
||||||
group = "WiFi";
|
|
||||||
}
|
|
||||||
mp_raise_msg_varg(exception_type, translate("%s error 0x%x"), group, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
MP_REGISTER_MODULE(MP_QSTR_espidf, espidf_module, CIRCUITPY_ESPIDF);
|
|
||||||
|
|
|
@ -39,4 +39,11 @@ NORETURN void mp_raise_espidf_MemoryError(void);
|
||||||
void raise_esp_error(esp_err_t err) NORETURN;
|
void raise_esp_error(esp_err_t err) NORETURN;
|
||||||
#define CHECK_ESP_RESULT(x) do { int res = (x); if (res != ESP_OK) raise_esp_error(res); } while (0)
|
#define CHECK_ESP_RESULT(x) do { int res = (x); if (res != ESP_OK) raise_esp_error(res); } while (0)
|
||||||
|
|
||||||
|
void common_hal_espidf_reserve_psram(void);
|
||||||
|
bool common_hal_espidf_set_reserved_psram(size_t amount);
|
||||||
|
size_t common_hal_espidf_get_reserved_psram(void);
|
||||||
|
size_t common_hal_espidf_get_total_psram(void);
|
||||||
|
intptr_t common_hal_espidf_get_psram_start(void);
|
||||||
|
intptr_t common_hal_espidf_get_psram_end(void);
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_ESPRESSIF_BINDINGS_ESPIDF___INIT___H
|
#endif // MICROPY_INCLUDED_ESPRESSIF_BINDINGS_ESPIDF___INIT___H
|
||||||
|
|
|
@ -0,0 +1,194 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Jeff Epler for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "bindings/espidf/__init__.h"
|
||||||
|
#include "supervisor/shared/translate/translate.h"
|
||||||
|
#include "supervisor/memory.h"
|
||||||
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
#include "esp_log.h"
|
||||||
|
#define TAG "espidf"
|
||||||
|
|
||||||
|
#ifdef CONFIG_SPIRAM
|
||||||
|
#include "esp32/spiram.h"
|
||||||
|
#include "esp_heap_caps.h"
|
||||||
|
#include "esp_heap_caps_init.h"
|
||||||
|
#include "soc/soc.h"
|
||||||
|
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||||
|
#include "esp32/himem.h"
|
||||||
|
#else
|
||||||
|
#define esp_himem_reserved_area_size() (0)
|
||||||
|
#endif
|
||||||
|
bool ok_to_reserve_psram = true;
|
||||||
|
size_t reserved_psram = DEFAULT_RESERVED_PSRAM;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static size_t psram_size_usable(void) {
|
||||||
|
#ifdef CONFIG_SPIRAM
|
||||||
|
/* PSRAM chip may be larger than the size we can map into address space */
|
||||||
|
size_t s = MIN(esp_spiram_get_size(), SOC_EXTRAM_DATA_SIZE);
|
||||||
|
return s - esp_himem_reserved_area_size();
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool common_hal_espidf_set_reserved_psram(size_t amount) {
|
||||||
|
#ifdef CONFIG_SPIRAM
|
||||||
|
if (!esp_spiram_is_initialized()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ok_to_reserve_psram) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (amount > psram_size_usable()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
reserved_psram = amount;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
supervisor_allocation *psram_for_idf;
|
||||||
|
|
||||||
|
void common_hal_espidf_reserve_psram(void) {
|
||||||
|
#ifdef CONFIG_SPIRAM
|
||||||
|
if (!psram_for_idf) {
|
||||||
|
ESP_LOGI(TAG, "Reserving %d bytes of psram", reserved_psram);
|
||||||
|
if (reserved_psram == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
psram_for_idf = allocate_memory(reserved_psram, true, false);
|
||||||
|
if (psram_for_idf) {
|
||||||
|
intptr_t psram_for_idf_start = (intptr_t)psram_for_idf->ptr;
|
||||||
|
intptr_t psram_for_idf_end = psram_for_idf_start + reserved_psram;
|
||||||
|
ESP_LOGI(TAG, "Reserved %x..%x", psram_for_idf_start, psram_for_idf_end);
|
||||||
|
heap_caps_add_region(psram_for_idf_start, psram_for_idf_end);
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "supervisor allocation failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t common_hal_espidf_get_reserved_psram(void) {
|
||||||
|
#ifdef CONFIG_SPIRAM
|
||||||
|
return reserved_psram;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t common_hal_espidf_get_total_psram(void) {
|
||||||
|
return psram_size_usable();
|
||||||
|
}
|
||||||
|
|
||||||
|
intptr_t common_hal_espidf_get_psram_start(void) {
|
||||||
|
#ifdef CONFIG_SPIRAM
|
||||||
|
if (esp_spiram_is_initialized()) {
|
||||||
|
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||||
|
return SOC_EXTRAM_DATA_LOW;
|
||||||
|
#else
|
||||||
|
return SOC_EXTRAM_DATA_HIGH - psram_size_usable();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
intptr_t common_hal_espidf_get_psram_end(void) {
|
||||||
|
#ifdef CONFIG_SPIRAM
|
||||||
|
if (esp_spiram_is_initialized()) {
|
||||||
|
return common_hal_espidf_get_psram_start() + psram_size_usable();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void raise_esp_error(esp_err_t err) {
|
||||||
|
const compressed_string_t *msg = NULL;
|
||||||
|
const mp_obj_type_t *exception_type = &mp_type_espidf_IDFError;
|
||||||
|
switch (err) {
|
||||||
|
case ESP_FAIL:
|
||||||
|
msg = translate("Generic Failure");
|
||||||
|
break;
|
||||||
|
case ESP_ERR_NO_MEM:
|
||||||
|
exception_type = &mp_type_espidf_MemoryError;
|
||||||
|
msg = translate("Out of memory");
|
||||||
|
break;
|
||||||
|
case ESP_ERR_INVALID_ARG:
|
||||||
|
msg = translate("Invalid argument");
|
||||||
|
break;
|
||||||
|
case ESP_ERR_INVALID_STATE:
|
||||||
|
msg = translate("Invalid state");
|
||||||
|
break;
|
||||||
|
case ESP_ERR_INVALID_SIZE:
|
||||||
|
msg = translate("Invalid size");
|
||||||
|
break;
|
||||||
|
case ESP_ERR_NOT_FOUND:
|
||||||
|
msg = translate("Requested resource not found");
|
||||||
|
break;
|
||||||
|
case ESP_ERR_NOT_SUPPORTED:
|
||||||
|
msg = translate("Operation or feature not supported");
|
||||||
|
break;
|
||||||
|
case ESP_ERR_TIMEOUT:
|
||||||
|
msg = translate("Operation timed out");
|
||||||
|
break;
|
||||||
|
case ESP_ERR_INVALID_RESPONSE:
|
||||||
|
msg = translate("Received response was invalid");
|
||||||
|
break;
|
||||||
|
case ESP_ERR_INVALID_CRC:
|
||||||
|
msg = translate("CRC or checksum was invalid");
|
||||||
|
break;
|
||||||
|
case ESP_ERR_INVALID_VERSION:
|
||||||
|
msg = translate("Version was invalid");
|
||||||
|
break;
|
||||||
|
case ESP_ERR_INVALID_MAC:
|
||||||
|
msg = translate("MAC address was invalid");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (msg) {
|
||||||
|
mp_raise_msg(exception_type, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *group = "ESP-IDF";
|
||||||
|
|
||||||
|
// tests must be in descending order
|
||||||
|
MP_STATIC_ASSERT(ESP_ERR_FLASH_BASE > ESP_ERR_MESH_BASE);
|
||||||
|
MP_STATIC_ASSERT(ESP_ERR_MESH_BASE > ESP_ERR_WIFI_BASE);
|
||||||
|
if (err >= ESP_ERR_FLASH_BASE) {
|
||||||
|
group = "Flash";
|
||||||
|
} else if (err >= ESP_ERR_MESH_BASE) {
|
||||||
|
group = "Mesh";
|
||||||
|
} else if (err >= ESP_ERR_WIFI_BASE) {
|
||||||
|
group = "WiFi";
|
||||||
|
}
|
||||||
|
mp_raise_msg_varg(exception_type, translate("%s error 0x%x"), group, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
MP_REGISTER_MODULE(MP_QSTR_espidf, espidf_module, CIRCUITPY_ESPIDF);
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022 Jeff Epler for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "bindings/espidf/__init__.h"
|
|
@ -90,4 +90,13 @@
|
||||||
#define CIRCUITPY_ESP_USB_SERIAL_JTAG (0)
|
#define CIRCUITPY_ESP_USB_SERIAL_JTAG (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef DEFAULT_RESERVED_PSRAM
|
||||||
|
#define DEFAULT_RESERVED_PSRAM (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_SPIRAM)
|
||||||
|
#undef CIRCUITPY_PORT_NUM_SUPERVISOR_ALLOCATIONS
|
||||||
|
#define CIRCUITPY_PORT_NUM_SUPERVISOR_ALLOCATIONS (1)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_ESPRESSIF_MPCONFIGPORT_H
|
#endif // MICROPY_INCLUDED_ESPRESSIF_MPCONFIGPORT_H
|
||||||
|
|
|
@ -29,11 +29,13 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include "supervisor/board.h"
|
#include "supervisor/board.h"
|
||||||
#include "supervisor/port.h"
|
#include "supervisor/port.h"
|
||||||
|
#include "supervisor/filesystem.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
|
||||||
|
#include "bindings/espidf/__init__.h"
|
||||||
#include "common-hal/microcontroller/Pin.h"
|
#include "common-hal/microcontroller/Pin.h"
|
||||||
#include "common-hal/analogio/AnalogOut.h"
|
#include "common-hal/analogio/AnalogOut.h"
|
||||||
#include "common-hal/busio/I2C.h"
|
#include "common-hal/busio/I2C.h"
|
||||||
|
@ -53,6 +55,7 @@
|
||||||
#include "shared-bindings/microcontroller/RunMode.h"
|
#include "shared-bindings/microcontroller/RunMode.h"
|
||||||
#include "shared-bindings/rtc/__init__.h"
|
#include "shared-bindings/rtc/__init__.h"
|
||||||
#include "shared-bindings/socketpool/__init__.h"
|
#include "shared-bindings/socketpool/__init__.h"
|
||||||
|
#include "shared-module/dotenv/__init__.h"
|
||||||
|
|
||||||
#include "peripherals/rmt.h"
|
#include "peripherals/rmt.h"
|
||||||
#include "peripherals/timer.h"
|
#include "peripherals/timer.h"
|
||||||
|
@ -95,20 +98,8 @@
|
||||||
#include "esp32/rom/efuse.h"
|
#include "esp32/rom/efuse.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SPIRAM
|
#include "esp_log.h"
|
||||||
#include "esp32/spiram.h"
|
#define TAG "port"
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
|
||||||
#include "esp32/himem.h"
|
|
||||||
#else
|
|
||||||
#define esp_himem_reserved_area_size() (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static size_t spiram_size_usable(void) {
|
|
||||||
/* SPIRAM chip may be larger than the size we can map into address space */
|
|
||||||
size_t s = MIN(esp_spiram_get_size(), SOC_EXTRAM_DATA_SIZE);
|
|
||||||
return s - esp_himem_reserved_area_size();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint32_t *heap;
|
uint32_t *heap;
|
||||||
uint32_t heap_size;
|
uint32_t heap_size;
|
||||||
|
@ -298,14 +289,16 @@ safe_mode_t port_init(void) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SPIRAM
|
#ifdef CONFIG_SPIRAM
|
||||||
if (esp_spiram_is_initialized()) {
|
{
|
||||||
size_t spiram_size = spiram_size_usable();
|
intptr_t heap_start = common_hal_espidf_get_psram_start();
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
intptr_t heap_end = common_hal_espidf_get_psram_end();
|
||||||
heap = (uint32_t *)SOC_EXTRAM_DATA_LOW;
|
size_t spiram_size = heap_end - heap_start;
|
||||||
#else
|
if (spiram_size > 0) {
|
||||||
heap = (uint32_t *)(SOC_EXTRAM_DATA_HIGH - spiram_size);
|
heap = (uint32_t *)heap_start;
|
||||||
#endif
|
heap_size = (heap_end - heap_start) / sizeof(uint32_t);
|
||||||
heap_size = spiram_size / sizeof(uint32_t);
|
} else {
|
||||||
|
ESP_LOGE(TAG, "CONFIG_SPIRAM enabled but no spiram heap available");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -514,6 +507,16 @@ void port_idle_until_interrupt(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void port_post_boot_py(bool heap_valid) {
|
||||||
|
if (!heap_valid && filesystem_present()) {
|
||||||
|
mp_int_t reserved;
|
||||||
|
if (dotenv_get_key_int("/.env", "CIRCUITPY_RESERVED_PSRAM", &reserved)) {
|
||||||
|
common_hal_espidf_set_reserved_psram(reserved);
|
||||||
|
}
|
||||||
|
common_hal_espidf_reserve_psram();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Wrap main in app_main that the IDF expects.
|
// Wrap main in app_main that the IDF expects.
|
||||||
extern void main(void);
|
extern void main(void);
|
||||||
extern void app_main(void);
|
extern void app_main(void);
|
||||||
|
|
|
@ -564,6 +564,10 @@ void supervisor_run_background_tasks_if_tick(void);
|
||||||
#error "CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR must be at least 1"
|
#error "CIRCUITPY_USB_HID_MAX_REPORT_IDS_PER_DESCRIPTOR must be at least 1"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CIRCUITPY_PORT_NUM_SUPERVISOR_ALLOCATIONS
|
||||||
|
#define CIRCUITPY_PORT_NUM_SUPERVISOR_ALLOCATIONS (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef USB_MIDI_EP_NUM_OUT
|
#ifndef USB_MIDI_EP_NUM_OUT
|
||||||
#define USB_MIDI_EP_NUM_OUT (0)
|
#define USB_MIDI_EP_NUM_OUT (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "shared-bindings/dotenv/__init__.h"
|
#include "shared-bindings/dotenv/__init__.h"
|
||||||
|
@ -223,3 +224,26 @@ mp_obj_t common_hal_dotenv_get_key(const char *path, const char *key) {
|
||||||
}
|
}
|
||||||
return mp_obj_new_str(value, actual_len);
|
return mp_obj_new_str(value, actual_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dotenv_get_key_terminated(const char *path, const char *key, char *value, mp_int_t value_len) {
|
||||||
|
mp_int_t actual_len = dotenv_get_key(path, key, value, value_len - 1);
|
||||||
|
if (actual_len >= value_len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
value[actual_len] = '\0'; // terminate string
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dotenv_get_key_int(const char *path, const char *key, mp_int_t *value) {
|
||||||
|
char buf[16];
|
||||||
|
if (!dotenv_get_key_terminated(path, key, buf, (mp_int_t)sizeof(buf))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char *end;
|
||||||
|
long result = strtol(buf, &end, 0);
|
||||||
|
if (end == buf || *end) { // If the whole buffer was not consumed it's an error
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*value = (mp_int_t)result;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -26,3 +26,11 @@
|
||||||
|
|
||||||
// Allocation free version that returns the full length of the value.
|
// Allocation free version that returns the full length of the value.
|
||||||
mp_int_t dotenv_get_key(const char *path, const char *key, char *value, mp_int_t value_len);
|
mp_int_t dotenv_get_key(const char *path, const char *key, char *value, mp_int_t value_len);
|
||||||
|
|
||||||
|
// Returns true and sets value to a '\0'-terminated string if key is present
|
||||||
|
// and the value (including the terminating '\0') fits strictly within
|
||||||
|
// value_len bytes.
|
||||||
|
bool dotenv_get_key_terminated(const char *path, const char *key, char *value, mp_int_t value_len);
|
||||||
|
|
||||||
|
// Returns true and sets value to the read value. Returns false if the value was not numeric.
|
||||||
|
bool dotenv_get_key_int(const char *path, const char *key, mp_int_t *value);
|
||||||
|
|
|
@ -109,4 +109,10 @@ void port_wake_main_task(void);
|
||||||
// default weak implementation is provided that does nothing.
|
// default weak implementation is provided that does nothing.
|
||||||
void port_wake_main_task_from_isr(void);
|
void port_wake_main_task_from_isr(void);
|
||||||
|
|
||||||
|
// Some ports need special handling just after completing boot.py execution.
|
||||||
|
// This function is called once while boot.py's VM is still valid, and
|
||||||
|
// then a second time after the VM is finalized.
|
||||||
|
// A default weak implementation is provided that does nothing.
|
||||||
|
void port_post_boot_py(bool heap_valid);
|
||||||
|
|
||||||
#endif // MICROPY_INCLUDED_SUPERVISOR_PORT_H
|
#endif // MICROPY_INCLUDED_SUPERVISOR_PORT_H
|
||||||
|
|
|
@ -56,6 +56,8 @@ enum {
|
||||||
#if CIRCUITPY_USB_VENDOR
|
#if CIRCUITPY_USB_VENDOR
|
||||||
+ 1 // usb_vendor_add_descriptor
|
+ 1 // usb_vendor_add_descriptor
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
+ CIRCUITPY_PORT_NUM_SUPERVISOR_ALLOCATIONS
|
||||||
,
|
,
|
||||||
|
|
||||||
CIRCUITPY_SUPERVISOR_MOVABLE_ALLOC_COUNT =
|
CIRCUITPY_SUPERVISOR_MOVABLE_ALLOC_COUNT =
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2022 Jeff Epler for Adafruit Industries
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
#include "stdbool.h"
|
||||||
|
|
||||||
|
#include "supervisor/port.h"
|
||||||
|
#include "py/mpconfig.h"
|
||||||
|
|
||||||
|
|
||||||
|
MP_WEAK void port_post_boot_py(bool heap_valid) {
|
||||||
|
}
|
|
@ -18,7 +18,8 @@ SRC_SUPERVISOR = \
|
||||||
supervisor/shared/title_bar.c \
|
supervisor/shared/title_bar.c \
|
||||||
supervisor/shared/traceback.c \
|
supervisor/shared/traceback.c \
|
||||||
supervisor/shared/translate/translate.c \
|
supervisor/shared/translate/translate.c \
|
||||||
supervisor/shared/workflow.c
|
supervisor/shared/workflow.c \
|
||||||
|
supervisor/stub/misc.c \
|
||||||
|
|
||||||
NO_USB ?= $(wildcard supervisor/usb.c)
|
NO_USB ?= $(wildcard supervisor/usb.c)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue