Skip to content

Commit 161e7bc

Browse files
committed
Added exception C wrapper replacement.
1 parent edf008a commit 161e7bc

12 files changed

+534
-46
lines changed

cores/esp8266/core_esp8266_main.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ extern "C" void user_init(void) {
334334

335335
cont_init(g_pcont);
336336

337-
#if defined(NON32XFER_HANDLER) || defined(MMU_SEC_HEAP)
337+
#if defined(NON32XFER_HANDLER)
338338
install_non32xfer_exception_handler();
339339
#endif
340340
#if defined(MMU_IRAM_HEAP)

cores/esp8266/core_esp8266_non32xfer.cpp

+28-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ extern "C" {
5050
uint32_t mmu_non32xfer_count = 0;
5151
uint32_t mmu_non32xfer_withinisr_count = 0;
5252

53-
#define DEBUG_WARNING
53+
54+
// #define DEBUG_WARNING
5455
#ifdef DEBUG_WARNING
5556
static void warning(void)
5657
{
@@ -76,7 +77,9 @@ static IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef,
7677
*/
7778
uint32_t insn;
7879
__asm(
80+
#if !defined(USE_ISR_SAFE_EXC_WRAPPER)
7981
"rsil %0, 15\n\t" /* Turn IRQs back off, let exit wrapper restore PS */
82+
#endif
8083
"movi %0, ~3\n\t" /* prepare a mask for the EPC */
8184
"and %0, %0, %1\n\t" /* apply mask for 32bit aligned base */
8285
"ssa8l %1\n\t" /* set up shift register for src op */
@@ -94,12 +97,14 @@ static IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef,
9497
an exception handler?
9598
*/
9699
if (ef->ps & 0x0F) {
100+
#if !defined(USE_ISR_SAFE_EXC_WRAPPER)
97101
if (0 == mmu_non32xfer_withinisr_count) {
98102
ETS_PRINTF("\nload/store exception with INTLEVEL 0x%02X\n", ef->ps & 0x0F);
99103
#if 0
100104
continue; /* fail, not safe for IRQ disabled ?? */
101105
#endif
102106
}
107+
#endif
103108
if (0 == ++mmu_non32xfer_withinisr_count) {
104109
--mmu_non32xfer_withinisr_count; // saturated
105110
}
@@ -205,7 +210,28 @@ static IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef,
205210
panic();
206211
}
207212

213+
#if defined(USE_ISR_SAFE_EXC_WRAPPER)
214+
215+
constexpr _xtos_handler ROM_xtos_c_wrapper_handler = (_xtos_handler)0x40000598;
216+
217+
static void IRAM_ATTR _set_exception_handler_wrapper(uint32_t cause) {
218+
_xtos_handler old_wrapper = _xtos_exc_handler_table[cause];
219+
if (old_wrapper == ROM_xtos_c_wrapper_handler) {
220+
_xtos_exc_handler_table[cause] = _xtos_c_wrapper_handler;
221+
}
222+
}
223+
224+
void IRAM_ATTR install_non32xfer_exception_handler(void) {
225+
if (NULL == old_handler) {
226+
old_handler =
227+
_xtos_set_exception_handler(EXCCAUSE_LOAD_STORE_ERROR,
228+
non32xfer_exception_handler);
208229

230+
_set_exception_handler_wrapper(EXCCAUSE_LOAD_STORE_ERROR);
231+
}
232+
}
233+
234+
#else
209235
void IRAM_ATTR install_non32xfer_exception_handler(void)
210236
{
211237
if (NULL == old_handler) {
@@ -214,5 +240,6 @@ void IRAM_ATTR install_non32xfer_exception_handler(void)
214240
non32xfer_exception_handler);
215241
}
216242
}
243+
#endif
217244

218245
};

cores/esp8266/esp8266_undocumented.h

+84-6
Original file line numberDiff line numberDiff line change
@@ -67,24 +67,102 @@ struct __exception_frame
6767
};
6868
uint32_t cause;
6969
};
70+
/*?
71+
TODO: A set of static_asserts to confim we are matching these.
72+
73+
Extracted from information at
74+
From https://github.com/fdivitto/ESPWebFramework/blob/master/SDK/xtensa-lx106-elf/xtensa-lx106-elf/lib/libhandlers-null.txt
75+
76+
#define UEXC_pc 0x0000
77+
#define UEXC_ps 0x0004
78+
#define UEXC_sar 0x0008
79+
#define UEXC_vpri 0x000c
80+
#define UEXC_a0 0x0010
81+
#define UEXC_a2 0x0014
82+
#define UEXC_a3 0x0018
83+
#define UEXC_a4 0x001c
84+
#define UEXC_a5 0x0020
85+
#define UEXC_a6 0x0024
86+
#define UEXC_a7 0x0028
87+
#define UEXC_a8 0x002c
88+
#define UEXC_a9 0x0030
89+
#define UEXC_a10 0x0034
90+
#define UEXC_a11 0x0038
91+
#define UEXC_a12 0x003c
92+
#define UEXC_a13 0x0040
93+
#define UEXC_a14 0x0044
94+
#define UEXC_a15 0x0048
95+
#define UEXC_exccause 0x004c
96+
#define UserFrameSize 0x0050
97+
#define UserFrameTotalSize 0x0100
98+
*/
99+
100+
/*
101+
Most of the comments here are gleamed from the xtensa files found at the site
102+
listed below and are mostly unverified:
103+
https://github.com/qca/open-ath9k-htc-firmware/tree/master/sboot/magpie_1_1/sboot/athos/src/xtos
104+
* exc-c-wrapper-handler.S
105+
* exc-sethandler.c
106+
*/
70107

71108
/*
72109
ROM Function, _xtos_set_exception_handler(), installs a "C" callable exception handler.
73-
If reason is out of range, >=64, it returns NULL.
74-
If the new exception handler is installed, it returns the previous handler.
75-
If the previous handler was _xtos_unhandled_exception/_xtos_p_none, it returns
76-
NULL.
110+
* If reason is out of range, >=64, it returns NULL.
111+
* If the new exception handler is installed, it returns the previous handler.
112+
* If the previous handler was _xtos_unhandled_exception/_xtos_p_none, it
113+
returns NULL.
77114
78115
Note, the installed "C" exception handler is called from the
79116
_xtos_c_wrapper_handler with IRQs enabled.
80117
*/
81118
typedef void (*fn_exception_handler_t)(struct __exception_frame *ef, uint32_t cause);
82-
extern fn_exception_handler_t _xtos_set_exception_handler(uint32_t reason, fn_exception_handler_t fn);
119+
fn_exception_handler_t _xtos_set_exception_handler(uint32_t reason, fn_exception_handler_t fn);
120+
121+
/*
122+
Added to eagle.rom.addr.v6.ld
123+
PROVIDE ( _xtos_exc_handler_table = 0x3fffc000 );
124+
PROVIDE ( _xtos_c_handler_table = 0x3fffc100 );
125+
*/
126+
#ifdef __cplusplus
127+
typedef void (_xtos_handler_func)(...);
128+
129+
/*
130+
Assembly-level handler, used in the _xtos_exc_handler_table[], a wrapper for
131+
calling registered "C" exception handlers.
132+
*/
133+
void _xtos_c_wrapper_handler(...);
83134

84-
extern void _xtos_unhandled_exception(struct __exception_frame *ef, uint32_t cause);
135+
/*
136+
Assembly-level handler, used in the _xtos_exc_handler_table[], for exceptions
137+
without a registered handler.
138+
*/
139+
void _xtos_unhandled_exception(...);
140+
141+
/*
142+
The default/empty "C" exception handler, used in the _xtos_c_handler_table[],
143+
when an exception handler has not been registered.
144+
Supply this to _xtos_set_exception_handler() to reset an exception handler
145+
back to the unhandled state, _xtos_unhandled_exception.
146+
Note, if you have nesting handlers this is much more complicated than this.
147+
*/
148+
void _xtos_p_none(void);
149+
150+
#else
151+
typedef void (_xtos_handler_func)();
152+
void _xtos_c_wrapper_handler();
153+
void _xtos_unhandled_exception());
154+
void _xtos_p_none();
155+
156+
#endif
157+
158+
typedef _xtos_handler_func *_xtos_handler;
159+
160+
extern _xtos_handler _xtos_exc_handler_table[];
161+
extern _xtos_handler _xtos_c_handler_table[];
85162

86163
#ifdef __cplusplus
87164
};
88165
#endif
89166

167+
90168
#endif

cores/esp8266/exc-c-wrapper-handler.S

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// exc-c-wrapper-handler.S, this is a reduced version of the original file at
2+
// https://github.com/qca/open-ath9k-htc-firmware/blob/master/sboot/magpie_1_1/sboot/athos/src/xtos/exc-c-wrapper-handler.S#L62-L67
3+
//
4+
5+
// exc-c-wrapper-handler.S - General Exception Handler that Dispatches C Handlers
6+
7+
// Copyright (c) 2002-2004, 2006-2007, 2010 Tensilica Inc.
8+
//
9+
// Permission is hereby granted, free of charge, to any person obtaining
10+
// a copy of this software and associated documentation files (the
11+
// "Software"), to deal in the Software without restriction, including
12+
// without limitation the rights to use, copy, modify, merge, publish,
13+
// distribute, sublicense, and/or sell copies of the Software, and to
14+
// permit persons to whom the Software is furnished to do so, subject to
15+
// the following conditions:
16+
//
17+
// The above copyright notice and this permission notice shall be included
18+
// in all copies or substantial portions of the Software.
19+
//
20+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21+
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22+
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23+
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24+
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25+
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26+
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27+
28+
#include <xtensa/coreasm.h>
29+
#include <xtensa/corebits.h>
30+
#include <xtensa/config/specreg.h>
31+
// #include "xtos-internal.h"
32+
// #ifdef SIMULATOR
33+
// #include <xtensa/simcall.h>
34+
// #endif
35+
36+
#include "xtruntime-frames.h"
37+
38+
/*
39+
* This is the general exception assembly-level handler that dispatches C handlers.
40+
*/
41+
.align 4
42+
.global _xtos_c_wrapper_handler
43+
_xtos_c_wrapper_handler:
44+
45+
// HERE: a2, a3, a4 have been saved to exception stack frame allocated with a1 (sp).
46+
// a2 contains EXCCAUSE.
47+
s32i a5, a1, UEXC_a5 // a5 will get clobbered by ENTRY after the pseudo-CALL4
48+
// (a4..a15 spilled as needed; save if modified)
49+
50+
//NOTA: Possible future improvement:
51+
// keep interrupts disabled until we get into the handler, such that
52+
// we don't have to save other critical state such as EXCVADDR here.
53+
// @mhightower83 - This promise was broken by an "rsil a13, 0" below.
54+
//rsr a3, EXCVADDR
55+
s32i a2, a1, UEXC_exccause
56+
//s32i a3, a1, UEXC_excvaddr
57+
58+
// Set PS fields:
59+
// EXCM = 0
60+
// WOE = __XTENSA_CALL0_ABI__ ? 0 : 1
61+
// UM = 1
62+
// INTLEVEL = EXCM_LEVEL = 1
63+
// CALLINC = __XTENSA_CALL0_ABI__ ? 0 : 1
64+
// OWB = 0 (really, a dont care if !__XTENSA_CALL0_ABI__)
65+
66+
movi a2, 0x23 // 0x21, PS_UM|PS_INTLEVEL(XCHAL_EXCM_LEVEL)
67+
rsr a3, EPC_1
68+
// @mhightower83 - I assume PS.EXCM was set and now is being cleared, thus
69+
// allowing new exceptions and interrupts within PS_INTLEVEL to be possible.
70+
xsr a2, PS
71+
72+
// HERE: window overflows enabled, but NOT SAFE because we're not quite
73+
// in a valid windowed context (haven't restored a1 yet...);
74+
// so don't cause any (keep to a0..a3) until we've saved critical state and restored a1:
75+
76+
// NOTE: MUST SAVE EPC1 before causing any overflows, because overflows corrupt EPC1.
77+
s32i a3, a1, UEXC_pc
78+
s32i a2, a1, UEXC_ps
79+
s32i a0, a1, UEXC_a0 // save the rest of the registers
80+
s32i a6, a1, UEXC_a6
81+
s32i a7, a1, UEXC_a7
82+
s32i a8, a1, UEXC_a8
83+
s32i a9, a1, UEXC_a9
84+
s32i a10, a1, UEXC_a10
85+
s32i a11, a1, UEXC_a11
86+
s32i a12, a1, UEXC_a12
87+
s32i a13, a1, UEXC_a13
88+
s32i a14, a1, UEXC_a14
89+
s32i a15, a1, UEXC_a15
90+
rsync // wait for WSR to PS to complete
91+
rsr a12, SAR
92+
93+
// @mhightower83 - I think after the next instruction we have the potential of
94+
// loosing UEXC_excvaddr Which the earlier comment said we need to preserve for
95+
// the exception handler.
96+
//
97+
// rsil a13, 0
98+
99+
movi a13, _xtos_c_handler_table // &table
100+
l32i a15, a1, UEXC_exccause // arg2: exccause
101+
s32i a12, a1, UEXC_sar
102+
addx4 a12, a15, a13 // a12 = table[exccause]
103+
l32i a12, a12, 0 // ...
104+
mov a2, a1 // arg1: exception parameters
105+
mov a3, a15 // arg2: exccause
106+
beqz a12, 1f // null handler => skip call
107+
callx0 a12 // call C exception handler for this exception
108+
1:
109+
// Now exit the handler.
110+
111+
// Restore special registers
112+
l32i a14, a1, UEXC_sar
113+
114+
/*
115+
* Disable interrupts while returning from the pseudo-CALL setup above,
116+
* for the same reason they were disabled while doing the pseudo-CALL:
117+
* this sequence restores SP such that it doesn't reflect the allocation
118+
* of the exception stack frame, which we still need to return from
119+
* the exception.
120+
*/
121+
// rsil a12, 1 // XCHAL_EXCM_LEVEL
122+
wsr a14, SAR
123+
movi a0, _xtos_return_from_exc
124+
jx a0
125+
126+
/* FIXME: what about _GeneralException ? */
127+
.size _xtos_c_wrapper_handler, . - _xtos_c_wrapper_handler

cores/esp8266/mmu_iram.h

+27-14
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@
4040
#define DEBUG_MMU
4141
#endif
4242

43-
43+
/*
44+
The more I look at _xtos_c_wrapper_handler the more convinced I am that this
45+
USE_ISR_SAFE_EXC_WRAPPER is required.
46+
*/
47+
#define USE_ISR_SAFE_EXC_WRAPPER
4448

4549
#if defined( DEV_DEBUG_PRINT) || defined(DEV_DEBUG_MMU_IRAM) || defined(DEBUG_MMU)
4650
#include <esp8266_peri.h>
@@ -113,18 +117,10 @@ extern mmu_cre_status_t mmu_status;
113117
static inline bool is_iram(uint32_t addr) {
114118
// constexpr uint32_t _start = 0x40100000UL;
115119
#define IRAM_START 0x40100000UL
116-
117120
#ifndef MMU_IRAM_SIZE
118-
#define MMU_IRAM_SIZE 0xC000UL
119-
#endif
120-
121-
#ifdef MMU_SEC_HEAP_SIZE
122-
// constexpr uint32_t _end = _start + MMU_IRAM_SIZE + MMU_SEC_HEAP_SIZE;
123-
#define IRAM_END (IRAM_START + MMU_IRAM_SIZE + MMU_SEC_HEAP_SIZE)
124-
#else
125-
// constexpr uint32_t _end = _start + MMU_IRAM_SIZE;
126-
#define IRAM_END (IRAM_START + MMU_IRAM_SIZE)
121+
#define MMU_IRAM_SIZE 0x8000UL
127122
#endif
123+
#define IRAM_END (IRAM_START + MMU_IRAM_SIZE)
128124

129125
return (IRAM_START <= addr && IRAM_END > addr);
130126
}
@@ -165,14 +161,14 @@ static inline bool is_icache(uint32_t addr) {
165161
if (is_iram((uint32_t)a) || is_dram((uint32_t)a)) { \
166162
} else { \
167163
DBG_MMU_PRINTF("\nexcvaddr: %p\n", a); \
168-
assert(("Outside of Range Write" && false)); \
164+
assert(("Outside of Range - Write" && false)); \
169165
}
170166

171167
#define ASSERT_RANGE_TEST_READ(a) \
172-
if (is_iram((uint32_t)a) || is_icache((uint32_t)a) || is_dram((uint32_t)a)) { \
168+
if (is_iram((uint32_t)a) || is_dram((uint32_t)a) || is_icache((uint32_t)a)) { \
173169
} else { \
174170
DBG_MMU_PRINTF("\nexcvaddr: %p\n", a); \
175-
assert(("Outside of Range Read" && false)); \
171+
assert(("Outside of Range - Read" && false)); \
176172
}
177173

178174
#else
@@ -258,4 +254,21 @@ static inline int16_t set_int16_iram(short *p16, const int16_t val) {
258254
}
259255
#endif
260256

257+
#if (MMU_IRAM_SIZE > 32*1024) && !defined(MMU_SEC_HEAP)
258+
extern "C" void _text_end(void);
259+
#define MMU_SEC_HEAP mmu_sec_heap()
260+
#define MMU_SEC_HEAP_SIZE mmu_sec_heap_size()
261+
262+
static inline __attribute__((always_inline))
263+
void *mmu_sec_heap(void) {
264+
uint32_t sec_heap = (uint32_t)_text_end + 32;
265+
return (void *)(sec_heap &= ~7);
266+
}
267+
268+
static inline __attribute__((always_inline))
269+
size_t mmu_sec_heap_size(void) {
270+
return (size_t)0xC000UL - ((size_t)mmu_sec_heap() - 0x40100000UL);
271+
}
272+
#endif
273+
261274
#endif

0 commit comments

Comments
 (0)