1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-27 18:02:17 +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:
M Hightower
2022-12-16 00:11:19 -08:00
committed by GitHub
parent d3c8d272d7
commit 4a0b66b017
76 changed files with 317 additions and 66 deletions

View File

@ -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
indicated with the menu options above:
+-------------------------+--------------+--------------+------------------------------------+------------------------------+
| ``#define`` | balanced | IRAM | shared (IRAM and Heap) | not shared (IRAM and Heap) |
+=========================+==============+==============+====================================+==============================+
| ``MMU_IRAM_SIZE`` | ``0x8000`` | ``0xC000`` | ``0xC000`` | ``0x8000`` |
+-------------------------+--------------+--------------+------------------------------------+------------------------------+
| ``MMU_ICACHE_SIZE`` | ``0x8000`` | ``0x4000`` | ``0x4000`` | ``0x4000`` |
+-------------------------+--------------+--------------+------------------------------------+------------------------------+
| ``MMU_IRAM_HEAP`` | -- | -- | defined, enables\ ``umm_malloc`` | -- |
+-------------------------+--------------+--------------+------------------------------------+------------------------------+
| ``MMU_SEC_HEAP`` | -- | \*\* | \*\* | ``0x40108000`` |
+-------------------------+--------------+--------------+------------------------------------+------------------------------+
| ``MMU_SEC_HEAP_SIZE`` | -- | \*\* | \*\* | ``0x4000`` |
+-------------------------+--------------+--------------+------------------------------------+------------------------------+
+-------------+------------+------------+-------------+-------------+
| ``#define`` | balanced | IRAM | shared | not shared |
| | | | (IRAM and | (IRAM and |
| | | | Heap) | Heap) |
+=============+============+============+=============+=============+
| ``MMU_ | ``0x8000`` | ``0xC000`` | ``0xC000`` | ``0x8000`` |
| IRAM_SIZE`` | | | | |
+-------------+------------+------------+-------------+-------------+
| ``MMU_IC | ``0x8000`` | ``0x4000`` | ``0x4000`` | ``0x4000`` |
| ACHE_SIZE`` | | | | |
+-------------+------------+------------+-------------+-------------+
| ``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,
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)``.
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
store operation remains an issue. For a block copy, ets\_memcpy appears
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
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.
@ -125,6 +134,11 @@ over-optimization.
To get a sense of how memory access time is effected, see examples
``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
-------------
@ -133,41 +147,43 @@ For calls to ``umm_malloc`` with interrupts disabled.
- ``malloc`` will always allocate from the ``DRAM`` heap when called
with interrupts disabled.
- ``realloc`` with a NULL pointer will use ``malloc`` and return a
``DRAM`` heap allocation. Note, calling ``realloc`` with interrupts
disabled is **not** officially supported. You are on your own if you
do this.
- ``realloc`` with a NULL pointer will use ``malloc`` and return a
``DRAM`` heap allocation. Note, calling ``realloc`` with
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
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, consider using the inline functions described in section
"Performance Functions" below.
Performance Functions below.
How to Select Heap
~~~~~~~~~~~~~~~~~~
The ``MMU`` selection ``16KB cache + 48KB IRAM and 2nd Heap (shared)``
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
``HeapSelectDram``. The usage is similar to that of the
``InterruptLock`` class. The default/initial heap source is DRAM. The
class is in ``umm_malloc/umm_heap_select.h``.
::
.. code:: cpp
...
char *bufferDram;
bufferDram = (char *)malloc(33);
char *bufferIram;
{
HeapSelectIram ephemeral;
bufferIram = (char *)malloc(33);
}
...
free(bufferIram);
free(bufferDram);
...
...
char *bufferDram;
bufferDram = (char *)malloc(33);
char *bufferIram;
{
HeapSelectIram ephemeral;
bufferIram = (char *)malloc(33);
}
...
free(bufferIram);
free(bufferDram);
...
``free`` will always return memory to the correct heap. There is no need
for tracking and selecting before freeing.
@ -182,8 +198,9 @@ Classes:
- ``umm_get_current_heap_id()``
- ``umm_set_heap_by_id( ID value )``
- 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
easy as the class method; however, for some small set of cases, it may
@ -201,9 +218,9 @@ a pointer:
.. code:: cpp
bool mmu_is_iram(const void *addr);
bool mmu_is_dram(const void *addr);
bool mmu_is_icache(const void *addr);
bool mmu_is_iram(const void *addr);
bool mmu_is_dram(const void *addr);
bool mmu_is_icache(const void *addr);
Performance Functions
~~~~~~~~~~~~~~~~~~~~~
@ -213,23 +230,25 @@ exception handler reducing execution time and stack use, it comes at the
cost of increased code size.
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
of IRAM, DRAM, or ICACHE.
.. code:: cpp
uint8_t mmu_get_uint8(const void *p8);
uint16_t mmu_get_uint16(const uint16_t *p16);
int16_t mmu_get_int16(const int16_t *p16);
uint8_t mmu_get_uint8(const void *p8);
uint16_t mmu_get_uint16(const uint16_t *p16);
int16_t mmu_get_int16(const int16_t *p16);
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
address range of IRAM or DRAM.
.. code:: cpp
uint8_t mmu_set_uint8(void *p8, const uint8_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);
uint8_t mmu_set_uint8(void *p8, const uint8_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);
::