Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Heap addendum to handle changes in NON-OS SDK 3.0.x #8746

Merged
merged 10 commits into from
Dec 16, 2022
2 changes: 1 addition & 1 deletion cores/esp8266/core_esp8266_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ extern "C" void user_init(void) {
install_vm_exception_handler();
#endif

#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP)
#if defined(NON32XFER_HANDLER) || (defined(MMU_IRAM_HEAP) && (NONOSDK < (0x30000 - 1)))
install_non32xfer_exception_handler();
#endif

Expand Down
31 changes: 29 additions & 2 deletions cores/esp8266/core_esp8266_non32xfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@
* Code taken directly from @pvvx's public domain code in
* 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 <user_interface.h>
#define VERIFY_C_ASM_EXCEPTION_FRAME_STRUCTURE
#include <esp8266_undocumented.h>
#include <core_esp8266_non32xfer.h>
Expand Down Expand Up @@ -58,10 +62,13 @@ extern "C" {

#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;
#endif

#if defined(NON32XFER_HANDLER) || (defined(MMU_IRAM_HEAP) && (NONOSDK < (0x30000 - 1)))
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 {
uint32_t insn, excvaddr;
Expand Down Expand Up @@ -138,6 +145,7 @@ IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef, int cau
} while(false);

/* Fail request, die */
#if (NONOSDK < (0x30000 - 1))
/*
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
Expand All @@ -148,16 +156,23 @@ IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef, int cau
old_c_handler(ef, cause);
return;
}

#endif
/*
Calling _xtos_unhandled_exception(ef, cause) in the Boot ROM, gets us a
hardware wdt.

Use panic instead as a fall back. It will produce a stack trace.
*/
#if defined(DEBUG_ESP_PORT) || defined(DEBUG_ESP_MMU)
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
`_xtos_set_exception_handler` from `exc-sethandler.cpp` and
Expand All @@ -174,5 +189,17 @@ void install_non32xfer_exception_handler(void) {
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

};
4 changes: 3 additions & 1 deletion cores/esp8266/exc-sethandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@
* 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:
Expand Down
65 changes: 60 additions & 5 deletions cores/esp8266/heap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,25 +356,25 @@ void system_show_malloc(void)
void* IRAM_ATTR pvPortMalloc(size_t size, const char* file, int line)
{
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)
{
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)
{
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)
{
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)
Expand All @@ -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.
HeapSelectDram ephemeral;
#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.

mhightower83 marked this conversation as resolved.
Show resolved Hide resolved
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);;
mcspr marked this conversation as resolved.
Show resolved Hide resolved
} else {
HeapSelectDram ephemeral;
return heap_pvPortMalloc(size, file, line);;
mcspr marked this conversation as resolved.
Show resolved Hide resolved
}
}

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
};
61 changes: 55 additions & 6 deletions cores/esp8266/wpa2_eap_patch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,44 @@
* modules.
*
*/

#include <string.h>
#include <ets_sys.h>
#include <pgmspace.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
#include "esp8266_undocumented.h"
#define DEBUG_PRINTF ets_uart_printf
Expand Down Expand Up @@ -100,7 +132,7 @@ struct StateMachine { // size 200 bytes
* same line.
*/
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()
struct StateMachine* sm = (struct StateMachine*)a12;
if (ptr == sm->config[0]) {
Expand All @@ -126,21 +158,38 @@ void patch_wpa2_eap_vPortFree_a12(void *ptr, const char* file, int line, void* a
}
#endif
}
#if 0
// This is not needed because the call was NO-OPed in the library. This code
// snippit is just to show how a future memory free issue might be resolved.
else if (672 == line) {

#if defined(NONOSDK300) || defined(NONOSDK301)
else if (682 == line) {
// This caller is wpa2_sm_rx_eapol()
// 1st of a double free
// let the 2nd free handle it.
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
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
* need the patch and disable_extra4k_at_link_time().
Expand Down
Loading