mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-03 07:02:28 +03:00
* PoC cache configuration control Expaned boards.txt.py to allow new MMU options and create revised .ld's Updated eboot to pass 48K IRAM segments. Added Cache_Read_Enable intercept to modify call for 16K ICACHE Update platform.txt to pass new mmu options through to compiler and linker preprocessor. Added quick example: esp8266/MMU48K * Style corrections Added MMU_ qualifier to new defines. Moved changes into their own file. Don't know how to fix platformio issue. * Added detailed description for Cache_Read_Enable. Updated tools/sizes.py to report correct IRAM size and indicate ICACHE size. Merged in earlephilhower's work on unaligned exception. Refactored and added support for store operations and changed the name to be more closely aligned with its function. Improved crash reporting path. * Style and MMU_SEC_HEAP corrections. * Improved asm register usage. Added some inline functions to aid in byte and short access to iRAM. * only byte read has been tested Updated .ld file to work better with platform.io; however, I am still missing some steps, so platformio will still fail. * Interesting glitch in boards.txt after github merge. A new board in master was missing new additions added by boards.txt.py in the PR. Which the CI flags when it rebuilds boards.txt. * Support for 2nd Heap, excess IRAM, through umm_malloc. Adapted changes to umm_malloc, Esp.cpp, StackThunk.cpp, WiFiClientSecureBearSSL.cpp, and virtualmem.ino to irammem.ino from @earlephilhower PR #6994. Reworked umm_malloc to use context pointers instead of copy context. umm_malloc now supports allocations from IRAM. Added class HeapSelectIram, ... to aid in selecting alternate heaps, modeled after class InterruptLock. Restrict alloc request from ISRs to DRAM. Never ending improvements to debug printing. Sec Heap option now pulls in free IRAM left over in the 1st 32K block. Managed through umm_malloc with HeapSelectIram. Updated examples. * Post push CI cleanup. * Cleanup part II * Cleanup part III * Updates to support platformio, maybe. * Added exception C wrapper replacement. * CI Cleanup * CI Cleanup II Don't know what to do with platformio it doesn't like my .S file. ifdef out USE_ISR_SAFE_EXC_WRAPPER to block the new assemlby module from building on platformio only. * Changes to exc-c-wrapper-handler.S to assemble under platformio. * For platformio, Correction to toolchain-xtensa include path. @mcspr, Thankyou! * Temporarily added --print-memory-usage to ld parameters for cross-checking IRAM size. * undo change to platform.txt * correct merge conflict. take 1 * Fixed #if... for building umm_get_oom_count. It was not building when UMM_STATS_FULL was used. * Commented out XMC support. Compatibility issues with PoC when using 16K ICACHE. * Corrected size.py, DRAM bracketing changed to not include ICACHE with DRAM total. * Added additional _context for support of use of UMM_INLINE_METRICS. Corrected some UMM_POSION missed edits. * Changes to clear errors and warnings from toolchain 10.1 Several fixes and improvements to example MMU48K. With the improved optimization in toolchain 10.1 The example divide by 0 exception was failing with a HWDT event instead of its exception handler. The compiler saw the obscured divide by 0 and replaced it with a break point. * Isolated incompatable definitions related to _xtos_set_exception_handler. GDBSTUB definitions are different from the BootROM's. * Update tools/platformio-build.py Co-authored-by: Max Prokhorov <prokhorov.max@outlook.com> * Requested changes Changed mmu related usages of ETS_... defines to DBG_MMU_... Cleanup in example MMU48K.ino. Removed stale memory reference macro and mmu_status print statement. Cleanup printf '\n' to be '\r\n'. Improved issolation of development debug prints from the rest of the debug prints. * Corrected comment. And added missing include. * Improve comment. * style and comment correction * Added draft mmu.rst file and updated index. Updated example HeapMetric.ino to also illustrate use of IRAM Improved comments in exc-c-wrapper-handler.S. Added insurance IRQ disable. * Updated mmu.rst Improved function name uniqueness for is_iram, is_dram, and is_icache by adding prefix mmu_. Also, made them available outside of a debug build. Made pointer precision width more specific. Made some of the static inline functions in mmu_irm.h safe for ISRs by setting then for always inline. * Add a default MMU_IRAM_SIZE value for a new CI test to pass. Extended use 'umm_heap_context_t *_context' argument in ..._core functions and expanded its usage to reduce unnecessary repeated calls to umm_info(NULL, false), also removed recursion from umm_info(NULL, true). Fixed stack buffer length in umm_info_safe_printf_P and heap.cpp. Added example for creating an IRAM reserve section. Updated mmu.rst. Grammar and spelling corrections. * CI appeasement * CI appeasement with comment correction. * Ensure SYS always runs with DRAM Heap selected. * Add/move heap stack overflow/underflow check to Esp.cpp where the event was discarded. * Improved comment clarity of purpose for IramReserve.ino. Clean up MMU48K.ino * Added missing #include * Corrected usage of warning * CI appeasement and use #message not #pragma message * Updated git version of eboot.elf to match build version. Good test catch. * Remove conditional build option USE_ISR_SAFE_EXC_WRAPPER, always install. Use the replacement wrapper on non32xfer_exception_handler install. Added comments to code describing some exception handling issues. * Updated mmu.rst * Expanded and clarified comments. Limited access to some detailed typdefs/prototypes to .cpp modules, to avoid future build conflicts. Completed TODO for verifing that the "C" structure struct __exception_frame matches the ASM version. Fixed some typo's, code rot, and added some more cases in examaple irammem.ino. Refactored a little and reordered printing to ease comparison between methods. Corrected `#ifdef __cplusplus` coverage area. Cleaned up `extern "C" ...` usage. Fixes issues with including mmu_iram.h or esp8266_undocumented.h in .c files. * Style fixes and more cleanup * Style fix * Remove unnessasary IRAM_ATTR from install_non32xfer_exception_handler Some comment tuning. In the context of _xtos_set_exception_handler and the functions it registers, changed to type int for exception cause type. This is also the type used by gdbstub and some other Xtensa files I found.
280 lines
12 KiB
C
280 lines
12 KiB
C
// ROM and blob calls without official headers available
|
|
|
|
#if !defined(__ESP8266_UNDOCUMENTED_H) && !(defined(_ASMLANGUAGE) || defined(__ASSEMBLER__))
|
|
#define __ESP8266_UNDOCUMENTED_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#ifndef XCHAL_EXCCAUSE_NUM
|
|
// from tools/xtensa-lx106-elf/include/xtensa/config/core.h:629:#define XCHAL_EXCCAUSE_NUM 64
|
|
#define XCHAL_EXCCAUSE_NUM 64
|
|
#endif
|
|
|
|
// ROM
|
|
|
|
extern void rom_i2c_writeReg_Mask(int, int, int, int, int, int);
|
|
extern int rom_i2c_readReg_Mask(int, int, int, int, int);
|
|
|
|
extern int uart_baudrate_detect(int, int);
|
|
|
|
/*
|
|
ROM function, uart_buff_switch(), is used to switch printing between UART0 and
|
|
UART1. It updates a structure that only controls a select group of print
|
|
functions. ets_putc() and ets_uart_printf() are examples and are not affected by
|
|
calls to ets_install_putc1().
|
|
|
|
Use:
|
|
0 for UART0, also clears RX FIFO
|
|
1 for UART1
|
|
*/
|
|
extern void uart_buff_switch(uint8_t);
|
|
|
|
/*
|
|
ROM function, ets_uart_printf(), prints on the UART selected by
|
|
uart_buff_switch(). Supported format options are the same as vprintf(). Also
|
|
has cooked newline behavior. No flash format/string support; however, ISR safe.
|
|
Also, uses a static function in ROM to print characters which is only
|
|
controlled by uart_buff_switch().
|
|
*/
|
|
extern int ets_uart_printf(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
|
|
|
|
extern void ets_delay_us(uint32_t us);
|
|
|
|
#ifndef GDBSTUB_H
|
|
/*
|
|
GDBSTUB duplicates these with some variances that are not compatible with our
|
|
references (offsets), which are synced with those used by the BootROM.
|
|
Specifically, the BootROM does not have register "a1" in the structure where
|
|
GDBSTUB does.
|
|
*/
|
|
|
|
/*
|
|
This structure is used in the argument list of "C" callable exception handlers.
|
|
See `_xtos_set_exception_handler` details below.
|
|
*/
|
|
struct __exception_frame
|
|
{
|
|
uint32_t epc;
|
|
uint32_t ps;
|
|
uint32_t sar;
|
|
uint32_t unused;
|
|
union {
|
|
struct {
|
|
uint32_t a0;
|
|
// note: no a1 here!
|
|
uint32_t a2;
|
|
uint32_t a3;
|
|
uint32_t a4;
|
|
uint32_t a5;
|
|
uint32_t a6;
|
|
uint32_t a7;
|
|
uint32_t a8;
|
|
uint32_t a9;
|
|
uint32_t a10;
|
|
uint32_t a11;
|
|
uint32_t a12;
|
|
uint32_t a13;
|
|
uint32_t a14;
|
|
uint32_t a15;
|
|
};
|
|
uint32_t a_reg[15];
|
|
};
|
|
uint32_t cause;
|
|
};
|
|
#endif
|
|
|
|
/*
|
|
Most of the comments here are gleamed from the xtensa files found at the site
|
|
listed below and are mostly unverified:
|
|
https://github.com/qca/open-ath9k-htc-firmware/tree/master/sboot/magpie_1_1/sboot/athos/src/xtos
|
|
* exc-c-wrapper-handler.S
|
|
* exc-sethandler.c
|
|
*/
|
|
|
|
/*
|
|
The Boot ROM sets up a table of dispatch handlers at 0x3FFFC000. This table
|
|
has an entry for each of the EXCCAUSE values, 0 through 63. The exception
|
|
handler at the `User Exception Vector` uses EXCCAUSE with the base address
|
|
0x3FFFC000 to build a jump address to the respective cause handler. Of the
|
|
cause handle functions, `_xtos_c_wrapper_handler` and `_xtos_unhandled_exception`
|
|
are of interest.
|
|
|
|
Exception handler entries that do not have a specific handler are set to
|
|
`_xtos_unhandled_exception`. This handler will execute a `break 1, 1`
|
|
(0x4000DC4Bu) before doing a `rfe` (return from exception). Since the PC has
|
|
not changed, the event that caused the 1st exception will likely keep
|
|
repeating until the HWDT kicks in.
|
|
|
|
These exception handling functions are in assembly, and do not conform to the
|
|
typical "C" function conventions. However, some form of prototype/typedef is
|
|
needed to reference these function addresses in "C" code. In
|
|
`RTOS_SDK/components/esp8266/include/xtensa/xtruntime.h`, it uses a compounded
|
|
definition that equates to `void (*)(...)` for .cpp modules to use. I have
|
|
noticed this creates sufficient confusion at compilation to get your attention
|
|
when used in the wrong place. I have copied that definition here.
|
|
|
|
Added to eagle.rom.addr.v6.ld:
|
|
PROVIDE ( _xtos_exc_handler_table = 0x3fffc000 );
|
|
PROVIDE ( _xtos_c_handler_table = 0x3fffc100 );
|
|
*/
|
|
#ifndef XTRUNTIME_H
|
|
// This is copy/paste from RTOS_SDK/components/esp8266/include/xtensa/xtruntime.h
|
|
#ifdef __cplusplus
|
|
typedef void (_xtos_handler_func)(...);
|
|
#else
|
|
typedef void (_xtos_handler_func)();
|
|
#endif
|
|
typedef _xtos_handler_func *_xtos_handler;
|
|
|
|
extern _xtos_handler _xtos_exc_handler_table[XCHAL_EXCCAUSE_NUM];
|
|
|
|
/*
|
|
Assembly-level handler, used in the _xtos_exc_handler_table[]. It is a wrapper
|
|
for calling registered "C" exception handlers.
|
|
*/
|
|
_xtos_handler_func _xtos_c_wrapper_handler;
|
|
|
|
/*
|
|
Assembly-level handler, used in the _xtos_exc_handler_table[]. It is the
|
|
default handler, for exceptions without a registered handler.
|
|
*/
|
|
_xtos_handler_func _xtos_unhandled_exception;
|
|
#endif
|
|
|
|
|
|
#ifdef __cplusplus
|
|
// For these definitions, try to be more precise for .cpp module usage.
|
|
|
|
/*
|
|
A detailed typdef for the "C" callable functions found in
|
|
`_xtos_c_handler_table[]` More details in `_xtos_set_exception_handler`
|
|
comments below.
|
|
*/
|
|
typedef void (*fn_c_exception_handler_t)(struct __exception_frame *ef, int cause);
|
|
|
|
/*
|
|
TMI maybe? However, it may be useful for a deep debugging session.
|
|
`_xtos_p_none` is the default "C" exception handler that fills the
|
|
_xtos_c_handler_table[]. It is present when an exception handler has not been
|
|
registered. It simply consist of a single instruction, `ret`.
|
|
It is also internally used by `_xtos_set_exception_handler(cause, NULL)` to
|
|
reset a "C" exception handler back to the unhandled state. The coresponding
|
|
`_xtos_exc_handler_table` entry will be set to `_xtos_unhandled_exception`.
|
|
Note, if nesting handlers is desired this must be implemented in the new "C"
|
|
exception handler(s) being registered.
|
|
*/
|
|
extern void _xtos_p_none(struct __exception_frame *ef, int cause);
|
|
|
|
/*
|
|
TMI maybe?
|
|
For `extern _xtos_handler _xtos_c_handler_table[XCHAL_EXCCAUSE_NUM];`, defined
|
|
in in `xtensa/xtos/exc-sethandler.c`. _xtos_handler is a generalized
|
|
definition that doesn't match the actual function definition of those
|
|
assigned to `_xtos_c_handler_table` entries.
|
|
|
|
At this time we do not require direct access to this table. We perform updates
|
|
by calling the ROM function `_xtos_set_exception_handler`.
|
|
|
|
A corrected version for .cpp would look like this:
|
|
*/
|
|
extern fn_c_exception_handler_t _xtos_c_handler_table[XCHAL_EXCCAUSE_NUM];
|
|
|
|
/*
|
|
ROM API function `_xtos_set_exception_handler` registers a "C" callable
|
|
exception handler for a specified general exception, (EXCCAUSE value). (source
|
|
in xtensa/xtos/exc-sethandler.c)
|
|
* If `cause`/reason (EXCCAUSE) is out of range, >=64, it returns NULL.
|
|
* If the new exception handler is installed, it returns the previous handler.
|
|
* If the previous handler was `_xtos_unhandled_exception`/`_xtos_p_none`, it
|
|
returns NULL.
|
|
|
|
Note, the installed "C" exception handler is noramlly called from the ROM
|
|
function _xtos_c_wrapper_handler with IRQs enabled. This build now includes a
|
|
replacement wrapper that is used with the "C" exception handler for
|
|
EXCCAUSE_LOAD_STORE_ERROR (3), Non 32-bit read/write error.
|
|
|
|
This prototype has been corrected (changed from a generalized to specific
|
|
argument list) for the .cpp files in this projects; however, it does not match
|
|
the over generalized version in some Xtensa .h files (not currently part of
|
|
this project)
|
|
|
|
To aid against future conflicts, keep these new defines limited to .cpp with
|
|
`#ifdef __cplusplus`.
|
|
*/
|
|
extern fn_c_exception_handler_t _xtos_set_exception_handler(int cause, fn_c_exception_handler_t fn);
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
};
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#if defined(VERIFY_C_ASM_EXCEPTION_FRAME_STRUCTURE) || defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
|
|
/*
|
|
Extracted from information at
|
|
From https://github.com/fdivitto/ESPWebFramework/blob/master/SDK/xtensa-lx106-elf/xtensa-lx106-elf/lib/libhandlers-null.txt
|
|
|
|
The UEXC_... values are create by the macro STRUCT_FIELD in `xtruntime-frames.h`
|
|
|
|
These VERIFY_... values are used to confirm that the "C" structure offsets
|
|
match those generated in exc-c-wrapper-handler.S.
|
|
*/
|
|
#define VERIFY_UEXC_pc 0x0000
|
|
#define VERIFY_UEXC_ps 0x0004
|
|
#define VERIFY_UEXC_sar 0x0008
|
|
#define VERIFY_UEXC_vpri 0x000c
|
|
#define VERIFY_UEXC_a0 0x0010
|
|
#define VERIFY_UEXC_a2 0x0014
|
|
#define VERIFY_UEXC_a3 0x0018
|
|
#define VERIFY_UEXC_a4 0x001c
|
|
#define VERIFY_UEXC_a5 0x0020
|
|
#define VERIFY_UEXC_a6 0x0024
|
|
#define VERIFY_UEXC_a7 0x0028
|
|
#define VERIFY_UEXC_a8 0x002c
|
|
#define VERIFY_UEXC_a9 0x0030
|
|
#define VERIFY_UEXC_a10 0x0034
|
|
#define VERIFY_UEXC_a11 0x0038
|
|
#define VERIFY_UEXC_a12 0x003c
|
|
#define VERIFY_UEXC_a13 0x0040
|
|
#define VERIFY_UEXC_a14 0x0044
|
|
#define VERIFY_UEXC_a15 0x0048
|
|
#define VERIFY_UEXC_exccause 0x004c
|
|
#define VERIFY_UserFrameSize 0x0050
|
|
#define VERIFY_UserFrameTotalSize 0x0100
|
|
#endif
|
|
|
|
#if defined(VERIFY_C_ASM_EXCEPTION_FRAME_STRUCTURE) && !(defined(_ASMLANGUAGE) || defined(__ASSEMBLER__))
|
|
/*
|
|
A set of static_asserts test to confirm both "C" and ASM structures match.
|
|
|
|
This only needs to be verified once.
|
|
We use `#define VERIFY_C_ASM_EXCEPTION_FRAME_STRUCTURE` to limit number of
|
|
times tested in a build. Testing is done from core_esp8266_non32xfer.cpp.
|
|
|
|
ASM structure defines are verified in exc-c-wrapper-handler.S
|
|
*/
|
|
static_assert(offsetof(struct __exception_frame, epc) == VERIFY_UEXC_pc, "offsetof(struct __exception_frame, epc) != VERIFY_UEXC_pc, expected 0x0000");
|
|
static_assert(offsetof(struct __exception_frame, ps) == VERIFY_UEXC_ps, "offsetof(struct __exception_frame, ps) != VERIFY_UEXC_ps, expected 0x0004");
|
|
static_assert(offsetof(struct __exception_frame, sar) == VERIFY_UEXC_sar, "offsetof(struct __exception_frame, sar) != VERIFY_UEXC_sar, expected 0x0008");
|
|
static_assert(offsetof(struct __exception_frame, unused) == VERIFY_UEXC_vpri, "offsetof(struct __exception_frame, unused) != VERIFY_UEXC_vpri, expected 0x000c");
|
|
static_assert(offsetof(struct __exception_frame, a0) == VERIFY_UEXC_a0, "offsetof(struct __exception_frame, a0) != VERIFY_UEXC_a0, expected 0x0010");
|
|
static_assert(offsetof(struct __exception_frame, a2) == VERIFY_UEXC_a2, "offsetof(struct __exception_frame, a2) != VERIFY_UEXC_a2, expected 0x0014");
|
|
static_assert(offsetof(struct __exception_frame, a3) == VERIFY_UEXC_a3, "offsetof(struct __exception_frame, a3) != VERIFY_UEXC_a3, expected 0x0018");
|
|
static_assert(offsetof(struct __exception_frame, a4) == VERIFY_UEXC_a4, "offsetof(struct __exception_frame, a4) != VERIFY_UEXC_a4, expected 0x001c");
|
|
static_assert(offsetof(struct __exception_frame, a5) == VERIFY_UEXC_a5, "offsetof(struct __exception_frame, a5) != VERIFY_UEXC_a5, expected 0x0020");
|
|
static_assert(offsetof(struct __exception_frame, a6) == VERIFY_UEXC_a6, "offsetof(struct __exception_frame, a6) != VERIFY_UEXC_a6, expected 0x0024");
|
|
static_assert(offsetof(struct __exception_frame, a7) == VERIFY_UEXC_a7, "offsetof(struct __exception_frame, a7) != VERIFY_UEXC_a7, expected 0x0028");
|
|
static_assert(offsetof(struct __exception_frame, a8) == VERIFY_UEXC_a8, "offsetof(struct __exception_frame, a8) != VERIFY_UEXC_a8, expected 0x002c");
|
|
static_assert(offsetof(struct __exception_frame, a9) == VERIFY_UEXC_a9, "offsetof(struct __exception_frame, a9) != VERIFY_UEXC_a9, expected 0x0030");
|
|
static_assert(offsetof(struct __exception_frame, a10) == VERIFY_UEXC_a10, "offsetof(struct __exception_frame, a10) != VERIFY_UEXC_a10, expected 0x0034");
|
|
static_assert(offsetof(struct __exception_frame, a11) == VERIFY_UEXC_a11, "offsetof(struct __exception_frame, a11) != VERIFY_UEXC_a11, expected 0x0038");
|
|
static_assert(offsetof(struct __exception_frame, a12) == VERIFY_UEXC_a12, "offsetof(struct __exception_frame, a12) != VERIFY_UEXC_a12, expected 0x003c");
|
|
static_assert(offsetof(struct __exception_frame, a13) == VERIFY_UEXC_a13, "offsetof(struct __exception_frame, a13) != VERIFY_UEXC_a13, expected 0x0040");
|
|
static_assert(offsetof(struct __exception_frame, a14) == VERIFY_UEXC_a14, "offsetof(struct __exception_frame, a14) != VERIFY_UEXC_a14, expected 0x0044");
|
|
static_assert(offsetof(struct __exception_frame, a15) == VERIFY_UEXC_a15, "offsetof(struct __exception_frame, a15) != VERIFY_UEXC_a15, expected 0x0048");
|
|
static_assert(offsetof(struct __exception_frame, cause) == VERIFY_UEXC_exccause, "offsetof(struct __exception_frame, cause) != VERIFY_UEXC_exccause, expected 0x004c");
|
|
#endif
|