mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-19 23:22:16 +03:00
Heap addendum to handle changes in NON-OS SDK 3.0.x (#8746)
## WPA2 Enterprise connections
References - merged PRs:
* https://github.com/esp8266/Arduino/pull/8529
* https://github.com/esp8266/Arduino/pull/8566 - these occurred with connect/disconnect with WPA-Enterprise
* https://github.com/esp8266/Arduino/pull/8736#issue-1470774550
The NON-OS SDK 3.0.x has breaking changes to the [`pvPortMalloc`](bf890b22e5/include/mem.h (L42)
) function. They added a new `bool` argument for selecting a heap.
```cpp
void *pvPortMalloc (size_t sz, const char *, unsigned, bool);
```
To avoid breaking the build, I added a new thin wrapper function `sdk3_pvPortMalloc` to `heap.cpp`.
Edited new SDK LIBs to call `pvPortMalloc`'s replacement `sdk3_pvPortMalloc`.
They also added `pvPortZallocIram` and `pvPortCallocIram`, which are not a problem to support. Support added to `heap.cpp`.
Issues with WPA2 Enterprise in new SDKs:
* v3.0.0 and v3.0.1 - have the same memory leak and duplicate free bugs from before
* v3.0.2 through v3.0.5 - have the same memory leak; however, _no_ duplicate free crash.
* memory leak can be seen by cycling through setup, connect, disconnect, and clear setup - repeatedly.
Updated `wpa2_eap_patch.cpp` and binary patch scripts to handle v3.0.0 through v3.0.5.
Patched SDKs v3.0.0 through v3.0.5
## Duplicate Non-32-bit exception handler
Issue: At v3.0.0 and above `libmain.a` supplies a built-in exception handler (`load_non_32_wide_handler`) for non-32-bit access. Our non-32-bit access handler (`non32xfer_exception_handler`) overrides it.
Solution: Add "weak" attribute to symbol `load_non_32_wide_handler`. Adjust the build to default to the SDK's built-in non-32-bit handler. If there is a need to use our non-32-bit handler, make the selection from the Arduino IDE Tools menu `Non-32-Bit Access: "Byte/Word access to IRAM/PROGMEM (very slow)"`.
With SDKs v3.0.0 and above a "non-32-bit exception handler" is always present.
This commit is contained in:
parent
d3c8d272d7
commit
4a0b66b017
@ -496,7 +496,7 @@ extern "C" void user_init(void) {
|
|||||||
install_vm_exception_handler();
|
install_vm_exception_handler();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP)
|
#if defined(NON32XFER_HANDLER) || (defined(MMU_IRAM_HEAP) && (NONOSDK < (0x30000 - 1)))
|
||||||
install_non32xfer_exception_handler();
|
install_non32xfer_exception_handler();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -26,10 +26,14 @@
|
|||||||
* Code taken directly from @pvvx's public domain code in
|
* Code taken directly from @pvvx's public domain code in
|
||||||
* https://github.com/pvvx/esp8266web/blob/master/app/sdklib/system/app_main.c
|
* https://github.com/pvvx/esp8266web/blob/master/app/sdklib/system/app_main.c
|
||||||
*
|
*
|
||||||
|
* In Espressif versions NONOSDK v3.0.0+ a similar feature was added
|
||||||
|
* load_non_32_wide_handler. Theirs is always loaded. Add weak attribute to
|
||||||
|
* theirs so we can choose by adding an alias to ours.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <user_interface.h>
|
||||||
#define VERIFY_C_ASM_EXCEPTION_FRAME_STRUCTURE
|
#define VERIFY_C_ASM_EXCEPTION_FRAME_STRUCTURE
|
||||||
#include <esp8266_undocumented.h>
|
#include <esp8266_undocumented.h>
|
||||||
#include <core_esp8266_non32xfer.h>
|
#include <core_esp8266_non32xfer.h>
|
||||||
@ -58,10 +62,13 @@ extern "C" {
|
|||||||
|
|
||||||
#define EXCCAUSE_LOAD_STORE_ERROR 3 /* Non 32-bit read/write error */
|
#define EXCCAUSE_LOAD_STORE_ERROR 3 /* Non 32-bit read/write error */
|
||||||
|
|
||||||
|
#if (defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP)) && (NONOSDK < (0x30000 - 1))
|
||||||
static fn_c_exception_handler_t old_c_handler = NULL;
|
static fn_c_exception_handler_t old_c_handler = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(NON32XFER_HANDLER) || (defined(MMU_IRAM_HEAP) && (NONOSDK < (0x30000 - 1)))
|
||||||
static
|
static
|
||||||
IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef, int cause)
|
IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef, [[maybe_unused]] int cause)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
uint32_t insn, excvaddr;
|
uint32_t insn, excvaddr;
|
||||||
@ -138,6 +145,7 @@ IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef, int cau
|
|||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
/* Fail request, die */
|
/* Fail request, die */
|
||||||
|
#if (NONOSDK < (0x30000 - 1))
|
||||||
/*
|
/*
|
||||||
The old handler points to the SDK. Be alert for HWDT when Calling with
|
The old handler points to the SDK. Be alert for HWDT when Calling with
|
||||||
INTLEVEL != 0. I cannot create it any more. I thought I saw this as a
|
INTLEVEL != 0. I cannot create it any more. I thought I saw this as a
|
||||||
@ -148,16 +156,23 @@ IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef, int cau
|
|||||||
old_c_handler(ef, cause);
|
old_c_handler(ef, cause);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
Calling _xtos_unhandled_exception(ef, cause) in the Boot ROM, gets us a
|
Calling _xtos_unhandled_exception(ef, cause) in the Boot ROM, gets us a
|
||||||
hardware wdt.
|
hardware wdt.
|
||||||
|
|
||||||
Use panic instead as a fall back. It will produce a stack trace.
|
Use panic instead as a fall back. It will produce a stack trace.
|
||||||
*/
|
*/
|
||||||
|
#if defined(DEBUG_ESP_PORT) || defined(DEBUG_ESP_MMU)
|
||||||
panic();
|
panic();
|
||||||
|
#else
|
||||||
|
// For non-debug builds, save on resources
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif // #if defined(NON32XFER_HANDLER) || (defined(MMU_IRAM_HEAP) && (NONOSDK < (0x30000 - 1)))
|
||||||
|
|
||||||
|
#if (defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP)) && (NONOSDK < (0x30000 - 1))
|
||||||
/*
|
/*
|
||||||
To operate reliably, this module requires the new
|
To operate reliably, this module requires the new
|
||||||
`_xtos_set_exception_handler` from `exc-sethandler.cpp` and
|
`_xtos_set_exception_handler` from `exc-sethandler.cpp` and
|
||||||
@ -174,5 +189,17 @@ void install_non32xfer_exception_handler(void) {
|
|||||||
non32xfer_exception_handler);
|
non32xfer_exception_handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
// For v3.0.x SDKs, no need for install - call_user_start will do the job.
|
||||||
|
// Need this for build dependencies
|
||||||
|
void install_non32xfer_exception_handler(void) __attribute__((weak));
|
||||||
|
void install_non32xfer_exception_handler(void) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(NON32XFER_HANDLER)
|
||||||
|
// For SDKs 3.0.x, we made load_non_32_wide_handler in
|
||||||
|
// libmain.c:user_exceptions.o a weak symbol allowing this override to work.
|
||||||
|
extern void load_non_32_wide_handler(struct __exception_frame *ef, int cause) __attribute__((alias("non32xfer_exception_handler")));
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -39,8 +39,10 @@
|
|||||||
* architecture, I am not convinced it can be done safely.
|
* architecture, I am not convinced it can be done safely.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
#include <user_interface.h> // need NONOSDK
|
||||||
|
|
||||||
#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP) || defined(NEW_EXC_C_WRAPPER) || defined(MMU_EXTERNAL_HEAP)
|
#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP) || \
|
||||||
|
defined(NEW_EXC_C_WRAPPER) || defined(MMU_EXTERNAL_HEAP) || (NONOSDK >= (0x30000 - 1))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The original module source code came from:
|
* The original module source code came from:
|
||||||
|
@ -356,25 +356,25 @@ void system_show_malloc(void)
|
|||||||
void* IRAM_ATTR pvPortMalloc(size_t size, const char* file, int line)
|
void* IRAM_ATTR pvPortMalloc(size_t size, const char* file, int line)
|
||||||
{
|
{
|
||||||
HeapSelectDram ephemeral;
|
HeapSelectDram ephemeral;
|
||||||
return heap_pvPortMalloc(size, file, line);;
|
return heap_pvPortMalloc(size, file, line);;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* IRAM_ATTR pvPortCalloc(size_t count, size_t size, const char* file, int line)
|
void* IRAM_ATTR pvPortCalloc(size_t count, size_t size, const char* file, int line)
|
||||||
{
|
{
|
||||||
HeapSelectDram ephemeral;
|
HeapSelectDram ephemeral;
|
||||||
return heap_pvPortCalloc(count, size, file, line);
|
return heap_pvPortCalloc(count, size, file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* IRAM_ATTR pvPortRealloc(void *ptr, size_t size, const char* file, int line)
|
void* IRAM_ATTR pvPortRealloc(void *ptr, size_t size, const char* file, int line)
|
||||||
{
|
{
|
||||||
HeapSelectDram ephemeral;
|
HeapSelectDram ephemeral;
|
||||||
return heap_pvPortRealloc(ptr, size, file, line);
|
return heap_pvPortRealloc(ptr, size, file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* IRAM_ATTR pvPortZalloc(size_t size, const char* file, int line)
|
void* IRAM_ATTR pvPortZalloc(size_t size, const char* file, int line)
|
||||||
{
|
{
|
||||||
HeapSelectDram ephemeral;
|
HeapSelectDram ephemeral;
|
||||||
return heap_pvPortZalloc(size, file, line);
|
return heap_pvPortZalloc(size, file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR vPortFree(void *ptr, const char* file, int line)
|
void IRAM_ATTR vPortFree(void *ptr, const char* file, int line)
|
||||||
@ -384,7 +384,62 @@ void IRAM_ATTR vPortFree(void *ptr, const char* file, int line)
|
|||||||
// correct context. umm_malloc free internally determines the correct heap.
|
// correct context. umm_malloc free internally determines the correct heap.
|
||||||
HeapSelectDram ephemeral;
|
HeapSelectDram ephemeral;
|
||||||
#endif
|
#endif
|
||||||
return heap_vPortFree(ptr, file, line);
|
return heap_vPortFree(ptr, file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (NONOSDK >= (0x30000))
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/*
|
||||||
|
New for NON-OS SDK 3.0.0 and up
|
||||||
|
Needed for WPA2 Enterprise support. This was not present in SDK pre 3.0
|
||||||
|
|
||||||
|
The NON-OS SDK 3.0.x has breaking changes to pvPortMalloc. They added one more
|
||||||
|
argument for selecting a heap. To avoid breaking the build, I renamed their
|
||||||
|
broken version pvEsprMalloc. To be used, the LIBS need to be edited.
|
||||||
|
|
||||||
|
They also added pvPortZallocIram and pvPortCallocIram, which are not a
|
||||||
|
problem.
|
||||||
|
|
||||||
|
WPA2 Enterprise connect crashing is fixed at v3.0.2 and up.
|
||||||
|
|
||||||
|
Not used for unreleased version NONOSDK3V0.
|
||||||
|
*/
|
||||||
|
void* IRAM_ATTR sdk3_pvPortMalloc(size_t size, const char* file, int line, bool iram)
|
||||||
|
{
|
||||||
|
if (iram) {
|
||||||
|
HeapSelectIram ephemeral;
|
||||||
|
return heap_pvPortMalloc(size, file, line);
|
||||||
|
} else {
|
||||||
|
HeapSelectDram ephemeral;
|
||||||
|
return heap_pvPortMalloc(size, file, line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* IRAM_ATTR pvPortCallocIram(size_t count, size_t size, const char* file, int line)
|
||||||
|
{
|
||||||
|
HeapSelectIram ephemeral;
|
||||||
|
return heap_pvPortCalloc(count, size, file, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* IRAM_ATTR pvPortZallocIram(size_t size, const char* file, int line)
|
||||||
|
{
|
||||||
|
HeapSelectIram ephemeral;
|
||||||
|
return heap_pvPortZalloc(size, file, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
uint32_t IRAM_ATTR user_iram_memory_is_enabled(void)
|
||||||
|
{
|
||||||
|
return CONFIG_ENABLE_IRAM_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
We do not need the function user_iram_memory_is_enabled().
|
||||||
|
1. It was used by mem_manager.o which was replaced with this custom heap
|
||||||
|
implementation. IRAM memory selection is handled differently.
|
||||||
|
2. In libmain.a, Cache_Read_Enable_New uses it for cache size. However, When
|
||||||
|
using IRAM for memory or running with 48K IRAM for code, we use a
|
||||||
|
replacement Cache_Read_Enable to correct the cache size ignoring
|
||||||
|
Cache_Read_Enable_New's selected value.
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
@ -5,12 +5,44 @@
|
|||||||
* modules.
|
* modules.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ets_sys.h>
|
#include <ets_sys.h>
|
||||||
#include <pgmspace.h>
|
#include <pgmspace.h>
|
||||||
#include "coredecls.h"
|
#include "coredecls.h"
|
||||||
|
|
||||||
|
#if defined(NONOSDK22x_190703) || \
|
||||||
|
defined(NONOSDK22x_191122) || \
|
||||||
|
defined(NONOSDK22x_191105) || \
|
||||||
|
defined(NONOSDK22x_191124) || \
|
||||||
|
defined(NONOSDK22x_190313) || \
|
||||||
|
defined(NONOSDK221) || \
|
||||||
|
defined(NONOSDK3V0) || \
|
||||||
|
defined(NONOSDK300) || \
|
||||||
|
defined(NONOSDK301) || \
|
||||||
|
defined(NONOSDK302) || \
|
||||||
|
defined(NONOSDK303) || \
|
||||||
|
defined(NONOSDK304) || \
|
||||||
|
defined(NONOSDK305)
|
||||||
|
|
||||||
|
// eap_peer_config_deinit() - For this list of SDKs there are no significant
|
||||||
|
// changes in the function. Just the line number reference for when vPortFree
|
||||||
|
// is called. When vPortFree is called, register a12 continues to hold a pointer
|
||||||
|
// to the struct StateMachine. Our cleanup routine should continue to work.
|
||||||
|
#if defined(NONOSDK300) || defined(NONOSDK301)
|
||||||
|
// Minor changes only line number changed
|
||||||
|
#define SDK_LEAK_LINE 809
|
||||||
|
#elif defined(NONOSDK302) || defined(NONOSDK303) || defined(NONOSDK304)
|
||||||
|
// Minor changes only line number changed
|
||||||
|
#define SDK_LEAK_LINE 831
|
||||||
|
#elif defined(NONOSDK305)
|
||||||
|
// At v3.0.5 Espressif moved `.text.eap_peer_config_deinit` to
|
||||||
|
// `eap_peer_config_deinit` then later in latest git they moved it
|
||||||
|
// back. For our linker script both are placed in flash.
|
||||||
|
#define SDK_LEAK_LINE 831
|
||||||
|
#else
|
||||||
|
#define SDK_LEAK_LINE 799
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_WPA2_EAP_PATCH
|
#ifdef DEBUG_WPA2_EAP_PATCH
|
||||||
#include "esp8266_undocumented.h"
|
#include "esp8266_undocumented.h"
|
||||||
#define DEBUG_PRINTF ets_uart_printf
|
#define DEBUG_PRINTF ets_uart_printf
|
||||||
@ -100,7 +132,7 @@ struct StateMachine { // size 200 bytes
|
|||||||
* same line.
|
* same line.
|
||||||
*/
|
*/
|
||||||
void patch_wpa2_eap_vPortFree_a12(void *ptr, const char* file, int line, void* a12) {
|
void patch_wpa2_eap_vPortFree_a12(void *ptr, const char* file, int line, void* a12) {
|
||||||
if (799 == line) {
|
if (SDK_LEAK_LINE == line) {
|
||||||
// This caller is eap_peer_config_deinit()
|
// This caller is eap_peer_config_deinit()
|
||||||
struct StateMachine* sm = (struct StateMachine*)a12;
|
struct StateMachine* sm = (struct StateMachine*)a12;
|
||||||
if (ptr == sm->config[0]) {
|
if (ptr == sm->config[0]) {
|
||||||
@ -126,21 +158,38 @@ void patch_wpa2_eap_vPortFree_a12(void *ptr, const char* file, int line, void* a
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
// This is not needed because the call was NO-OPed in the library. This code
|
#if defined(NONOSDK300) || defined(NONOSDK301)
|
||||||
// snippit is just to show how a future memory free issue might be resolved.
|
else if (682 == line) {
|
||||||
else if (672 == line) {
|
|
||||||
// This caller is wpa2_sm_rx_eapol()
|
// This caller is wpa2_sm_rx_eapol()
|
||||||
// 1st of a double free
|
// 1st of a double free
|
||||||
// let the 2nd free handle it.
|
// let the 2nd free handle it.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#elif defined(NONOSDK302) || defined(NONOSDK303) || defined(NONOSDK304) || defined(NONOSDK305)
|
||||||
|
// It looks like double free is fixed. WPA2 Enterpise connections work
|
||||||
|
// without crashing. wpa2_sm_rx_eapol() has a few changes between NONOSDK301
|
||||||
|
// and NONOSDK302. However, this set of releases still have memory leaks.
|
||||||
|
#else
|
||||||
|
// This is not needed because the call was NO-OPed in the library.
|
||||||
|
// Keep code snippit for reference.
|
||||||
|
// else if (672 == line) {
|
||||||
|
// // This caller is wpa2_sm_rx_eapol()
|
||||||
|
// // 1st of a double free
|
||||||
|
// // let the 2nd free handle it.
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
#endif
|
#endif
|
||||||
vPortFree(ptr, file, line);
|
vPortFree(ptr, file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error "Internal error: A new SDK has been added. This module must be updated."
|
||||||
|
#error " Need to test WPA2 Enterpise connectivity."
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This will minimize code space for non-wifi enterprise sketches which do not
|
* This will minimize code space for non-wifi enterprise sketches which do not
|
||||||
* need the patch and disable_extra4k_at_link_time().
|
* need the patch and disable_extra4k_at_link_time().
|
||||||
|
113
doc/mmu.rst
113
doc/mmu.rst
@ -76,19 +76,28 @@ The Arduino IDE Tools menu option, ``MMU`` has the following selections:
|
|||||||
MMU related build defines and possible values. These values change as
|
MMU related build defines and possible values. These values change as
|
||||||
indicated with the menu options above:
|
indicated with the menu options above:
|
||||||
|
|
||||||
+-------------------------+--------------+--------------+------------------------------------+------------------------------+
|
+-------------+------------+------------+-------------+-------------+
|
||||||
| ``#define`` | balanced | IRAM | shared (IRAM and Heap) | not shared (IRAM and Heap) |
|
| ``#define`` | balanced | IRAM | shared | not shared |
|
||||||
+=========================+==============+==============+====================================+==============================+
|
| | | | (IRAM and | (IRAM and |
|
||||||
| ``MMU_IRAM_SIZE`` | ``0x8000`` | ``0xC000`` | ``0xC000`` | ``0x8000`` |
|
| | | | Heap) | Heap) |
|
||||||
+-------------------------+--------------+--------------+------------------------------------+------------------------------+
|
+=============+============+============+=============+=============+
|
||||||
| ``MMU_ICACHE_SIZE`` | ``0x8000`` | ``0x4000`` | ``0x4000`` | ``0x4000`` |
|
| ``MMU_ | ``0x8000`` | ``0xC000`` | ``0xC000`` | ``0x8000`` |
|
||||||
+-------------------------+--------------+--------------+------------------------------------+------------------------------+
|
| IRAM_SIZE`` | | | | |
|
||||||
| ``MMU_IRAM_HEAP`` | -- | -- | defined, enables\ ``umm_malloc`` | -- |
|
+-------------+------------+------------+-------------+-------------+
|
||||||
+-------------------------+--------------+--------------+------------------------------------+------------------------------+
|
| ``MMU_IC | ``0x8000`` | ``0x4000`` | ``0x4000`` | ``0x4000`` |
|
||||||
| ``MMU_SEC_HEAP`` | -- | \*\* | \*\* | ``0x40108000`` |
|
| ACHE_SIZE`` | | | | |
|
||||||
+-------------------------+--------------+--------------+------------------------------------+------------------------------+
|
+-------------+------------+------------+-------------+-------------+
|
||||||
| ``MMU_SEC_HEAP_SIZE`` | -- | \*\* | \*\* | ``0x4000`` |
|
| ``MMU_ | – | – | defined, | – |
|
||||||
+-------------------------+--------------+--------------+------------------------------------+------------------------------+
|
| IRAM_HEAP`` | | | e | |
|
||||||
|
| | | | nables\ ``u | |
|
||||||
|
| | | | mm_malloc`` | |
|
||||||
|
+-------------+------------+------------+-------------+-------------+
|
||||||
|
| ``MMU | – | \*\* | \*\* | ``0 |
|
||||||
|
| _SEC_HEAP`` | | | | x40108000`` |
|
||||||
|
+-------------+------------+------------+-------------+-------------+
|
||||||
|
| ``MMU_SEC_ | – | \*\* | \*\* | ``0x4000`` |
|
||||||
|
| HEAP_SIZE`` | | | | |
|
||||||
|
+-------------+------------+------------+-------------+-------------+
|
||||||
|
|
||||||
\*\* This define is to an inline function that calculates the value,
|
\*\* This define is to an inline function that calculates the value,
|
||||||
based on unused code space, requires ``#include <mmu_iram.h>``.
|
based on unused code space, requires ``#include <mmu_iram.h>``.
|
||||||
@ -112,8 +121,8 @@ The Arduino IDE Tools menu option, ``Non-32-Bit Access`` has the following selec
|
|||||||
option ``16KB cache + 48KB IRAM and 2nd Heap (shared)``.
|
option ``16KB cache + 48KB IRAM and 2nd Heap (shared)``.
|
||||||
|
|
||||||
IRAM, unlike DRAM, must be accessed as aligned full 32-bit words, no
|
IRAM, unlike DRAM, must be accessed as aligned full 32-bit words, no
|
||||||
byte or short access. The pgm\_read macros are an option; however, the
|
byte or short access. The pgm_read macros are an option; however, the
|
||||||
store operation remains an issue. For a block copy, ets\_memcpy appears
|
store operation remains an issue. For a block copy, ets_memcpy appears
|
||||||
to work well as long as the byte count is rounded up to be evenly
|
to work well as long as the byte count is rounded up to be evenly
|
||||||
divided by 4, and source and destination addresses are 4 bytes aligned.
|
divided by 4, and source and destination addresses are 4 bytes aligned.
|
||||||
|
|
||||||
@ -125,6 +134,11 @@ over-optimization.
|
|||||||
To get a sense of how memory access time is effected, see examples
|
To get a sense of how memory access time is effected, see examples
|
||||||
``MMU48K`` and ``irammem`` in ``ESP8266``.
|
``MMU48K`` and ``irammem`` in ``ESP8266``.
|
||||||
|
|
||||||
|
NON-OS SDK v3.0.0 and above have builtin support for Non-32-Bit Access.
|
||||||
|
Selecting ``Byte/Word access to IRAM/PROGMEM`` will override the builtin
|
||||||
|
version with ours. However, there is no known reason to do this other
|
||||||
|
than debugging.
|
||||||
|
|
||||||
Miscellaneous
|
Miscellaneous
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@ -133,41 +147,43 @@ For calls to ``umm_malloc`` with interrupts disabled.
|
|||||||
|
|
||||||
- ``malloc`` will always allocate from the ``DRAM`` heap when called
|
- ``malloc`` will always allocate from the ``DRAM`` heap when called
|
||||||
with interrupts disabled.
|
with interrupts disabled.
|
||||||
- ``realloc`` with a NULL pointer will use ``malloc`` and return a
|
|
||||||
``DRAM`` heap allocation. Note, calling ``realloc`` with interrupts
|
- ``realloc`` with a NULL pointer will use ``malloc`` and return a
|
||||||
disabled is **not** officially supported. You are on your own if you
|
``DRAM`` heap allocation. Note, calling ``realloc`` with
|
||||||
do this.
|
interrupts disabled is **not** officially supported. You are on
|
||||||
|
your own if you do this.
|
||||||
|
|
||||||
- If you must use IRAM memory in your ISR, allocate the memory in your
|
- If you must use IRAM memory in your ISR, allocate the memory in your
|
||||||
init code. To reduce the time spent in the ISR, avoid non32-bit
|
init code. To reduce the time spent in the ISR, avoid non32-bit
|
||||||
access that would trigger the exception handler. For short or byte
|
access that would trigger the exception handler. For short or byte
|
||||||
access, consider using the inline functions described in section
|
access, consider using the inline functions described in section
|
||||||
"Performance Functions" below.
|
“Performance Functions” below.
|
||||||
|
|
||||||
How to Select Heap
|
How to Select Heap
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The ``MMU`` selection ``16KB cache + 48KB IRAM and 2nd Heap (shared)``
|
The ``MMU`` selection ``16KB cache + 48KB IRAM and 2nd Heap (shared)``
|
||||||
allows you to use the standard heap API function calls (``malloc``,
|
allows you to use the standard heap API function calls (``malloc``,
|
||||||
``calloc``, ``free``, ... ). to allocate memory from DRAM or IRAM. This
|
``calloc``, ``free``, … ). to allocate memory from DRAM or IRAM. This
|
||||||
selection can be made by instantiating the class ``HeapSelectIram`` or
|
selection can be made by instantiating the class ``HeapSelectIram`` or
|
||||||
``HeapSelectDram``. The usage is similar to that of the
|
``HeapSelectDram``. The usage is similar to that of the
|
||||||
``InterruptLock`` class. The default/initial heap source is DRAM. The
|
``InterruptLock`` class. The default/initial heap source is DRAM. The
|
||||||
class is in ``umm_malloc/umm_heap_select.h``.
|
class is in ``umm_malloc/umm_heap_select.h``.
|
||||||
|
|
||||||
::
|
.. code:: cpp
|
||||||
|
|
||||||
...
|
...
|
||||||
char *bufferDram;
|
char *bufferDram;
|
||||||
bufferDram = (char *)malloc(33);
|
bufferDram = (char *)malloc(33);
|
||||||
char *bufferIram;
|
char *bufferIram;
|
||||||
{
|
{
|
||||||
HeapSelectIram ephemeral;
|
HeapSelectIram ephemeral;
|
||||||
bufferIram = (char *)malloc(33);
|
bufferIram = (char *)malloc(33);
|
||||||
}
|
}
|
||||||
...
|
...
|
||||||
free(bufferIram);
|
free(bufferIram);
|
||||||
free(bufferDram);
|
free(bufferDram);
|
||||||
...
|
...
|
||||||
|
|
||||||
``free`` will always return memory to the correct heap. There is no need
|
``free`` will always return memory to the correct heap. There is no need
|
||||||
for tracking and selecting before freeing.
|
for tracking and selecting before freeing.
|
||||||
@ -182,8 +198,9 @@ Classes:
|
|||||||
- ``umm_get_current_heap_id()``
|
- ``umm_get_current_heap_id()``
|
||||||
- ``umm_set_heap_by_id( ID value )``
|
- ``umm_set_heap_by_id( ID value )``
|
||||||
- Possible ID values
|
- Possible ID values
|
||||||
- ``UMM_HEAP_DRAM``
|
|
||||||
- ``UMM_HEAP_IRAM``
|
- ``UMM_HEAP_DRAM``
|
||||||
|
- ``UMM_HEAP_IRAM``
|
||||||
|
|
||||||
Also, an alternate stack select method API is available. This is not as
|
Also, an alternate stack select method API is available. This is not as
|
||||||
easy as the class method; however, for some small set of cases, it may
|
easy as the class method; however, for some small set of cases, it may
|
||||||
@ -201,9 +218,9 @@ a pointer:
|
|||||||
|
|
||||||
.. code:: cpp
|
.. code:: cpp
|
||||||
|
|
||||||
bool mmu_is_iram(const void *addr);
|
bool mmu_is_iram(const void *addr);
|
||||||
bool mmu_is_dram(const void *addr);
|
bool mmu_is_dram(const void *addr);
|
||||||
bool mmu_is_icache(const void *addr);
|
bool mmu_is_icache(const void *addr);
|
||||||
|
|
||||||
Performance Functions
|
Performance Functions
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -213,23 +230,25 @@ exception handler reducing execution time and stack use, it comes at the
|
|||||||
cost of increased code size.
|
cost of increased code size.
|
||||||
|
|
||||||
These are an alternative to the ``pgm_read`` macros for reading from
|
These are an alternative to the ``pgm_read`` macros for reading from
|
||||||
IRAM. When compiled with 'Debug Level: core' range checks are performed
|
IRAM. When compiled with ‘Debug Level: core’ range checks are performed
|
||||||
on the pointer value to make sure you are reading from the address range
|
on the pointer value to make sure you are reading from the address range
|
||||||
of IRAM, DRAM, or ICACHE.
|
of IRAM, DRAM, or ICACHE.
|
||||||
|
|
||||||
.. code:: cpp
|
.. code:: cpp
|
||||||
|
|
||||||
uint8_t mmu_get_uint8(const void *p8);
|
uint8_t mmu_get_uint8(const void *p8);
|
||||||
uint16_t mmu_get_uint16(const uint16_t *p16);
|
uint16_t mmu_get_uint16(const uint16_t *p16);
|
||||||
int16_t mmu_get_int16(const int16_t *p16);
|
int16_t mmu_get_int16(const int16_t *p16);
|
||||||
|
|
||||||
While these functions are intended for writing to IRAM, they will work
|
While these functions are intended for writing to IRAM, they will work
|
||||||
with DRAM. When compiled with 'Debug Level: core', range checks are
|
with DRAM. When compiled with ‘Debug Level: core’, range checks are
|
||||||
performed on the pointer value to make sure you are writing to the
|
performed on the pointer value to make sure you are writing to the
|
||||||
address range of IRAM or DRAM.
|
address range of IRAM or DRAM.
|
||||||
|
|
||||||
.. code:: cpp
|
.. code:: cpp
|
||||||
|
|
||||||
uint8_t mmu_set_uint8(void *p8, const uint8_t val);
|
uint8_t mmu_set_uint8(void *p8, const uint8_t val);
|
||||||
uint16_t mmu_set_uint16(uint16_t *p16, const uint16_t val);
|
uint16_t mmu_set_uint16(uint16_t *p16, const uint16_t val);
|
||||||
int16_t mmu_set_int16(int16_t *p16, const int16_t val);
|
int16_t mmu_set_int16(int16_t *p16, const int16_t val);
|
||||||
|
|
||||||
|
::
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,8 +1,20 @@
|
|||||||
|
## Adding a new SDK library
|
||||||
|
|
||||||
|
- Create a directory for the new SDK.
|
||||||
|
- Copy .a files from SDK `lib` directory to the new directory
|
||||||
|
- Add the new SDK directory to those supported in `eval_fix_sdks.sh` and `fix_sdk_libs.sh`.
|
||||||
|
- To support WPA2 Enterprise connections, some patches are reguired review `wpa2_eap_patch.cpp` and `eval_fix_sdks.sh` for details.
|
||||||
|
- Use `./eval_fix_sdks.sh --analyze` to aid in finding relevant differences.
|
||||||
|
- Also, you can compare two SDKs with something like `./eval_fix_sdks.sh --analyze "NONOSDK305\nNONOSDK306"`
|
||||||
|
- Apply updates to `fix_sdk_libs.sh` and `wpa2_eap_patch.cpp`. You can run `./eval_fix_sdks.sh --patch` to do a batch run of `fix_sdk_libs.sh` against each SDK.
|
||||||
|
- If you used this section, you can skip _Updating SDK libraries_.
|
||||||
|
|
||||||
## Updating SDK libraries
|
## Updating SDK libraries
|
||||||
|
|
||||||
- Copy .a files from SDK `lib` directory to this directory
|
- Copy .a files from SDK `lib` directory to this directory
|
||||||
- Run `fix_sdk_libs.sh`
|
- Run `fix_sdk_libs.sh`
|
||||||
|
|
||||||
|
|
||||||
## Updating libstdc++
|
## Updating libstdc++
|
||||||
|
|
||||||
After building gcc using crosstool-NG, get compiled libstdc++ and remove some objects:
|
After building gcc using crosstool-NG, get compiled libstdc++ and remove some objects:
|
||||||
@ -17,4 +29,3 @@ xtensa-lx106-elf-ar d libstdc++.a del_opv.o
|
|||||||
xtensa-lx106-elf-ar d libstdc++.a new_op.o
|
xtensa-lx106-elf-ar d libstdc++.a new_op.o
|
||||||
xtensa-lx106-elf-ar d libstdc++.a new_opv.o
|
xtensa-lx106-elf-ar d libstdc++.a new_opv.o
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# set -e
|
# set -e
|
||||||
|
|
||||||
|
single_sdk="${2}"
|
||||||
|
if [[ -n "$single_sdk" ]]; then
|
||||||
|
if [[ "NONOSDK" != "${single_sdk:0:7}" ]]; then
|
||||||
|
single_sdk=""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
add_path_ifexist() {
|
add_path_ifexist() {
|
||||||
if [[ -d $1 ]]; then
|
if [[ -d $1 ]]; then
|
||||||
export PATH=$( realpath $1 ):$PATH
|
export PATH=$( realpath $1 ):$PATH
|
||||||
@ -24,6 +31,10 @@ EOF
|
|||||||
}
|
}
|
||||||
|
|
||||||
list_sdks() {
|
list_sdks() {
|
||||||
|
if [[ -n "$single_sdk" ]]; then
|
||||||
|
echo -e "$single_sdk"
|
||||||
|
return
|
||||||
|
fi
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
NONOSDK22x_190313
|
NONOSDK22x_190313
|
||||||
NONOSDK22x_190703
|
NONOSDK22x_190703
|
||||||
@ -68,7 +79,7 @@ analyze() {
|
|||||||
done
|
done
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
find . -name eap.o -exec md5sum {} \; | sort
|
find . -name eap.o -exec md5sum {} \; | sort -k2
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
unset prev_sdk
|
unset prev_sdk
|
||||||
|
@ -42,6 +42,58 @@ patchFile() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grepPatchFiles() {
|
||||||
|
local SDKVER OLDNAME NEWNAME FILES OLDNAME64 NEWNAME64 FILE OFFSET PATTERN
|
||||||
|
SDKVER="${1}"
|
||||||
|
OLDNAME="${2}"
|
||||||
|
NEWNAME="${3}"
|
||||||
|
FILES="${4}"
|
||||||
|
[[ "${SDKVER:0:9}" != "NONOSDK30" ]] && return
|
||||||
|
if [[ -z "${FILES}" ]]; then
|
||||||
|
echo "grepPatchFile: bad input: file specification required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ "${#OLDNAME}" != "${#NEWNAME}" ]]; then
|
||||||
|
echo "grepPatchFile: bad input: old name ${OLDNAME}(${#OLDNAME}) and new name ${NEWNAME}(${#NEWNAME}) must be the same length."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
OLDNAME64=( `echo -n "${OLDNAME}" | base64 -w0` )
|
||||||
|
NEWNAME64=( `echo -n "${NEWNAME}" | base64 -w0` )
|
||||||
|
|
||||||
|
while read -u3 FILE OFFSET PATTERN; do
|
||||||
|
if [[ "${#OLDNAME}" == "${#PATTERN}" ]] && [[ "${OLDNAME}" == "${PATTERN}" ]]; then
|
||||||
|
patchFile "$FILE" "$OFFSET" "${#PATTERN}" "${OLDNAME64}" "${NEWNAME64}"
|
||||||
|
else
|
||||||
|
echo "grepPatchFile: bad parameters FILE=${FILE} OFFSET=${OFFSET} PATTERN=${PATTERN}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done 3< <( grep --with-filename --byte-offset --only-matching --text "${OLDNAME}" $FILES | tr ":" " " )
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
redefineSym() {
|
||||||
|
local SDKVER OLDNAME NEWNAME FILES FILE EXTRA PATTERN
|
||||||
|
SDKVER="${1}"
|
||||||
|
OLDNAME="${2}"
|
||||||
|
NEWNAME="${3}"
|
||||||
|
FILES="${4}"
|
||||||
|
[[ "${SDKVER:0:9}" != "NONOSDK30" ]] && return
|
||||||
|
if [[ -z "${FILES}" ]]; then
|
||||||
|
echo "redefineSym: bad input: file specification required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
PATTERN="UND ${OLDNAME}"
|
||||||
|
for FILE in $FILES ; do
|
||||||
|
echo "xtensa-lx106-elf-objcopy --redefine-sym ${OLDNAME}=${NEWNAME} \"$FILE\""
|
||||||
|
echo "Before:"
|
||||||
|
xtensa-lx106-elf-nm "$FILE" | grep ${OLDNAME} | sort -u
|
||||||
|
xtensa-lx106-elf-objcopy --redefine-sym ${OLDNAME}=${NEWNAME} "$FILE"
|
||||||
|
echo "After:"
|
||||||
|
xtensa-lx106-elf-nm "$FILE" | grep ${OLDNAME} | sort -u
|
||||||
|
done
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
# # xtensa-lx106-elf-ar x libwpa2.a eap.o
|
# # xtensa-lx106-elf-ar x libwpa2.a eap.o
|
||||||
if [[ "--shell" == "$1" ]]; then
|
if [[ "--shell" == "$1" ]]; then
|
||||||
# need to poke around a bit
|
# need to poke around a bit
|
||||||
@ -81,12 +133,28 @@ elif [[ ${VERSION} == "NONOSDK22x"* ]]; then
|
|||||||
addSymbol_system_func1 "0x54"
|
addSymbol_system_func1 "0x54"
|
||||||
patchFile "eap.o" "3059" "2" "wAA=" "8CA=" # WPA2-Enterprise patch which replaces a double-free with nop, see #8082
|
patchFile "eap.o" "3059" "2" "wAA=" "8CA=" # WPA2-Enterprise patch which replaces a double-free with nop, see #8082
|
||||||
patchFile "eap.o" "26356" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
|
patchFile "eap.o" "26356" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
|
||||||
elif [[ ${VERSION} == "NONOSDK3V0"* ]]; then
|
elif [[ ${VERSION} == "NONOSDK3V0" ]]; then
|
||||||
addSymbol_system_func1 "0x60"
|
addSymbol_system_func1 "0x60"
|
||||||
patchFile "eap.o" "3059" "2" "wAA=" "8CA=" # WPA2-Enterprise patch which replaces a double-free with nop, see #8082
|
patchFile "eap.o" "3059" "2" "wAA=" "8CA=" # WPA2-Enterprise patch which replaces a double-free with nop, see #8082
|
||||||
patchFile "eap.o" "26356" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
|
patchFile "eap.o" "26356" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
|
||||||
elif [[ ${VERSION} == "NONOSDK3"* ]]; then
|
elif [[ ${VERSION} == "NONOSDK300" ]]; then
|
||||||
addSymbol_system_func1 "0x54"
|
addSymbol_system_func1 "0x54"
|
||||||
|
patchFile "eap.o" "19204" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
|
||||||
|
elif [[ ${VERSION} == "NONOSDK301" ]]; then
|
||||||
|
addSymbol_system_func1 "0x54"
|
||||||
|
patchFile "eap.o" "26364" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
|
||||||
|
elif [[ ${VERSION} == "NONOSDK302" ]]; then
|
||||||
|
addSymbol_system_func1 "0x54"
|
||||||
|
patchFile "eap.o" "26536" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
|
||||||
|
elif [[ ${VERSION} == "NONOSDK303" ]]; then
|
||||||
|
addSymbol_system_func1 "0x54"
|
||||||
|
patchFile "eap.o" "26536" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
|
||||||
|
elif [[ ${VERSION} == "NONOSDK304" ]]; then
|
||||||
|
addSymbol_system_func1 "0x54"
|
||||||
|
patchFile "eap.o" "19376" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
|
||||||
|
elif [[ ${VERSION} == "NONOSDK305" ]]; then
|
||||||
|
addSymbol_system_func1 "0x54"
|
||||||
|
patchFile "eap.o" "67670" "9" "dlBvcnRGcmVl" "ejJFYXBGcmVl" # special vPortFree to recover leaked memory
|
||||||
else
|
else
|
||||||
echo "WARN: Unknown address for system_func1() called by system_restart_local()"
|
echo "WARN: Unknown address for system_func1() called by system_restart_local()"
|
||||||
fi
|
fi
|
||||||
@ -98,3 +166,12 @@ if [[ $(sha256sum user_interface.o | awk '{print $1}') != $uics || $(sha256sum e
|
|||||||
xtensa-lx106-elf-ar r libmain.a eagle_lwip_if.o user_interface.o
|
xtensa-lx106-elf-ar r libmain.a eagle_lwip_if.o user_interface.o
|
||||||
fi
|
fi
|
||||||
rm -f eagle_lwip_if.o user_interface.o eap.o
|
rm -f eagle_lwip_if.o user_interface.o eap.o
|
||||||
|
|
||||||
|
if [[ ${VERSION} == "NONOSDK3V0" ]]; then
|
||||||
|
xtensa-lx106-elf-objcopy --weaken-symbol load_non_32_wide_handler libmain.a
|
||||||
|
elif [[ ${VERSION:0:9} == "NONOSDK30" ]]; then
|
||||||
|
# v3.0.0 and up use a non-standard pvPortMalloc.
|
||||||
|
# SDK Library global replace
|
||||||
|
redefineSym "${VERSION}" "pvPortMalloc" "sdk3_pvPortMalloc" '*.a'
|
||||||
|
xtensa-lx106-elf-objcopy --weaken-symbol load_non_32_wide_handler libmain.a
|
||||||
|
fi
|
||||||
|
Loading…
x
Reference in New Issue
Block a user