commit
947068cd8b
|
@ -99,7 +99,7 @@ LINKFLAGS_eagle.app.v6 = \
|
||||||
-nostdlib \
|
-nostdlib \
|
||||||
-T$(LD_FILE) \
|
-T$(LD_FILE) \
|
||||||
-Wl,--no-check-sections \
|
-Wl,--no-check-sections \
|
||||||
-u call_user_start \
|
-Wl,--wrap=_xtos_set_exception_handler \
|
||||||
-Wl,-static \
|
-Wl,-static \
|
||||||
-Wl,--start-group \
|
-Wl,--start-group \
|
||||||
-lc \
|
-lc \
|
||||||
|
|
|
@ -37,3 +37,57 @@ extern unsigned char * base64_decode(const unsigned char *src, size_t len, size_
|
||||||
// initialized because it uses mem_malloc
|
// initialized because it uses mem_malloc
|
||||||
|
|
||||||
extern void mem_init(void * start_addr);
|
extern void mem_init(void * start_addr);
|
||||||
|
|
||||||
|
|
||||||
|
// Hardware exception handling
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* C-level exception handler callback prototype.
|
||||||
|
*
|
||||||
|
* Does not need an RFE instruction - it is called through a wrapper which
|
||||||
|
* performs state capture & restore, as well as the actual RFE.
|
||||||
|
*
|
||||||
|
* @param ef An exception frame containing the relevant state from the
|
||||||
|
* exception triggering. This state may be manipulated and will
|
||||||
|
* be applied on return.
|
||||||
|
* @param cause The exception cause number.
|
||||||
|
*/
|
||||||
|
typedef void (*exception_handler_fn) (struct exception_frame *ef, uint32_t cause);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the exception handler function for a particular exception cause.
|
||||||
|
* @param handler The exception handler to install.
|
||||||
|
* If NULL, reverts to the XTOS default handler.
|
||||||
|
* @returns The previous exception handler, or NULL if none existed prior.
|
||||||
|
*/
|
||||||
|
exception_handler_fn _xtos_set_exception_handler (uint32_t cause, exception_handler_fn handler);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2015 Dius Computing Pty Ltd. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* - Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* - Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* - Neither the name of the copyright holders nor the names of
|
||||||
|
* its contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||||
|
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||||
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @author Johny Mattsson <jmattsson@dius.com.au>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "user_exceptions.h"
|
||||||
|
|
||||||
|
#define LOAD_MASK 0x00f00fu
|
||||||
|
#define L8UI_MATCH 0x000002u
|
||||||
|
#define L16UI_MATCH 0x001002u
|
||||||
|
#define L16SI_MATCH 0x009002u
|
||||||
|
|
||||||
|
|
||||||
|
void load_non_32_wide_handler (struct exception_frame *ef, uint32_t cause)
|
||||||
|
{
|
||||||
|
/* If this is not EXCCAUSE_LOAD_STORE_ERROR you're doing it wrong! */
|
||||||
|
(void)cause;
|
||||||
|
|
||||||
|
uint32_t epc1 = ef->epc;
|
||||||
|
uint32_t excvaddr;
|
||||||
|
uint32_t insn;
|
||||||
|
asm (
|
||||||
|
"rsr %0, EXCVADDR;" /* read out the faulting address */
|
||||||
|
"movi a4, ~3;" /* prepare a mask for the EPC */
|
||||||
|
"and a4, a4, %2;" /* apply mask for 32bit aligned base */
|
||||||
|
"l32i a5, a4, 0;" /* load part 1 */
|
||||||
|
"l32i a6, a4, 4;" /* load part 2 */
|
||||||
|
"ssa8l %2;" /* set up shift register for src op */
|
||||||
|
"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 */
|
||||||
|
if (what == L16SI_MATCH && (val & 0x8000))
|
||||||
|
val |= 0xffff0000;
|
||||||
|
|
||||||
|
int regno = (insn & 0x0000f0u) >> 4;
|
||||||
|
if (regno == 1)
|
||||||
|
goto die; /* we can't support loading into a1, just die */
|
||||||
|
else if (regno != 0)
|
||||||
|
--regno; /* account for skipped a1 in exception_frame */
|
||||||
|
|
||||||
|
ef->a_reg[regno] = val; /* carry out the load */
|
||||||
|
ef->epc += 3; /* resume at following instruction */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SDK's user_main function installs a debugging handler regardless
|
||||||
|
* of whether there's a proper handler installed for EXCCAUSE_LOAD_STORE_ERROR,
|
||||||
|
* 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
|
||||||
|
__wrap__xtos_set_exception_handler (uint32_t cause, exception_handler_fn fn)
|
||||||
|
{
|
||||||
|
if (cause != EXCCAUSE_LOAD_STORE_ERROR)
|
||||||
|
__real__xtos_set_exception_handler (cause, fn);
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
#include "c_types.h"
|
||||||
|
#include "rom.h"
|
||||||
|
#include <xtensa/corebits.h>
|
||||||
|
|
||||||
|
void load_non_32_wide_handler (struct exception_frame *ef, uint32_t cause) TEXT_SECTION_ATTR;
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "flash_fs.h"
|
#include "flash_fs.h"
|
||||||
#include "user_interface.h"
|
#include "user_interface.h"
|
||||||
|
#include "user_exceptions.h"
|
||||||
|
|
||||||
#include "ets_sys.h"
|
#include "ets_sys.h"
|
||||||
#include "driver/uart.h"
|
#include "driver/uart.h"
|
||||||
|
@ -25,6 +26,21 @@
|
||||||
#define TASK_QUEUE_LEN 4
|
#define TASK_QUEUE_LEN 4
|
||||||
os_event_t *taskQueue;
|
os_event_t *taskQueue;
|
||||||
|
|
||||||
|
|
||||||
|
/* Note: the trampoline *must* be explicitly put into the .text segment, since
|
||||||
|
* by the time it is invoked the irom has not yet been mapped. This naturally
|
||||||
|
* also goes for anything the trampoline itself calls.
|
||||||
|
*/
|
||||||
|
void user_start_trampoline (void) TEXT_SECTION_ATTR;
|
||||||
|
void user_start_trampoline (void)
|
||||||
|
{
|
||||||
|
__real__xtos_set_exception_handler (
|
||||||
|
EXCCAUSE_LOAD_STORE_ERROR, load_non_32_wide_handler);
|
||||||
|
|
||||||
|
call_user_start ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void task_lua(os_event_t *e){
|
void task_lua(os_event_t *e){
|
||||||
char* lua_argv[] = { (char *)"lua", (char *)"-i", NULL };
|
char* lua_argv[] = { (char *)"lua", (char *)"-i", NULL };
|
||||||
NODE_DBG("Task task_lua started.\n");
|
NODE_DBG("Task task_lua started.\n");
|
||||||
|
|
|
@ -84,6 +84,9 @@ typedef enum {
|
||||||
#define ICACHE_FLASH_ATTR
|
#define ICACHE_FLASH_ATTR
|
||||||
#endif /* ICACHE_FLASH */
|
#endif /* ICACHE_FLASH */
|
||||||
|
|
||||||
|
#define TEXT_SECTION_ATTR __attribute__((section(".text")))
|
||||||
|
#define RAM_CONST_ATTR __attribute__((section(".text")))
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
typedef unsigned char bool;
|
typedef unsigned char bool;
|
||||||
#define BOOL bool
|
#define BOOL bool
|
||||||
|
|
|
@ -19,7 +19,7 @@ PHDRS
|
||||||
|
|
||||||
|
|
||||||
/* Default entry point: */
|
/* Default entry point: */
|
||||||
ENTRY(call_user_start)
|
ENTRY(user_start_trampoline)
|
||||||
PROVIDE(_memmap_vecbase_reset = 0x40000000);
|
PROVIDE(_memmap_vecbase_reset = 0x40000000);
|
||||||
/* Various memory-map dependent cache attribute settings: */
|
/* Various memory-map dependent cache attribute settings: */
|
||||||
_memmap_cacheattr_wb_base = 0x00000110;
|
_memmap_cacheattr_wb_base = 0x00000110;
|
||||||
|
@ -75,6 +75,10 @@ SECTIONS
|
||||||
/* put font and progmem data into irom0 */
|
/* put font and progmem data into irom0 */
|
||||||
*(.u8g_progmem.*)
|
*(.u8g_progmem.*)
|
||||||
|
|
||||||
|
/* Trade some performance for lots of ram. At the time of writing the
|
||||||
|
* available Lua heap went from 18248 to 34704. */
|
||||||
|
*(.rodata*)
|
||||||
|
|
||||||
_irom0_text_end = ABSOLUTE(.);
|
_irom0_text_end = ABSOLUTE(.);
|
||||||
_flash_used_end = ABSOLUTE(.);
|
_flash_used_end = ABSOLUTE(.);
|
||||||
} >irom0_0_seg :irom0_0_phdr
|
} >irom0_0_seg :irom0_0_phdr
|
||||||
|
@ -124,10 +128,7 @@ SECTIONS
|
||||||
.rodata : ALIGN(4)
|
.rodata : ALIGN(4)
|
||||||
{
|
{
|
||||||
_rodata_start = ABSOLUTE(.);
|
_rodata_start = ABSOLUTE(.);
|
||||||
*(.rodata)
|
|
||||||
*(.rodata.*)
|
|
||||||
*(.gnu.linkonce.r.*)
|
*(.gnu.linkonce.r.*)
|
||||||
*(.rodata1)
|
|
||||||
__XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
|
__XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
|
||||||
*(.xt_except_table)
|
*(.xt_except_table)
|
||||||
*(.gcc_except_table)
|
*(.gcc_except_table)
|
||||||
|
|
|
@ -360,6 +360,20 @@ class ELFFile:
|
||||||
self._fetch_symbols()
|
self._fetch_symbols()
|
||||||
return self.symbols[sym]
|
return self.symbols[sym]
|
||||||
|
|
||||||
|
def get_entry_point(self):
|
||||||
|
tool_readelf = "xtensa-lx106-elf-readelf"
|
||||||
|
if os.getenv('XTENSA_CORE')=='lx106':
|
||||||
|
tool_objcopy = "xt-readelf"
|
||||||
|
try:
|
||||||
|
proc = subprocess.Popen([tool_readelf, "-h", self.name], stdout=subprocess.PIPE)
|
||||||
|
except OSError:
|
||||||
|
print "Error calling "+tool_nm+", do you have Xtensa toolchain in PATH?"
|
||||||
|
sys.exit(1)
|
||||||
|
for l in proc.stdout:
|
||||||
|
fields = l.strip().split()
|
||||||
|
if fields[0] == "Entry":
|
||||||
|
return int(fields[3], 0);
|
||||||
|
|
||||||
def load_section(self, section):
|
def load_section(self, section):
|
||||||
tool_objcopy = "xtensa-lx106-elf-objcopy"
|
tool_objcopy = "xtensa-lx106-elf-objcopy"
|
||||||
if os.getenv('XTENSA_CORE')=='lx106':
|
if os.getenv('XTENSA_CORE')=='lx106':
|
||||||
|
@ -586,7 +600,7 @@ if __name__ == '__main__':
|
||||||
args.output = args.input + '-'
|
args.output = args.input + '-'
|
||||||
e = ELFFile(args.input)
|
e = ELFFile(args.input)
|
||||||
image = ESPFirmwareImage()
|
image = ESPFirmwareImage()
|
||||||
image.entrypoint = e.get_symbol_addr("call_user_start")
|
image.entrypoint = e.get_entry_point()
|
||||||
for section, start in ((".text", "_text_start"), (".data", "_data_start"), (".rodata", "_rodata_start")):
|
for section, start in ((".text", "_text_start"), (".data", "_data_start"), (".rodata", "_rodata_start")):
|
||||||
data = e.load_section(section)
|
data = e.load_section(section)
|
||||||
image.add_segment(e.get_symbol_addr(start), data)
|
image.add_segment(e.get_symbol_addr(start), data)
|
||||||
|
|
Loading…
Reference in New Issue