Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Nodemcu Firmware
Commits
7f92bf64
Commit
7f92bf64
authored
May 26, 2016
by
Johny Mattsson
Browse files
Completely reworked user exception handler.
Incidentally now also a whole lot faster.
parent
5c39a1f6
Changes
4
Hide whitespace changes
Inline
Side-by-side
app/Makefile
View file @
7f92bf64
...
@@ -109,7 +109,6 @@ USED_SDK_LIBS= \
...
@@ -109,7 +109,6 @@ USED_SDK_LIBS= \
phy
\
phy
\
pp
\
pp
\
smartconfig
\
smartconfig
\
ssc
\
ssl
\
ssl
\
wpa
\
wpa
\
wps
\
wps
\
...
@@ -125,6 +124,7 @@ LINKFLAGS_eagle.app.v6 = \
...
@@ -125,6 +124,7 @@ LINKFLAGS_eagle.app.v6 = \
-Wl
,--wrap
=
_xtos_set_exception_handler
\
-Wl
,--wrap
=
_xtos_set_exception_handler
\
-Wl
,-static
\
-Wl
,-static
\
$(
addprefix
-u
,
$(SELECTED_MODULE_SYMS)
)
\
$(
addprefix
-u
,
$(SELECTED_MODULE_SYMS)
)
\
-u
_UserExceptionVectorOverride
\
-Wl
,--start-group
\
-Wl
,--start-group
\
-lhal
\
-lhal
\
$(
addprefix
-l
,
$(USED_SDK_LIBS)
)
\
$(
addprefix
-l
,
$(USED_SDK_LIBS)
)
\
...
...
app/user/user_exceptions.c
View file @
7f92bf64
...
@@ -31,82 +31,71 @@
...
@@ -31,82 +31,71 @@
* @author Johny Mattsson <jmattsson@dius.com.au>
* @author Johny Mattsson <jmattsson@dius.com.au>
*/
*/
#include "user_exceptions.h"
/* Minimal handler function for 8/16bit loads from the mapped SPI flash.
* Called from the overridden UserExceptionVector on exception cause 3.
#define LOAD_MASK 0x00f00fu
*/
#define L8UI_MATCH 0x000002u
asm
(
#define L16UI_MATCH 0x001002u
".section
\"
.iram0.text
\"\n
"
#define L16SI_MATCH 0x009002u
" .align 4
\n
"
"store_mask:
\n
"
" .word 0x004000
\n
"
/* bit 14 is set on store instructions (see note ^) */
void
load_non_32_wide_handler
(
struct
exception_frame
*
ef
,
uint32_t
cause
)
"align_mask:
\n
"
{
" .word ~3
\n
"
/* mask to get 32bit alignment of addresses */
/* If this is not EXCCAUSE_LOAD_STORE_ERROR you're doing it wrong! */
".type cause3_handler,@function
\n
"
(
void
)
cause
;
"cause3_handler:
\n
"
" wsr a2, EXCSAVE2
\n
"
/* free up a2 for use too */
uint32_t
epc1
=
ef
->
epc
;
" rsr a2, EPC1
\n
"
/* get the program counter that caused the exception */
uint32_t
excvaddr
;
" ssa8l a2
\n
"
/* prepare to extract the (unaligned) instruction */
uint32_t
insn
;
" l32r a0, align_mask
\n
"
/* prepare mask for 32bit alignment */
asm
(
" and a2, a2, a0
\n
"
/* get aligned base address of instruction */
"rsr %0, EXCVADDR;"
/* read out the faulting address */
" l32i a0, a2, 0
\n
"
/* load first part */
"movi a4, ~3;"
/* prepare a mask for the EPC */
" l32i a2, a2, 4
\n
"
/* load second part */
"and a4, a4, %2;"
/* apply mask for 32bit aligned base */
" src a0, a2, a0
\n
"
/* faulting instruction now in a0 */
"l32i a5, a4, 0;"
/* load part 1 */
" l32r a2, store_mask
\n
"
"l32i a6, a4, 4;"
/* load part 2 */
" and a0, a0, a2
\n
"
/* test for store bit */
"ssa8l %2;"
/* set up shift register for src op */
" bnez a0, 1f
\n
"
/* it's a store, we don't do stores, get out */
"src %1, a6, a5;"
/* right shift to get faulting instruction */
:
"=r"
(
excvaddr
),
"=r"
(
insn
)
:
"r"
(
epc1
)
:
"a4"
,
"a5"
,
"a6"
);
uint32_t
valmask
=
0
;
uint32_t
what
=
insn
&
LOAD_MASK
;
if
(
what
==
L8UI_MATCH
)
valmask
=
0xffu
;
else
if
(
what
==
L16UI_MATCH
||
what
==
L16SI_MATCH
)
valmask
=
0xffffu
;
else
{
die:
/* Turns out we couldn't fix this, trigger a system break instead
* and hang if the break doesn't get handled. This is effectively
* what would happen if the default handler was installed. */
asm
(
"break 1, 1"
);
while
(
1
)
{}
}
/* Load, shift and mask down to correct size */
uint32_t
val
=
(
*
(
uint32_t
*
)(
excvaddr
&
~
0x3
));
val
>>=
(
excvaddr
&
0x3
)
*
8
;
val
&=
valmask
;
/* Sign-extend for L16SI, if applicable */
""
/* As it turns out, the ESP8266 happily does 8/16bit */
if
(
what
==
L16SI_MATCH
&&
(
val
&
0x8000
))
/* loads from the mapped SPI flash, but then raises an */
val
|=
0xffff0000
;
/* exception anyway; we can simply increment the */
/* program counter and be our merry way, safe in */
/* the knowledge that the loads have already been done.*/
/* Note that this only applies to the SPI flash, not */
/* internal ROM or IRAM - if we ever want to support */
/* those we'll need to add the appropriate loading */
/* logic here. For now I see no need for such support. */
int
regno
=
(
insn
&
0x0000f0u
)
>>
4
;
" rsr a2, EPC1
\n
"
/* read the program counter again */
if
(
regno
==
1
)
" addi a2, a2, 3
\n
"
/* advance program counter past faulting instruction */
goto
die
;
/* we can't support loading into a1, just die */
" wsr a2, EPC1
\n
"
/* and store it back */
else
if
(
regno
!=
0
)
" rsr a2, EXCSAVE2
\n
"
/* restore a2 */
--
regno
;
/* account for skipped a1 in exception_frame */
" rsr a0, EXCSAVE1
\n
"
/* restore a0 */
" rfe
\n
"
/* and done! */
"1:rsr a2, EXCSAVE2
\n
"
/* we're about to chain, so restore the a2 we clobbered*/
" ret
\n
"
/* and hop back into the exception vector code */
);
/* Note ^) Except for the S32E instruction, but that's not applicable here,
* so we can happily ignore it.
*/
ef
->
a_reg
[
regno
]
=
val
;
/* carry out the load */
ef
->
epc
+=
3
;
/* resume at following instruction */
}
/**
/* Our sneaky override of the UserExceptionVector to allow us to handle 8/16bit
* The SDK's user_main function installs a debugging handler regardless
* loads from SPI flash. MUST BE >= 32bytes compiled, as the next vector starts
* of whether there's a proper handler installed for EXCCAUSE_LOAD_STORE_ERROR,
* there.
* which of course breaks everything if we allow that to go through. As such,
* we use the linker to wrap that call and stop the SDK from shooting itself in
* its proverbial foot.
*/
*/
exception_handler_fn
TEXT_SECTION_ATTR
asm
(
__wrap__xtos_set_exception_handler
(
uint32_t
cause
,
exception_handler_fn
fn
)
".section
\"
.UserExceptionVectorOverride.text
\"\n
"
{
".type _UserExceptionVectorOverride,@function
\n
"
if
(
cause
!=
EXCCAUSE_LOAD_STORE_ERROR
)
".globl _UserExceptionVectorOverride
\n
"
__real__xtos_set_exception_handler
(
cause
,
fn
);
"_UserExceptionVectorOverride:
\n
"
}
" wsr a0, EXCSAVE1
\n
"
/* free up a0 for a while */
" rsr a0, EXCCAUSE
\n
"
/* get the exception cause */
" bnei a0, 3, 2f
\n
"
/* if not EXCCAUSE_LOAD_STORE_ERROR, chain to rtos */
" j 1f
\n
"
/* jump past noncode bytes for cause3_handler addr */
" .align 4
\n
"
/* proper alignment for literals */
" .literal_position
\n
"
/* the linker will put cause3_handler addr here */
"1:call0 cause3_handler
\n
"
/* handle loads and rfe, stores will return here */
"2:rsr a0, EXCSAVE1
\n
"
/* restore a0 before we chain */
" j _UserExceptionVector
\n
"
/* and off we go to rtos */
);
app/user/user_main.c
View file @
7f92bf64
...
@@ -39,9 +39,6 @@ static os_event_t *taskQueue;
...
@@ -39,9 +39,6 @@ static os_event_t *taskQueue;
*/
*/
void
TEXT_SECTION_ATTR
user_start_trampoline
(
void
)
void
TEXT_SECTION_ATTR
user_start_trampoline
(
void
)
{
{
__real__xtos_set_exception_handler
(
EXCCAUSE_LOAD_STORE_ERROR
,
load_non_32_wide_handler
);
#ifdef LUA_USE_MODULES_RTCTIME
#ifdef LUA_USE_MODULES_RTCTIME
// Note: Keep this as close to call_user_start() as possible, since it
// Note: Keep this as close to call_user_start() as possible, since it
// is where the cpu clock actually gets bumped to 80MHz.
// is where the cpu clock actually gets bumped to 80MHz.
...
@@ -113,7 +110,6 @@ void nodemcu_init(void)
...
@@ -113,7 +110,6 @@ void nodemcu_init(void)
fs_mount
();
fs_mount
();
// test_spiffs();
// test_spiffs();
#endif
#endif
// endpoint_setup();
task_post_low
(
task_get_id
(
start_lua
),
's'
);
task_post_low
(
task_get_id
(
start_lua
),
's'
);
}
}
...
...
ld/nodemcu.ld
View file @
7f92bf64
...
@@ -159,13 +159,6 @@ SECTIONS
...
@@ -159,13 +159,6 @@ SECTIONS
_rodata_end = ABSOLUTE(.);
_rodata_end = ABSOLUTE(.);
} >dram0_0_seg :dram0_0_phdr
} >dram0_0_seg :dram0_0_phdr
.UserExceptionVector.literal : AT(LOADADDR(.rodata) + (ADDR(.UserExceptionVector.literal) - ADDR(.rodata))) ALIGN(4)
{
_UserExceptionVector_literal_start = ABSOLUTE(.);
*(.UserExceptionVector.literal)
_UserExceptionVector_literal_end = ABSOLUTE(.);
} >dram0_0_seg :dram0_0_phdr
.bss ALIGN(8) (NOLOAD) : ALIGN(4)
.bss ALIGN(8) (NOLOAD) : ALIGN(4)
{
{
. = ALIGN (8);
. = ALIGN (8);
...
@@ -206,11 +199,7 @@ SECTIONS
...
@@ -206,11 +199,7 @@ SECTIONS
LONG(0)
LONG(0)
LONG(0)
LONG(0)
. = ALIGN(16);
. = ALIGN(16);
*(.UserExceptionVector.text)
KEEP(*(.UserExceptionVectorOverride.text))
LONG(0)
LONG(0)
LONG(0)
LONG(0)
. = ALIGN(16);
. = ALIGN(16);
*(.DoubleExceptionVector.text)
*(.DoubleExceptionVector.text)
LONG(0)
LONG(0)
...
@@ -218,6 +207,7 @@ SECTIONS
...
@@ -218,6 +207,7 @@ SECTIONS
LONG(0)
LONG(0)
LONG(0)
LONG(0)
. = ALIGN (16);
. = ALIGN (16);
KEEP(*(.UserExceptionVector.text))
*(.entry.text)
*(.entry.text)
*(.init.literal)
*(.init.literal)
*(.init)
*(.init)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment