Discuss here different C compiler set ups, and compiling executables for the ESP8266

User avatar
By rhaenel
#23054
cal wrote:just a short node. Since the newer SDK already installs a new vecbase you should be able to modify the nmi vector
without installing a new vecbase.


Guys, thank you for your hints, I appreciate that very much. This is the way I'll try, since I'm planning a project that will (hopefully) last some time, and moving back to an "old" SDK to solve that problem seems too dangerous.

Unfortunately I'm not that familiar with the xtensa architecture - but I'm willing to invest time and effort to get this running, and I'll report back to you.

To help me get started, maybe you could provide me with some information (if you have some at hand) for the following topics? Anything will do, maybe just a short statement, some link to some piece of sourcecode (even in other projects like linux-xtensa or something) where I can learn from:
  • is installing a new vecbase as easy as setting a list of pointers somewhere in memory, and installing it with "wsr.vecbase"?
  • what is the format/layout of that vector table? I've read the Xtensa ISA document on that topic, however it is very generic, do you know what alignment and size the table has in the case we have here (ESP8266/lx106)? At which position would the NMI vector be within the table?
  • Cal, did I understand your hint correctly, if I check the current vecbase and find it already in RAM, I could just save the NMI pointer within the table, redirect it to my code, and write back the old pointer after my stuff?
  • I suppose it would be beneficial to not completely skip the NMI but just "execute it later". Does anyone know if I there is some sort of "interrupt pending" bit that could be set from my code and would immediately trigger the NMI?

Thanks again for your support.

-Roland
User avatar
By cal
#23056 Moin Roland,

This is the output of

Code: Select allxtensa-lx106-elf-objdump -d build/app.out | less


Code: Select allbuild/app.out:     file format elf32-xtensa-le


Disassembly of section .text:

40100000 <_stext>:
40100000:       100000          and     a0, a0, a0
40100003:       ff2140          excw

40100004 <call_user_start>:
40100004:       ffff21          l32r    a2, 40100000 <_stext>
40100007:       13e720          wsr.vecbase     a2
4010000a:       0022c5          call0   40100238 <call_user_start_local>
4010000d:       000000          ill

40100010 <_DebugExceptionVector>:
40100010:       007200          waiti   2
40100013:       fffe46          j       40100010 <_DebugExceptionVector>
        ...

40100020 <_NMIExceptionVector>:
40100020:       13d300          wsr.excsave3    a0
40100023:       000785          call0   4010009c <_NMILevelVector>
        ...

40100030 <_KernelExceptionVector>:
40100030:       004100          break   1, 0
40100033:       fffe46          j       40100030 <_KernelExceptionVector>
        ...

40100050 <_UserExceptionVector>:
40100050:       13d100          wsr.excsave1    a0
40100053:       001085          call0   4010015c <_UserExceptionVector_1>
        ...

40100070 <_DoubleExceptionVector>:
40100070:       004140          break   1, 4
40100073:       fffe46          j       40100070 <_DoubleExceptionVector>


Current SDK sets vecbase at 0x40100000 (IRAM). As you see its not pointers, but code. The offsets are fixed.

I don't know, if you can cause an NMI but you should be able IMHO to set the cpu flags "as if" and then jump to the code.

Cal
User avatar
By jcmvbkbc
#23058
rhaenel wrote:is installing a new vecbase as easy as setting a list of pointers somewhere in memory, and installing it with "wsr.vecbase"?

Not a list of pointers but code for vector handlers must be at specific offsets from what you write to vecbase.

rhaenel wrote:what is the format/layout of that vector table? I've read the Xtensa ISA document on that topic, however it is very generic, do you know what alignment and size the table has in the case we have here (ESP8266/lx106)? At which position would the NMI vector be within the table?

There's no layout fixed by ISA, core designer decides where to put vectors. This information is visible in the core configuration overlay file config/core.h:
Code: Select all#define XCHAL_VECBASE_RESET_VADDR       0x40000000  /* VECBASE reset value */
#define XCHAL_VECBASE_RESET_PADDR       0x40000000
#define XCHAL_RESET_VECBASE_OVERLAP     0

#define XCHAL_RESET_VECTOR0_VADDR       0x50000000
#define XCHAL_RESET_VECTOR0_PADDR       0x50000000
#define XCHAL_RESET_VECTOR1_VADDR       0x40000080
#define XCHAL_RESET_VECTOR1_PADDR       0x40000080
#define XCHAL_RESET_VECTOR_VADDR        0x50000000
#define XCHAL_RESET_VECTOR_PADDR        0x50000000
#define XCHAL_USER_VECOFS               0x00000050
#define XCHAL_USER_VECTOR_VADDR         0x40000050
#define XCHAL_USER_VECTOR_PADDR         0x40000050
#define XCHAL_KERNEL_VECOFS             0x00000030
#define XCHAL_KERNEL_VECTOR_VADDR       0x40000030
#define XCHAL_KERNEL_VECTOR_PADDR       0x40000030
#define XCHAL_DOUBLEEXC_VECOFS          0x00000070
#define XCHAL_DOUBLEEXC_VECTOR_VADDR    0x40000070
#define XCHAL_DOUBLEEXC_VECTOR_PADDR    0x40000070
#define XCHAL_INTLEVEL2_VECOFS          0x00000010
#define XCHAL_INTLEVEL2_VECTOR_VADDR    0x40000010
#define XCHAL_INTLEVEL2_VECTOR_PADDR    0x40000010
#define XCHAL_DEBUG_VECOFS              XCHAL_INTLEVEL2_VECOFS
#define XCHAL_DEBUG_VECTOR_VADDR        XCHAL_INTLEVEL2_VECTOR_VADDR
#define XCHAL_DEBUG_VECTOR_PADDR        XCHAL_INTLEVEL2_VECTOR_PADDR
#define XCHAL_NMI_VECOFS                0x00000020
#define XCHAL_NMI_VECTOR_VADDR          0x40000020
#define XCHAL_NMI_VECTOR_PADDR          0x40000020
#define XCHAL_INTLEVEL3_VECOFS          XCHAL_NMI_VECOFS
#define XCHAL_INTLEVEL3_VECTOR_VADDR    XCHAL_NMI_VECTOR_VADDR
#define XCHAL_INTLEVEL3_VECTOR_PADDR    XCHAL_NMI_VECTOR_PADDR

It lists the default physical and virtual addresses of the vectors (XCHAL_NMI_VECTOR_PADDR, XCHAL_NMI_VECTOR_VADDR) as well as the offset from the vecbase (XCHAL_NMI_VECOFS).
So for lx106 debug interrupt handler goes at offset 0x00000010 from the vecbase, NMI handler goes at 0x00000020, kernel handler goes at 0x00000030, user handler goes at 0x00000050 and double exception handler goes at 0x00000070.

rhaenel wrote:I suppose it would be beneficial to not completely skip the NMI but just "execute it later". Does anyone know if I there is some sort of "interrupt pending" bit that could be set from my code and would immediately trigger the NMI?

There are such bits for software interrupts: you can set and clear them by writing to intset and intclear SRs, but not for hardware-triggered interrupts or NMI. They can only be triggered by hardware.
User avatar
By jcmvbkbc
#23061
cal wrote:you should be able IMHO to set the cpu flags "as if" and then jump to the code.

Once NMI is triggered further NMIs are disabled until return from the handler. AFAIK there's no way to do it in the software, so fake NMI can always be interrupted by real NMI.