diff --git a/cpu/esp8266/vendor/Makefile b/cpu/esp8266/vendor/Makefile new file mode 100644 index 0000000000..4465636f70 --- /dev/null +++ b/cpu/esp8266/vendor/Makefile @@ -0,0 +1,9 @@ +# Add a list of subdirectories, that should also be built: +DIRS += esp +DIRS += xtensa + +ifeq ($(ENABLE_GDBSTUB), 1) + DIRS += esp-gdbstub +endif + +include $(RIOTBASE)/Makefile.base diff --git a/cpu/esp8266/vendor/README.md b/cpu/esp8266/vendor/README.md new file mode 100644 index 0000000000..29084961b6 --- /dev/null +++ b/cpu/esp8266/vendor/README.md @@ -0,0 +1,16 @@ +The subdirectories here contain third-party software components used by the RIOT port for ESP8266. + +### esp + +The files that are part of [esp-open-rtos](https://github.com/SuperHouse/esp-open-rtos.git). The files in this directory are under the copyright of their respective owners. Please note the copyright notice in these files. All of these files are BSD Licensed as described in the file [LICENSE](https://github.com/SuperHouse/esp-open-rtos/blob/master/LICENSE). + +### esp-gdbstub + +The files in this directory are a modified version of [esp-gdbstub](https://github.com/espressif/esp-gdbstub). The files are copyright of Espressif Systems (Shanghai) Pte., Ltd. and are licensed under the Espressif MIT license. + +### espressif + +The files in this directory are either from the [ESP8266_NONOS_SDK](https://github.com/espressif/ESP8266_NONOS_SDK.git) or from the [ESP_RTOS_SDK](https://github.com/espressif/ESP8266_RTOS_SDK.git) for ESP8266. All of these files are copyright of Espressif Systems (Shanghai) Pte., Ltd. Please note the copyright notice in these files. + +### xtensa +The files in this directory are from the [FreeRTOS port for Xtensa](https://github.com/tensilica/freertos) configurable processors and Diamond processors. All of these files are copyright of Cadence Design Systems Inc. and licensed under the MIT license. diff --git a/cpu/esp8266/vendor/esp-gdbstub/License b/cpu/esp8266/vendor/esp-gdbstub/License new file mode 100644 index 0000000000..0d8ccab252 --- /dev/null +++ b/cpu/esp8266/vendor/esp-gdbstub/License @@ -0,0 +1,9 @@ +ESPRESSIF MIT License + +Copyright (c) 2015 + +Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, it is free of charge, to any person obtaining a copy of this software and associated documentation files (the Software, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/cpu/esp8266/vendor/esp-gdbstub/Makefile b/cpu/esp8266/vendor/esp-gdbstub/Makefile new file mode 100644 index 0000000000..30d8b91bf5 --- /dev/null +++ b/cpu/esp8266/vendor/esp-gdbstub/Makefile @@ -0,0 +1,3 @@ +MODULE=esp_gdbstub + +include $(RIOTBASE)/Makefile.base diff --git a/cpu/esp8266/vendor/esp-gdbstub/README.md b/cpu/esp8266/vendor/esp-gdbstub/README.md new file mode 100644 index 0000000000..4aa84302ae --- /dev/null +++ b/cpu/esp8266/vendor/esp-gdbstub/README.md @@ -0,0 +1,69 @@ + +GDBSTUB +======= + +Intro +----- + +While the ESP8266 supports the standard Gnu set of C programming utilities, for now the choice of debuggers +has been limited: there is an attempt at [OpenOCD support](https://github.com/projectgus/openocd), but at +the time of writing, it doesn't support hardware watchpoints and breakpoints yet, and it needs a separate +JTAG adapter connecting to the ESP8266s JTAG pins. As an alternative, [Cesanta](https://www.cesanta.com/) +has implemented a barebones[GDB stub](https://blog.cesanta.com/esp8266-gdb) in their Smart.js solution - +unfortunately, this only supports exception catching and needs some work before you can use it outside of +the Smart.js platform. Moreover, it also does not work with FreeRTOS. + +For internal use, we at Espressif desired a GDB stub that works with FreeRTOS and is a bit more capable, +so we designed our own implementation of it. This stub works both under FreeRTOS as well as the OS-less +SDK and is able to catch exceptions and do backtraces on them, read and write memory, forward [os_]printf +statements to gdb, single-step instructions and set hardware break- and watchpoints. It connects to the +host machine (which runs gdb) using the standard serial connection that's also used for programming. + +In order to be useful the gdbstub has to be used in conjunction with an xtensa-lx106-elf-gdb, for example +as generated by the [esp-open-sdk](https://github.com/pfalcon/esp-open-sdk) project. + +Usage +----- + * Grab the gdbstub project and put the files in a directory called 'gdbstub' in your project. You can do this +either by checking out the Git repo, or adding the Git repo as a submodule to your project if it's already +in Git. + * Modify your Makefile. You'll need to include the gdbstub sources: if your Makefile is structured like the +ones in the Espressif examples, you can add `gdbstub` to the `SUBDIRS` define and `gdbstub/libgdbstub.a` to the +`COMPONENTS_eagle.app.v6` define. Also, you probably want to add `-ggdb` to your compiler flags (`TARGET_LDFLAGS`) +and, if you are debugging, change any optimation flags (-Os, -O2 etc) into `-Og`. Finally, make sure your Makefile +also compiles .S files. + * Configure gdbstub by editting `gdbstub-cfg.h`. There are a bunch of options you can tweak: FreeRTOS or bare SDK, +private exception/breakpoint stack, console redirection to GDB, wait till debugger attachment etc. You can also +configure the options by including the proper -Dwhatever gcc flags in your Makefiles. + * In your user_main.c, add an `#include <../gdbstub/gdbstub.h>` and call `gdbstub_init();` somewhere in user_main. + * Compile and flash your board. + * Run gdb, depending on your configuration immediately after resetting the board or after it has run into +an exception. The easiest way to do it is to use the provided script: xtensa-lx106-elf-gdb -x gdbcmds -b 38400 +Change the '38400' into the baud rate your code uses. You may need to change the gdbcmds script to fit the +configuration of your hardware and build environment. + +Notes +----- + * Using software breakpoints ('br') only works on code that's in RAM. Code in flash can only have a hardware +breakpoint ('hbr'). + * Due to hardware limitations, only one hardware breakpount and one hardware watchpoint are available. + * Pressing control-C to interrupt the running program depends on gdbstub hooking the UART interrupt. +If some code re-hooks this afterwards, gdbstub won't be able to receive characters. If gdbstub handles +the interrupt, the user code will not receive any characters. + * Continuing from an exception is not (yet) supported in FreeRTOS mode. + * The WiFi hardware is designed to be serviced by software periodically. It has some buffers so it +will behave OK when some data comes in while the processor is busy, but these buffers are not infinite. +If the WiFi hardware receives lots of data while the debugger has stopped the CPU, it is bound +to crash. This will happen mostly when working with UDP and/or ICMP; TCP-connections in general will +not send much more data when the other side doesn't send any ACKs. + +License +------- +This gdbstub is licensed under the Espressif MIT license, as described in the License file. + + +Thanks +------ + * Cesanta, for their initial ESP8266 exception handling only gdbstub, + * jcmvbkbc, for providing an incompatible but interesting gdbstub for other Xtensa CPUs, + * Sysprogs (makers of VisualGDB), for their suggestions and bugreports. diff --git a/cpu/esp8266/vendor/esp-gdbstub/gdbcmds b/cpu/esp8266/vendor/esp-gdbstub/gdbcmds new file mode 100644 index 0000000000..61dfdbeda7 --- /dev/null +++ b/cpu/esp8266/vendor/esp-gdbstub/gdbcmds @@ -0,0 +1,8 @@ +file ../ld/esp8266.riot-os.sdk.app.ld +#set remotedebug 1 +set remotelogfile gdb_rsp_logfile.txt +set serial baud 115200 +set remote hardware-breakpoint-limit 1 +set remote hardware-watchpoint-limit 1 +#set debug xtensa 4 +target remote /dev/ttyUSB0 diff --git a/cpu/esp8266/vendor/esp-gdbstub/gdbstub-cfg.h b/cpu/esp8266/vendor/esp-gdbstub/gdbstub-cfg.h new file mode 100644 index 0000000000..849d733220 --- /dev/null +++ b/cpu/esp8266/vendor/esp-gdbstub/gdbstub-cfg.h @@ -0,0 +1,71 @@ +#ifndef GDBSTUB_CFG_H +#define GDBSTUB_CFG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* +Enable this define if you're using the RTOS SDK. It will use a custom exception handler instead of the HAL +and do some other magic to make everything work and compile under FreeRTOS. +*/ +#ifndef GDBSTUB_FREERTOS +#define GDBSTUB_FREERTOS 1 +#endif + +/* +Enable this to make the exception and debugging handlers switch to a private stack. This will use +up 1K of RAM, but may be useful if you're debugging stack or stack pointer corruption problems. It's +normally disabled because not many situations need it. If for some reason the GDB communication +stops when you run into an error in your code, try enabling this. +*/ +#ifndef GDBSTUB_USE_OWN_STACK +#define GDBSTUB_USE_OWN_STACK 0 +#endif + +/* +If this is defined, gdbstub will break the program when you press Ctrl-C in gdb. it does this by +hooking the UART interrupt. Unfortunately, this means receiving stuff over the serial port won't +work for your program anymore. This will fail if your program sets an UART interrupt handler after +the gdbstub_init call. +*/ +#ifndef GDBSTUB_CTRLC_BREAK +#define GDBSTUB_CTRLC_BREAK 1 +#endif + +/* +Enabling this will redirect console output to GDB. This basically means that printf/os_printf output +will show up in your gdb session, which is useful if you use gdb to do stuff. It also means that if +you use a normal terminal, you can't read the printfs anymore. +*/ +#ifndef GDBSTUB_REDIRECT_CONSOLE_OUTPUT +#define GDBSTUB_REDIRECT_CONSOLE_OUTPUT 1 +#endif + +/* +Enable this if you want the GDB stub to wait for you to attach GDB before running. It does this by +breaking in the init routine; use the gdb 'c' command (continue) to start the program. +*/ +#ifndef GDBSTUB_BREAK_ON_INIT +#define GDBSTUB_BREAK_ON_INIT 1 +#endif + +/* +Function attributes for function types. +Gdbstub functions are placed in flash or IRAM using attributes, as defined here. The gdbinit function +(and related) can always be in flash, because it's called in the normal code flow. The rest of the +gdbstub functions can be in flash too, but only if there's no chance of them being called when the +flash somehow is disabled (eg during SPI operations or flash write/erase operations). If the routines +are called when the flash is disabled (eg due to a Ctrl-C at the wrong time), the ESP8266 will most +likely crash. +*/ +#define ATTR_GDBINIT ICACHE_FLASH_ATTR +#ifndef ATTR_GDBFN +#define ATTR_GDBFN +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* GDBSTUB_CFG_H */ diff --git a/cpu/esp8266/vendor/esp-gdbstub/gdbstub-entry.S b/cpu/esp8266/vendor/esp-gdbstub/gdbstub-entry.S new file mode 100644 index 0000000000..8ff28da66e --- /dev/null +++ b/cpu/esp8266/vendor/esp-gdbstub/gdbstub-entry.S @@ -0,0 +1,404 @@ +/****************************************************************************** + * Copyright 2015 Espressif Systems + * + * Description: Assembly routines for the gdbstub + * + * License: ESPRESSIF MIT License + *******************************************************************************/ + + +#include "gdbstub-cfg.h" + +#include +#include +#include + +#define DEBUG_PC (EPC + XCHAL_DEBUGLEVEL) +#define DEBUG_EXCSAVE (EXCSAVE + XCHAL_DEBUGLEVEL) +#define DEBUG_PS (EPS + XCHAL_DEBUGLEVEL) + + +.global gdbstub_savedRegs + +#if GDBSTUB_USE_OWN_STACK +.global gdbstub_exceptionStack +#endif + + .text +.literal_position + + .text + .align 4 + +/* +The savedRegs struct: + uint32_t pc; + uint32_t ps; + uint32_t sar; + uint32_t vpri; + uint32_t a0; + uint32_t a[14]; //a2..a15 + uint32_t litbase; + uint32_t sr176; + uint32_t sr208; + uint32_t a1; + uint32_t reason; +*/ + +/* +This is the debugging exception routine; it's called by the debugging vector + +We arrive here with all regs intact except for a2. The old contents of A2 are saved +into the DEBUG_EXCSAVE special function register. EPC is the original PC. +*/ +gdbstub_debug_exception_entry: +/* + //Minimum no-op debug exception handler, for debug + rsr a2,DEBUG_PC + addi a2,a2,3 + wsr a2,DEBUG_PC + xsr a2, DEBUG_EXCSAVE + rfi XCHAL_DEBUGLEVEL +*/ + +//Save all regs to structure + movi a2, gdbstub_savedRegs + s32i a0, a2, 0x10 + s32i a1, a2, 0x58 + rsr a0, DEBUG_PS + s32i a0, a2, 0x04 + rsr a0, DEBUG_EXCSAVE //was R2 + s32i a0, a2, 0x14 + s32i a3, a2, 0x18 + s32i a4, a2, 0x1c + s32i a5, a2, 0x20 + s32i a6, a2, 0x24 + s32i a7, a2, 0x28 + s32i a8, a2, 0x2c + s32i a9, a2, 0x30 + s32i a10, a2, 0x34 + s32i a11, a2, 0x38 + s32i a12, a2, 0x3c + s32i a13, a2, 0x40 + s32i a14, a2, 0x44 + s32i a15, a2, 0x48 + rsr a0, SAR + s32i a0, a2, 0x08 + rsr a0, LITBASE + s32i a0, a2, 0x4C + rsr a0, 176 + s32i a0, a2, 0x50 + rsr a0, 208 + s32i a0, a2, 0x54 + rsr a0, DEBUGCAUSE + s32i a0, a2, 0x5C + rsr a4, DEBUG_PC + s32i a4, a2, 0x00 + +#if GDBSTUB_USE_OWN_STACK + //Move to our own stack + movi a1, exceptionStack+255*4 +#endif + +//If ICOUNT is -1, disable it by setting it to 0, otherwise we will keep triggering on the same instruction. + rsr a2, ICOUNT + movi a3, -1 + bne a2, a3, noIcountReset + movi a3, 0 + wsr a3, ICOUNT +noIcountReset: + + rsr a2, ps + addi a2, a2, -PS_EXCM_MASK + wsr a2, ps + rsync + +//Call into the C code to do the actual handling. + call0 gdbstub_handle_debug_exception + +DebugExceptionExit: + + rsr a2, ps + addi a2, a2, PS_EXCM_MASK + wsr a2, ps + rsync + + //Restore registers from the gdbstub_savedRegs struct + movi a2, gdbstub_savedRegs + l32i a0, a2, 0x00 + wsr a0, DEBUG_PC +// l32i a0, a2, 0x54 +// wsr a0, 208 + l32i a0, a2, 0x50 + //wsr a0, 176 //Some versions of gcc do not understand this... + .byte 0x00, 176, 0x13 //so we hand-assemble the instruction. + l32i a0, a2, 0x4C + wsr a0, LITBASE + l32i a0, a2, 0x08 + wsr a0, SAR + l32i a15, a2, 0x48 + l32i a14, a2, 0x44 + l32i a13, a2, 0x40 + l32i a12, a2, 0x3c + l32i a11, a2, 0x38 + l32i a10, a2, 0x34 + l32i a9, a2, 0x30 + l32i a8, a2, 0x2c + l32i a7, a2, 0x28 + l32i a6, a2, 0x24 + l32i a5, a2, 0x20 + l32i a4, a2, 0x1c + l32i a3, a2, 0x18 + l32i a0, a2, 0x14 + wsr a0, DEBUG_EXCSAVE //was R2 + l32i a0, a2, 0x04 + wsr a0, DEBUG_PS + l32i a1, a2, 0x58 + l32i a0, a2, 0x10 + + //Read back vector-saved a2 value, put back address of this routine. + movi a2, gdbstub_debug_exception_entry + xsr a2, DEBUG_EXCSAVE + + //All done. Return to where we came from. + rfi XCHAL_DEBUGLEVEL + + + +#if GDBSTUB_FREERTOS +/* +FreeRTOS exception handling code. For some reason or another, we can't just hook the main exception vector: it +seems FreeRTOS uses that for something else too (interrupts). FreeRTOS has its own fatal exception handler, and we +hook that. Unfortunately, that one is called from a few different places (eg directly in the DoubleExceptionVector) +so the precise location of the original register values are somewhat of a mystery when we arrive here... + +As a 'solution', we'll just decode the most common case of the user_fatal_exception_handler being called from +the user exception handler vector: +- excsave1 - orig a0 +- a1: stack frame: + sf+16: orig a1 + sf+8: ps + sf+4: epc + sf+12: orig a0 + sf: magic no? +*/ + .global gdbstub_handle_user_exception + .global gdbstub_user_exception_entry + .align 4 +gdbstub_user_exception_entry: +//Save all regs to structure + movi a0, gdbstub_savedRegs + s32i a1, a0, 0x14 //was a2 + s32i a3, a0, 0x18 + s32i a4, a0, 0x1c + s32i a5, a0, 0x20 + s32i a6, a0, 0x24 + s32i a7, a0, 0x28 + s32i a8, a0, 0x2c + s32i a9, a0, 0x30 + s32i a10, a0, 0x34 + s32i a11, a0, 0x38 + s32i a12, a0, 0x3c + s32i a13, a0, 0x40 + s32i a14, a0, 0x44 + s32i a15, a0, 0x48 + rsr a2, SAR + s32i a2, a0, 0x08 + rsr a2, LITBASE + s32i a2, a0, 0x4C + rsr a2, 176 + s32i a2, a0, 0x50 + rsr a2, 208 + s32i a2, a0, 0x54 + rsr a2, EXCCAUSE + s32i a2, a0, 0x5C + +//Get the rest of the regs from the stack struct + l32i a3, a1, 12 + s32i a3, a0, 0x10 + l32i a3, a1, 16 + s32i a3, a0, 0x58 + l32i a3, a1, 8 + s32i a3, a0, 0x04 + l32i a3, a1, 4 + s32i a3, a0, 0x00 + +#if GDBSTUB_USE_OWN_STACK + movi a1, exceptionStack+255*4 +#endif + + rsr a2, ps + addi a2, a2, -PS_EXCM_MASK + wsr a2, ps + rsync + + call0 gdbstub_handle_user_exception + +UserExceptionExit: + +/* +Okay, from here on, it Does Not Work. There's not really any continuing from an exception in the +FreeRTOS case; there isn't any effort put in reversing the mess the exception code made yet. Maybe this +is still something we need to implement later, if there's any demand for it, or maybe we should modify +FreeRTOS to allow this in the future. (Which will then kill backwards compatibility... hmmm.) +*/ + j UserExceptionExit + + + .global gdbstub_handle_uart_int + .global gdbstub_uart_entry + .align 4 +gdbstub_uart_entry: + //On entry, the stack frame is at SP+16. + //This is a small stub to present that as the first arg to the gdbstub_handle_uart function. + movi a2, 16 + add a2, a2, a1 + movi a3, gdbstub_handle_uart_int + jx a3 + +#endif + + + + .global gdbstub_save_extra_sfrs_for_exception + .align 4 +//The Xtensa OS HAL does not save all the special function register things. This bit of assembly +//fills the gdbstub_savedRegs struct with them. +gdbstub_save_extra_sfrs_for_exception: + movi a2, gdbstub_savedRegs + rsr a3, LITBASE + s32i a3, a2, 0x4C + rsr a3, 176 + s32i a3, a2, 0x50 + rsr a3, 208 + s32i a3, a2, 0x54 + rsr a3, EXCCAUSE + s32i a3, a2, 0x5C + ret + + .global gdbstub_init_debug_entry + .global _DebugExceptionVector + .align 4 +gdbstub_init_debug_entry: +//This puts the following 2 instructions into the debug exception vector: +// xsr a2, DEBUG_EXCSAVE +// jx a2 + movi a2, _DebugExceptionVector + movi a3, 0xa061d220 + s32i a3, a2, 0 + movi a3, 0x00000002 + s32i a3, a2, 4 + +//Tell the just-installed debug vector where to go. + movi a2, gdbstub_debug_exception_entry + wsr a2, DEBUG_EXCSAVE + + ret + + +//Set up ICOUNT register to step one single instruction + .global gdbstub_icount_ena_single_step + .align 4 +gdbstub_icount_ena_single_step: + movi a3, XCHAL_DEBUGLEVEL //Only count steps in non-debug mode + movi a2, -2 + wsr a3, ICOUNTLEVEL + wsr a2, ICOUNT + isync + ret + + +//These routines all assume only one breakpoint and watchpoint is available, which +//is the case for the ESP8266 Xtensa core. + + + .global gdbstub_set_hw_breakpoint +gdbstub_set_hw_breakpoint: + //a2 - addr, a3 - len (unused here) + rsr a4, IBREAKENABLE + bbsi a4, 0, return_w_error + wsr a2, IBREAKA + movi a2, 1 + wsr a2, IBREAKENABLE + isync + movi a2, 1 + ret + + .global gdbstub_del_hw_breakpoint +gdbstub_del_hw_breakpoint: + //a2 - addr + rsr a5, IBREAKENABLE + bbci a5, 0, return_w_error + rsr a3, IBREAKA + bne a3, a2, return_w_error + movi a2,0 + wsr a2, IBREAKENABLE + isync + movi a2, 1 + ret + + .global gdbstub_set_hw_watchpoint + //a2 - addr, a3 - mask, a4 - type (1=read, 2=write, 3=access) +gdbstub_set_hw_watchpoint: + //Check if any of the masked address bits are set. If so, that is an error. + movi a5,0x0000003F + xor a5, a5, a3 + bany a2, a5, return_w_error + //Check if watchpoint already is set + rsr a5, DBREAKC + movi a6, 0xC0000000 + bany a6, a5, return_w_error + //Set watchpoint + wsr a2, DBREAKA + + //Combine type and mask + movi a6, 0x3F + and a3, a3, a6 + slli a4, a4, 30 + or a3, a3, a4 + wsr a3, DBREAKC + +// movi a2, 1 + mov a2, a3 + isync + ret + + + .global gdbstub_del_hw_watchpoint + //a2 - addr +gdbstub_del_hw_watchpoint: + //See if the address matches + rsr a3, DBREAKA + bne a3, a2, return_w_error + //See if the bp actually is set + rsr a3, DBREAKC + movi a2, 0xC0000000 + bnone a3, a2, return_w_error + //Disable bp + movi a2,0 + wsr a2,DBREAKC + movi a2,1 + isync + ret + +return_w_error: + movi a2, 0 + ret + + +//Breakpoint, with an attempt at a functional function prologue and epilogue... + .global gdbstub_do_break_breakpoint_addr + .global gdbstub_do_break + .align 4 +gdbstub_do_break: + addi a1, a1, -16 + s32i a15, a1, 12 + mov a15, a1 + +gdbstub_do_break_breakpoint_addr: + break 0,0 + + mov a1, a15 + l32i a15, a1, 12 + addi a1, a1, 16 + ret diff --git a/cpu/esp8266/vendor/esp-gdbstub/gdbstub-entry.h b/cpu/esp8266/vendor/esp-gdbstub/gdbstub-entry.h new file mode 100644 index 0000000000..cecee2ad8e --- /dev/null +++ b/cpu/esp8266/vendor/esp-gdbstub/gdbstub-entry.h @@ -0,0 +1,25 @@ +#ifndef GDBSTUB_ENTRY_H +#define GDBSTUB_ENTRY_H + +#ifdef __cplusplus +extern "C" { +#endif + +void gdbstub_init_debug_entry(void); +void gdbstub_do_break(void); +void gdbstub_icount_ena_single_step(void); +void gdbstub_save_extra_sfrs_for_exception(void); +void gdbstub_uart_entry(void); + +int gdbstub_set_hw_breakpoint(int addr, int len); +int gdbstub_set_hw_watchpoint(int addr, int len, int type); +int gdbstub_del_hw_breakpoint(int addr); +int gdbstub_del_hw_watchpoint(int addr); + +extern void* gdbstub_do_break_breakpoint_addr; + +#ifdef __cplusplus +} +#endif + +#endif /* GDBSTUB_ENTRY_H */ diff --git a/cpu/esp8266/vendor/esp-gdbstub/gdbstub.c b/cpu/esp8266/vendor/esp-gdbstub/gdbstub.c new file mode 100644 index 0000000000..5c80cdfdb1 --- /dev/null +++ b/cpu/esp8266/vendor/esp-gdbstub/gdbstub.c @@ -0,0 +1,766 @@ +/****************************************************************************** + * Copyright 2015 Espressif Systems + * + * Description: A stub to make the ESP8266 debuggable by GDB over the serial + * port. + * + * License: ESPRESSIF MIT License + *******************************************************************************/ + +#include + +#include "gdbstub.h" +#include "ets_sys.h" +#include "eagle_soc.h" +#include "c_types.h" +#include "gpio.h" +#include "xtensa/corebits.h" + +#include "gdbstub.h" +#include "gdbstub-entry.h" +#include "gdbstub-cfg.h" + +// From xtruntime-frames.h +struct XTensa_exception_frame_s { + uint32_t pc; + uint32_t ps; + uint32_t sar; + uint32_t vpri; + uint32_t a0; + uint32_t a[14]; //a2..a15 + // These are added manually by the exception code; the HAL doesn't + // set these on an exception. + uint32_t litbase; + uint32_t sr176; + uint32_t sr208; + uint32_t a1; + // 'reason' is abused for both the debug and the exception vector: if bit 7 is set, + // this contains an exception reason, otherwise it contains a debug vector bitmap. + uint32_t reason; +}; + + +struct XTensa_rtos_int_frame_s { + uint32_t exitPtr; + uint32_t pc; + uint32_t ps; + uint32_t a[16]; + uint32_t sar; +}; + +// OS-less SDK defines. Defines some headers for things that aren't in the +// include files, plus the xthal stack frame struct. +#include "sdk/sdk.h" + +#define EXCEPTION_GDB_SP_OFFSET 0x100 + +//We need some UART register defines. +#define ETS_UART_INUM 5 +#define REG_UART_BASE( i ) (0x60000000+(i)*0xf00) +#define UART_STATUS( i ) (REG_UART_BASE( i ) + 0x1C) +#define UART_RXFIFO_CNT 0x000000FF +#define UART_RXFIFO_CNT_S 0 +#define UART_TXFIFO_CNT 0x000000FF +#define UART_TXFIFO_CNT_S 16 +#define UART_FIFO( i ) (REG_UART_BASE( i ) + 0x0) +#define UART_INT_ENA(i) (REG_UART_BASE(i) + 0xC) +#define UART_INT_CLR(i) (REG_UART_BASE(i) + 0x10) +#define UART_RXFIFO_TOUT_INT_ENA (BIT(8)) +#define UART_RXFIFO_FULL_INT_ENA (BIT(0)) +#define UART_RXFIFO_TOUT_INT_CLR (BIT(8)) +#define UART_RXFIFO_FULL_INT_CLR (BIT(0)) + +// Length of buffer used to reserve GDB commands. Has to be at least able to +// fit the G command, which implies a minimum size of about 190 bytes. +#define PBUFLEN 256 +// Length of gdb stdout buffer, for console redirection +#define OBUFLEN 32 + +// The asm stub saves the Xtensa registers here when a debugging exception +// happens. +struct XTensa_exception_frame_s gdbstub_savedRegs; +#if GDBSTUB_USE_OWN_STACK +// This is the debugging exception stack. +int exceptionStack[256]; +#endif + +static unsigned char cmd[PBUFLEN]; // GDB command input buffer +static char chsum; // Running checksum of the output packet +#if GDBSTUB_REDIRECT_CONSOLE_OUTPUT +static unsigned char obuf[OBUFLEN]; // GDB stdout buffer +static int obufpos=0; // Current position in the buffer +#endif +static int32_t singleStepPs = -1; // Stores ps when single-stepping + // instruction. -1 when not in use. + +// Small function to feed the hardware watchdog. Needed to stop the ESP from +// resetting due to a watchdog timeout while reading a command. +static void ATTR_GDBFN keepWDTalive(void) +{ + uint64_t *wdtval = (uint64_t*)0x3ff21048; + uint64_t *wdtovf = (uint64_t*)0x3ff210cc; + int *wdtctl = (int*)0x3ff210c8; + *wdtovf = *wdtval+1600000; + *wdtctl |= (1 << 31); +} + +// Receive a char from the uart. Uses polling and feeds the watchdog. +static int ATTR_GDBFN gdbRecvChar(void) +{ + int i; + while (((READ_PERI_REG(UART_STATUS(0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT)==0) + keepWDTalive(); + i = READ_PERI_REG(UART_FIFO(0)); + return i; +} + +// Send a char to the uart. +static void ATTR_GDBFN gdbSendChar(char c) +{ + while (((READ_PERI_REG(UART_STATUS(0)) >> UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=126) + ; + WRITE_PERI_REG(UART_FIFO(0), c); +} + +// Send the start of a packet; reset checksum calculation. +static void ATTR_GDBFN gdbPacketStart(void) +{ + chsum=0; + gdbSendChar('$'); +} + +// Send a char as part of a packet +static void ATTR_GDBFN gdbPacketChar(char c) +{ + if (c == '#' || c == '$' || c == '}' || c == '*') + { + gdbSendChar('}'); + gdbSendChar(c ^ 0x20); + chsum += (c ^ 0x20) +'}'; + } + else + { + gdbSendChar(c); + chsum += c; + } +} + +// Send a string as part of a packet +static void ATTR_GDBFN gdbPacketStr(char *c) +{ + while (*c != 0) + { + gdbPacketChar(*c); + c++; + } +} + +// Send a hex val as part of a packet. 'bits'/4 dictates the number of hex chars sent. +static void ATTR_GDBFN gdbPacketHex(int val, int bits) +{ + char hexChars[]="0123456789abcdef"; + int i; + for (i = bits; i > 0; i -= 4) + gdbPacketChar(hexChars[(val >> (i-4)) & 0xf]); +} + +// Finish sending a packet. +static void ATTR_GDBFN gdbPacketEnd(void) +{ + gdbSendChar('#'); + gdbPacketHex(chsum, 8); +} + +// Error states used by the routines that grab stuff from the incoming gdb packet +#define ST_ENDPACKET -1 +#define ST_ERR -2 +#define ST_OK -3 +#define ST_CONT -4 + +// Grab a hex value from the gdb packet. Ptr will get positioned on the end +// of the hex string, as far as the routine has read into it. Bits/4 indicates +// the max amount of hex chars it gobbles up. Bits can be -1 to eat up as much +// hex chars as possible. +static long ATTR_GDBFN gdbGetHexVal(unsigned char **ptr, int bits) { + int i; + int no; + unsigned int v=0; + no=bits/4; + if (bits==-1) no=64; + for (i=0; i='0' && c<='9') { + v <<= 4; + v|=(c-'0'); + } else if (c>='A' && c<='F') { + v <<= 4; + v|=(c-'A')+10; + } else if (c>='a' && c<='f') { + v <<= 4; + v|=(c-'a')+10; + } else if (c=='#') { + if (bits==-1) { + (*ptr)--; + return v; + } + return ST_ENDPACKET; + } else { + if (bits==-1) { + (*ptr)--; + return v; + } + return ST_ERR; + } + } + return v; +} + +// Swap an int into the form gdb wants it +static int ATTR_GDBFN iswap(int i) +{ + int r; + r = ((i >> 24) & 0xff); + r |= ((i >> 16) & 0xff) << 8; + r |= ((i >> 8) & 0xff) << 16; + r |= ((i >> 0) & 0xff) << 24; + return r; +} + +// Read a byte from the ESP8266 memory. +static unsigned char ATTR_GDBFN readbyte(unsigned int p) +{ + int *i = (int*)(p & (~3)); + if (p < 0x20000000 || p >= 0x60000000) + return -1; + return *i >> ((p & 3) * 8); +} + +// Write a byte to the ESP8266 memory. +static void ATTR_GDBFN writeByte(unsigned int p, unsigned char d) +{ + int *i = (int*)(p & (~3)); + if (p < 0x20000000 || p >= 0x60000000) return; + if ((p & 3) == 0) *i = (*i & 0xffffff00) | (d << 0); + if ((p & 3) == 1) *i = (*i & 0xffff00ff) | (d << 8); + if ((p & 3) == 2) *i = (*i & 0xff00ffff) | (d << 16); + if ((p & 3) == 3) *i = (*i & 0x00ffffff) | (d << 24); +} + +// Returns 1 if it makes sense to write to addr p +static int ATTR_GDBFN validWrAddr(int p) +{ + if (p >= 0x3ff00000 && p < 0x40000000) return 1; + if (p >= 0x40100000 && p < 0x40140000) return 1; + if (p >= 0x60000000 && p < 0x60002000) return 1; + return 0; +} + +/* +Register file in the format lx106 gdb port expects it. +Inspired by gdb/regformats/reg-xtensa.dat from +https://github.com/jcmvbkbc/crosstool-NG/blob/lx106-g%2B%2B/overlays/xtensa_lx106.tar +As decoded by Cesanta. +*/ +struct regfile +{ + uint32_t a[16]; + uint32_t pc; + uint32_t sar; + uint32_t litbase; + uint32_t sr176; + uint32_t sr208; + uint32_t ps; +}; + + +//Send the reason execution is stopped to GDB. +static void ATTR_GDBFN sendReason(void) +{ + #if 0 + char *reason=""; //default + #endif + gdbPacketStart(); + gdbPacketChar('T'); + if (gdbstub_savedRegs.reason == 0xff) + { + gdbPacketHex(2, 8); //sigint + } + else if (gdbstub_savedRegs.reason & 0x80) + { + // exception-to-signal mapping + char exceptionSignal[] = { 4, 31, 11, 11, 2, 6 , 8, 0, 6, 7, 0, 0, 7, 7, 7, 7}; + unsigned int i=0; + // We stopped because of an exception. + // Convert exception code to a signal number and send it. + i = gdbstub_savedRegs.reason & 0x7f; + if (i < sizeof(exceptionSignal)) + gdbPacketHex(exceptionSignal[i], 8); + else + gdbPacketHex(11, 8); + } + else + { + // We stopped because of a debugging exception. + gdbPacketHex(5, 8); //sigtrap + // Current Xtensa GDB versions don't seem to request this, so let's + // leave it off. + #if 0 + if (gdbstub_savedRegs.reason&(1 << 0)) reason="break"; + if (gdbstub_savedRegs.reason&(1 << 1)) reason="hwbreak"; + if (gdbstub_savedRegs.reason&(1 << 2)) reason="watch"; + if (gdbstub_savedRegs.reason&(1 << 3)) reason="swbreak"; + if (gdbstub_savedRegs.reason&(1 << 4)) reason="swbreak"; + + gdbPacketStr(reason); + gdbPacketChar(':'); + //ToDo: watch: send address + #endif + } + gdbPacketEnd(); +} + +// Handle a command as received from GDB. +static int ATTR_GDBFN gdbHandleCommand(unsigned char *cmd, int len) +{ + // Handle a command + int i, j, k; + unsigned char *data=cmd+1; + if (cmd[0] == 'g') + { // send all registers to gdb + gdbPacketStart(); + gdbPacketHex(iswap(gdbstub_savedRegs.a0), 32); + gdbPacketHex(iswap(gdbstub_savedRegs.a1), 32); + for (i = 2; i < 16; i++) + gdbPacketHex(iswap(gdbstub_savedRegs.a[i-2]), 32); + gdbPacketHex(iswap(gdbstub_savedRegs.pc), 32); + gdbPacketHex(iswap(gdbstub_savedRegs.sar), 32); + gdbPacketHex(iswap(gdbstub_savedRegs.litbase), 32); + gdbPacketHex(iswap(gdbstub_savedRegs.sr176), 32); + gdbPacketHex(0, 32); + gdbPacketHex(iswap(gdbstub_savedRegs.ps), 32); + gdbPacketEnd(); + } + else if (cmd[0]=='G') + { //receive content for all registers from gdb + gdbstub_savedRegs.a0 = iswap(gdbGetHexVal(&data, 32)); + gdbstub_savedRegs.a1 = iswap(gdbGetHexVal(&data, 32)); + for (i = 2; i < 16; i++) + gdbstub_savedRegs.a[i-2]=iswap(gdbGetHexVal(&data, 32)); + gdbstub_savedRegs.pc = iswap(gdbGetHexVal(&data, 32)); + gdbstub_savedRegs.sar = iswap(gdbGetHexVal(&data, 32)); + gdbstub_savedRegs.litbase = iswap(gdbGetHexVal(&data, 32)); + gdbstub_savedRegs.sr176 = iswap(gdbGetHexVal(&data, 32)); + gdbGetHexVal(&data, 32); + gdbstub_savedRegs.ps = iswap(gdbGetHexVal(&data, 32)); + gdbPacketStart(); + gdbPacketStr("OK"); + gdbPacketEnd(); + } + else if (cmd[0]=='m') { //read memory to gdb + i=gdbGetHexVal(&data, -1); + data++; + j=gdbGetHexVal(&data, -1); + gdbPacketStart(); + for (k=0; k=PBUFLEN) return ST_ERR; + } + //A # has been received. Get and check the received chsum. + sentchs[0]=gdbRecvChar(); + sentchs[1]=gdbRecvChar(); + ptr=&sentchs[0]; + rchsum=gdbGetHexVal(&ptr, 8); +// ets_printf("c %x r %x\n", chsum, rchsum); + if (rchsum!=chsum) { + gdbSendChar('-'); + return ST_ERR; + } else { + gdbSendChar('+'); + return gdbHandleCommand(cmd, p); + } +} + +//Get the value of one of the A registers +static unsigned int ATTR_GDBFN getaregval(int reg) { + if (reg==0) return gdbstub_savedRegs.a0; + if (reg==1) return gdbstub_savedRegs.a1; + return gdbstub_savedRegs.a[reg-2]; +} + +//Set the value of one of the A registers +static void ATTR_GDBFN setaregval(int reg, unsigned int val) { + ets_printf("%x -> %x\n", val, reg); + if (reg==0) gdbstub_savedRegs.a0=val; + if (reg==1) gdbstub_savedRegs.a1=val; + gdbstub_savedRegs.a[reg-2]=val; +} + +//Emulate the l32i/s32i instruction we're stopped at. +static void ATTR_GDBFN emulLdSt(void) { + unsigned char i0=readbyte(gdbstub_savedRegs.pc); + unsigned char i1=readbyte(gdbstub_savedRegs.pc+1); + unsigned char i2=readbyte(gdbstub_savedRegs.pc+2); + int *p; + if ((i0 & 0xf)==2 && (i1 & 0xf0)==0x20) { + //l32i + p=(int*)getaregval(i1 & 0xf)+(i2*4); + setaregval(i0 >> 4, *p); + gdbstub_savedRegs.pc+=3; + } else if ((i0 & 0xf)==0x8) { + //l32i.n + p=(int*)getaregval(i1 & 0xf)+((i1 >> 4)*4); + setaregval(i0 >> 4, *p); + gdbstub_savedRegs.pc+=2; + } else if ((i0 & 0xf)==2 && (i1 & 0xf0)==0x60) { + //s32i + p=(int*)getaregval(i1 & 0xf)+(i2*4); + *p=getaregval(i0 >> 4); + gdbstub_savedRegs.pc+=3; + } else if ((i0 & 0xf)==0x9) { + //s32i.n + p=(int*)getaregval(i1 & 0xf)+((i1 >> 4)*4); + *p=getaregval(i0 >> 4); + gdbstub_savedRegs.pc+=2; + } else { + ets_printf("GDBSTUB: No l32i/s32i instruction: %x %x %x. Huh?", i2, i1, i0); + } +} + +// We just caught a debug exception and need to handle it. This is called +// from an assembly routine in gdbstub-entry.S +void ATTR_GDBFN gdbstub_handle_debug_exception(void) +{ + ets_wdt_disable(); + + if (singleStepPs != -1) + { + // We come here after single-stepping an instruction. Interrupts are + // disabled for the single step. Re-enable them here. + gdbstub_savedRegs.ps = (gdbstub_savedRegs.ps & ~0xf) | (singleStepPs & 0xf); + singleStepPs = -1; + } + + sendReason(); + while (gdbReadCommand()!=ST_CONT) + ; + + if ((gdbstub_savedRegs.reason & 0x84) == 0x4) + { + //We stopped due to a watchpoint. We can't re-execute the current instruction + //because it will happily re-trigger the same watchpoint, so we emulate it + //while we're still in debugger space. + emulLdSt(); + } else if ((gdbstub_savedRegs.reason & 0x88)==0x8) { + //We stopped due to a BREAK instruction. Skip over it. + //Check the instruction first; gdb may have replaced it with the original instruction + //if it's one of the breakpoints it set. + if (readbyte(gdbstub_savedRegs.pc+2)==0 && + (readbyte(gdbstub_savedRegs.pc+1) & 0xf0)==0x40 && + (readbyte(gdbstub_savedRegs.pc) & 0x0f)==0x00) { + gdbstub_savedRegs.pc+=3; + } + } else if ((gdbstub_savedRegs.reason & 0x90)==0x10) { + //We stopped due to a BREAK.N instruction. Skip over it, after making sure the instruction + //actually is a BREAK.N + if ((readbyte(gdbstub_savedRegs.pc+1) & 0xf0)==0xf0 && + readbyte(gdbstub_savedRegs.pc)==0x2d) { + gdbstub_savedRegs.pc+=3; + } + } + ets_wdt_enable(); +} + + +#ifdef MODULE_ESP_SDK_INT_HANDLING + +// Non-OS exception handler. Gets called by the Xtensa HAL. +static void ATTR_GDBFN gdb_exception_handler (void* arg) +{ + struct XTensa_exception_frame_s* frame = (struct XTensa_exception_frame_s*)arg; + + // Save the extra registers the Xtensa HAL doesn't save + gdbstub_save_extra_sfrs_for_exception(); + + // Copy registers the Xtensa HAL did save to gdbstub_savedRegs + ets_memcpy(&gdbstub_savedRegs, frame, 19*4); + + // Credits go to Cesanta for this trick. A1 seems to be destroyed, but because it + // has a fixed offset from the address of the passed frame, we can recover it. + gdbstub_savedRegs.a1 = (uint32_t)frame + EXCEPTION_GDB_SP_OFFSET; + + gdbstub_savedRegs.reason |= 0x80; //mark as an exception reason + + ets_wdt_disable(); + sendReason(); + while (gdbReadCommand() != ST_CONT) + ; + ets_wdt_enable(); + + // Copy any changed registers back to the frame the Xtensa HAL uses. + ets_memcpy(frame, &gdbstub_savedRegs, 19*4); +} + +#else +/* TODO +static void ATTR_GDBFN gdb_exception_handler (XtExcFrame *frame) +{ + ets_printf("GDB EXCEPTION\n"); + while (1) ; +} +*/ +#endif // MODULE_ESP_SDK_INT_HANDLING + + +#if GDBSTUB_REDIRECT_CONSOLE_OUTPUT +// Replacement putchar1 routine. Instead of spitting out the character +// directly, it will buffer up to OBUFLEN characters (or up to a \n, +// whichever comes earlier) and send it out as a gdb stdout packet. +static void ATTR_GDBFN gdb_semihost_putchar1(char c) +{ + obuf[obufpos++]=c; + if (c=='\n' || obufpos==OBUFLEN) + { + int i; + gdbPacketStart(); + gdbPacketChar('O'); + for (i=0; i> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT; + while (fifolen!=0) + { + //Check if any of the chars is control-C. Throw away rest. + if ((READ_PERI_REG(UART_FIFO(0)) & 0xFF)==0x3) + doDebug=1; + fifolen--; + } + WRITE_PERI_REG(UART_INT_CLR(0), UART_RXFIFO_FULL_INT_CLR|UART_RXFIFO_TOUT_INT_CLR); + + if (doDebug) + { + // Copy registers the Xtensa HAL did save to gdbstub_savedRegs + ets_memcpy(&gdbstub_savedRegs, frame, 19*4); + gdbstub_savedRegs.a1=(uint32_t)frame+EXCEPTION_GDB_SP_OFFSET; + + //mark as user break reason + gdbstub_savedRegs.reason=0xff; + + ets_wdt_disable(); + sendReason(); + while(gdbReadCommand()!=ST_CONT); + ets_wdt_enable(); + // Copy any changed registers back to the frame the Xtensa HAL uses. + ets_memcpy(frame, &gdbstub_savedRegs, 19*4); + } +} + +static void ATTR_GDBINIT install_uart_hdlr(void) +{ + ets_isr_attach(ETS_UART_INUM, (ets_isr_t)uart_hdlr, NULL); + SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA); + // enable uart interrupt + ets_isr_unmask((1 << ETS_UART_INUM)); +} + +#endif // GDBSTUB_CTRLC_BREAK + +// gdbstub initialization routine. +void ATTR_GDBINIT gdbstub_init(void) +{ + #if GDBSTUB_REDIRECT_CONSOLE_OUTPUT + ets_install_putc1(gdb_semihost_putchar1); + #endif + + #if GDBSTUB_CTRLC_BREAK + install_uart_hdlr(); + #endif + + install_exceptions(); + gdbstub_init_debug_entry(); + + #if GDBSTUB_BREAK_ON_INIT + gdbstub_do_break(); + #endif +} diff --git a/cpu/esp8266/vendor/esp-gdbstub/gdbstub.h b/cpu/esp8266/vendor/esp-gdbstub/gdbstub.h new file mode 100644 index 0000000000..d9e8b4a094 --- /dev/null +++ b/cpu/esp8266/vendor/esp-gdbstub/gdbstub.h @@ -0,0 +1,14 @@ +#ifndef GDBSTUB_H +#define GDBSTUB_H + +#ifdef __cplusplus +extern "C" { +#endif + +void gdbstub_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* GDBSTUB_H */ diff --git a/cpu/esp8266/vendor/esp/FreeRTOS.h b/cpu/esp8266/vendor/esp/FreeRTOS.h new file mode 100644 index 0000000000..64c2b8225d --- /dev/null +++ b/cpu/esp8266/vendor/esp/FreeRTOS.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + * + * FreeRTOS to RIOT-OS adaption module + */ + +#ifndef FREERTOS_H +#define FREERTOS_H + +#ifndef DOXYGEN + +#include "stdlib.h" + +#include "mutex.h" +#include "irq.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SemaphoreHandle_t mutex_t* + +static inline SemaphoreHandle_t xSemaphoreCreateMutex(void) +{ + mutex_t* _tmp = malloc (sizeof(mutex_t)); + mutex_init(_tmp); + return _tmp; +} + +#define xSemaphoreTake(s,to) mutex_lock(s) +#define xSemaphoreGive(s) mutex_unlock(s) + +#define vPortEnterCritical() int _irq_state = irq_disable () +#define vPortExitCritical() irq_restore(_irq_state) + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* FREERTOS_H */ diff --git a/cpu/esp8266/vendor/esp/LICENSE b/cpu/esp8266/vendor/esp/LICENSE new file mode 100644 index 0000000000..08d96c4a59 --- /dev/null +++ b/cpu/esp8266/vendor/esp/LICENSE @@ -0,0 +1,12 @@ +Copyright (c) 2015, SuperHouse Automation 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: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. diff --git a/cpu/esp8266/vendor/esp/Makefile b/cpu/esp8266/vendor/esp/Makefile new file mode 100644 index 0000000000..5db2d2121c --- /dev/null +++ b/cpu/esp8266/vendor/esp/Makefile @@ -0,0 +1,3 @@ +MODULE=esp + +include $(RIOTBASE)/Makefile.base diff --git a/cpu/esp8266/vendor/esp/README.md b/cpu/esp8266/vendor/esp/README.md new file mode 100644 index 0000000000..bf5deb40d3 --- /dev/null +++ b/cpu/esp8266/vendor/esp/README.md @@ -0,0 +1,3 @@ +All files in this directory are part of [esp-open-rtos](https://github.com/SuperHouse/esp-open-rtos.git). They are under the copyright of their respective owners. Please note the copyright notice in these files. + +All of these files are BSD Licensed as described in the file [LICENSE](https://github.com/SuperHouse/esp-open-rtos/blob/master/LICENSE). diff --git a/cpu/esp8266/vendor/esp/common_macros.h b/cpu/esp8266/vendor/esp/common_macros.h new file mode 100644 index 0000000000..d14c34639c --- /dev/null +++ b/cpu/esp8266/vendor/esp/common_macros.h @@ -0,0 +1,145 @@ +/* Some common compiler macros + * + * Not esp8266-specific. + * + * Part of esp-open-rtos + * Copyright (C) 2015 Superhouse Automation Pty Ltd + * BSD Licensed as described in the file LICENSE + */ + +/* +Copyright (c) 2015, SuperHouse Automation 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: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef COMMON_MACROS_H +#define COMMON_MACROS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define UNUSED __attributed((unused)) + +#ifndef BIT +#define BIT(X) (1<<(X)) +#endif + +/* These macros convert values to/from bitfields specified by *_M and *_S (mask + * and shift) constants. Used primarily with ESP8266 register access. + */ + +#define VAL2FIELD(fieldname, value) ((value) << fieldname##_S) +#define FIELD2VAL(fieldname, regbits) (((regbits) >> fieldname##_S) & fieldname##_M) + +#define FIELD_MASK(fieldname) (fieldname##_M << fieldname##_S) +#define SET_FIELD(regbits, fieldname, value) (((regbits) & ~FIELD_MASK(fieldname)) | VAL2FIELD(fieldname, value)) + +/* VAL2FIELD/SET_FIELD do not normally check to make sure that the passed value + * will fit in the specified field (without clobbering other bits). This makes + * them faster and is usually fine. If you do need to make sure that the value + * will not overflow the field, use VAL2FIELD_M or SET_FIELD_M (which will + * first mask the supplied value to only the allowed number of bits) instead. + */ +#define VAL2FIELD_M(fieldname, value) (((value) & fieldname##_M) << fieldname##_S) +#define SET_FIELD_M(regbits, fieldname, value) (((regbits) & ~FIELD_MASK(fieldname)) | VAL2FIELD_M(fieldname, value)) + +/* Set bits in reg with specified mask. + */ +#define SET_MASK_BITS(reg, mask) (reg) |= (mask) + +/* Clear bits in reg with specified mask + */ +#define CLEAR_MASK_BITS(reg, mask) (reg) &= ~(mask) + +/* Use the IRAM macro to place functions into Instruction RAM (IRAM) + instead of flash (aka irom). + + (This is the opposite to the Espressif SDK, where functions default + to being placed in IRAM but the ICACHE_FLASH_ATTR attribute will + place them in flash.) + + Use the IRAM attribute for functions which are called when the + flash may not be available (for example during NMI exceptions), or + for functions which are called very frequently and need high + performance. + + Usage example: + + void IRAM high_performance_function(void) + { + // do important thing here + } + + Bear in mind IRAM is limited (32KB), compared to up to 1MB of flash. +*/ +#define IRAM __attribute__((section(".iram1.text"))) + +/* Use the RAM macro to place constant data (rodata) into RAM (data + RAM) instead of the default placement in flash. This is useful for + constant data which needs high performance access. + + Usage example: + + const RAM uint8_t constants[] = { 1, 2, 3, 7 }; + + When placing string literals in RAM, they need to be declared with + the type "const char[]" not "const char *" + + Usage example: + + const RAM char hello_world[] = "Hello World"; +*/ +#define RAM __attribute__((section(".data"))) + +/* Use the IRAM_DATA macro to place data into Instruction RAM (IRAM) + instead of the default of flash (for constant data) or data RAM + (for non-constant data). + + This may be useful to free up data RAM. However all data read from + any instruction space (either IRAM or Flash) must be 32-bit aligned + word reads. Reading unaligned data stored with IRAM_DATA will be + slower than reading data stored in RAM. You can't perform unaligned + writes to IRAM. +*/ +#define IRAM_DATA __attribute__((section(".iram1.data"))) + +/* Use the IROM macro to store constant values in IROM flash. In + esp-open-rtos this is already the default location for most constant + data (rodata), so you don't need this attribute in 99% of cases. + + The exceptions are to mark data in the core & freertos libraries, + where the default for constant data storage is RAM. + + (Unlike the Espressif SDK you don't need to use an attribute like + ICACHE_FLASH_ATTR for functions, they go into flash by default.) + + Important to note: IROM flash is accessed via 32-bit word aligned + reads. esp-open-rtos does some magic to "fix" unaligned reads, but + performance is reduced. +*/ +#ifdef __cplusplus + #define IROM __attribute__((section(".irom0.text"))) + #define IROM_LIT __attribute__((section(".irom0.literal"))) +#else + #define IROM __attribute__((section(".irom0.text"))) + #define IROM_LIT __attribute__((section(".irom0.literal"))) const +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* COMMON_MACROS_H */ diff --git a/cpu/esp8266/vendor/esp/dport_regs.h b/cpu/esp8266/vendor/esp/dport_regs.h new file mode 100644 index 0000000000..79769b61b9 --- /dev/null +++ b/cpu/esp8266/vendor/esp/dport_regs.h @@ -0,0 +1,155 @@ +/* esp/dport_regs.h + * + * ESP8266 DPORT0 register definitions + * + * Not compatible with ESP SDK register access code. + */ + +/* +Copyright (c) 2015, SuperHouse Automation 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: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef DPORT_REGS_H +#define DPORT_REGS_H + +#ifndef DOXYGEN + +#include "esp/types.h" +#include "common_macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define DPORT_BASE 0x3ff00000 +#define DPORT (*(struct DPORT_REGS *)(DPORT_BASE)) + +/* DPORT registers + + Control various aspects of core/peripheral interaction... Not well + documented or understood. +*/ + +struct DPORT_REGS { + uint32_t volatile DPORT0; // 0x00 FIXME: need a better name for this + uint32_t volatile INT_ENABLE; // 0x04 + uint32_t volatile _unknown08; // 0x08 + uint32_t volatile SPI_READY; // 0x0c + uint32_t volatile _unknown10; // 0x10 + uint32_t volatile CPU_CLOCK; // 0x14 + uint32_t volatile CLOCKGATE_WATCHDOG; // 0x18 + uint32_t volatile _unknown1c; // 0x1c + uint32_t volatile SPI_INT_STATUS; // 0x20 + uint32_t volatile SPI_CACHE_RAM; // 0x24 + uint32_t volatile PERI_IO; // 0x28 + uint32_t volatile SLC_TX_DESC_DEBUG; // 0x2c + uint32_t volatile _unknown30; // 0x30 + uint32_t volatile _unknown34; // 0x34 + uint32_t volatile _unknown38; // 0x38 + uint32_t volatile _unknown3c; // 0x3c + uint32_t volatile _unknown40; // 0x40 + uint32_t volatile _unknown44; // 0x44 + uint32_t volatile _unknown48; // 0x48 + uint32_t volatile _unknown4c; // 0x4c + uint32_t volatile OTP_MAC0; // 0x50 + uint32_t volatile OTP_MAC1; // 0x54 + uint32_t volatile OTP_CHIPID; // 0x58 + uint32_t volatile OTP_MAC2; // 0x5c +}; + +_Static_assert(sizeof(struct DPORT_REGS) == 0x60, "DPORT_REGS is the wrong size"); + +/* Details for DPORT0 register */ + +/* Currently very little known about this register. The following is based on analysis of the startup code in the Espressif SDK: */ + +#define DPORT_DPORT0_FIELD0_M 0x0000001f +#define DPORT_DPORT0_FIELD0_S 0 + +/* Details for INT_ENABLE register */ + +/* Set flags to enable CPU interrupts from some peripherals. Read/write. + + bit 0 - INT_ENABLE_WDT (unclear exactly how this works. Set by RTOS SDK startup code) + bit 1 - INT_ENABLE_TIMER0 allows TIMER 0 (FRC1) to trigger interrupt INUM_TIMER_FRC1. + bit 2 - INT_ENABLE_TIMER1 allows TIMER 1 (FRC2) to trigger interrupt INUM_TIMER_FRC2. + + Espressif calls this register "EDGE_INT_ENABLE_REG". The "edge" in + question is (I think) the interrupt line from the peripheral, as + the interrupt status bit is set. There may be a similar register + for enabling "level" interrupts instead of edge triggering + - this is unknown. +*/ + +#define DPORT_INT_ENABLE_WDT BIT(0) +#define DPORT_INT_ENABLE_TIMER0 BIT(1) +#define DPORT_INT_ENABLE_TIMER1 BIT(2) + +/* Aliases for the Espressif way of referring to TIMER0 (FRC1) and TIMER1 + * (FRC2).. */ +#define DPORT_INT_ENABLE_FRC1 DPORT_INT_ENABLE_TIMER0 +#define DPORT_INT_ENABLE_FRC2 DPORT_INT_ENABLE_TIMER1 + +/* Details for SPI_READY register */ + +#define DPORT_SPI_READY_IDLE BIT(9) + +/* Details for CPU_CLOCK register */ + +#define DPORT_CPU_CLOCK_X2 BIT(0) + +/* Details for CLOCKGATE_WATCHDOG register */ + +// Set and then cleared during sdk_system_restart_in_nmi(). +// Not sure what this does. May be related to ESPSAR.UNKNOWN_48 +#define DPORT_CLOCKGATE_WATCHDOG_UNKNOWN_8 BIT(8) + +/* Comment found in pvvx/mp3_decode headers: "use clockgate_watchdog(flg) { if(flg) 0x3FF00018 &= 0x77; else 0x3FF00018 |= 8; }". Not sure what this means or does. */ + +#define DPORT_CLOCKGATE_WATCHDOG_DISABLE BIT(3) + +/* Details for SPI_INT_STATUS register */ + +#define DPORT_SPI_INT_STATUS_SPI0 BIT(4) +#define DPORT_SPI_INT_STATUS_SPI1 BIT(7) +#define DPORT_SPI_INT_STATUS_I2S BIT(9) + +/* Details for SPI_CACHE_RAM register */ + +#define DPORT_SPI_CACHE_RAM_BANK1 BIT(3) +#define DPORT_SPI_CACHE_RAM_BANK0 BIT(4) + +/* Details for PERI_IO register */ + +#define DPORT_PERI_IO_SWAP_UARTS BIT(0) +#define DPORT_PERI_IO_SWAP_SPIS BIT(1) +#define DPORT_PERI_IO_SWAP_UART0_PINS BIT(2) +#define DPORT_PERI_IO_SWAP_UART1_PINS BIT(3) +#define DPORT_PERI_IO_SPI1_PRIORITY BIT(5) +#define DPORT_PERI_IO_SPI1_SHARED BIT(6) +#define DPORT_PERI_IO_SPI0_SHARED BIT(7) + +/* Details for SLC_TX_DESC_DEBUG register */ + +#define SLC_TX_DESC_DEBUG_VALUE_M 0x0000ffff +#define SLC_TX_DESC_DEBUG_VALUE_S 0 + +#define SLC_TX_DESC_DEBUG_VALUE_MAGIC 0xcccc + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* DPORT_REGS_H */ diff --git a/cpu/esp8266/vendor/esp/flashchip.h b/cpu/esp8266/vendor/esp/flashchip.h new file mode 100644 index 0000000000..4aad689d19 --- /dev/null +++ b/cpu/esp8266/vendor/esp/flashchip.h @@ -0,0 +1,67 @@ +/* flashchip.h + * + * sdk_flashchip_t structure used by the SDK and some bootrom routines + * + * This is in a separate include file because it's referenced by several other + * headers which are otherwise independent of each other. + * + * Part of esp-open-rtos + * Copyright (C) 2015 Alex Stewart and Angus Gratton + * BSD Licensed as described in the file LICENSE + */ + +/* +Copyright (C) 2015 Alex Stewart and Angus Gratton +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef FLASHCHIP_H +#define FLASHCHIP_H + +#ifndef DOXYGEN + +#ifdef __cplusplus +extern "C" { +#endif + +/* SDK/bootrom uses this structure internally to account for flash size. + + chip_size field is initialised during startup from the flash size + saved in the image header (on the first 8 bytes of SPI flash). + + Other field are initialised to hardcoded values by the SDK. + + ** NOTE: This structure is passed to some bootrom routines and is therefore + fixed. Be very careful if you want to change it that you do not break + things. ** + + Based on RE work by @foogod at + http://esp8266-re.foogod.com/wiki/Flashchip_%28IoT_RTOS_SDK_0.9.9%29 +*/ +typedef struct { + uint32_t device_id; + uint32_t chip_size; /* in bytes */ + uint32_t block_size; /* in bytes */ + uint32_t sector_size; /* in bytes */ + uint32_t page_size; /* in bytes */ + uint32_t status_mask; +} sdk_flashchip_t; + +extern sdk_flashchip_t sdk_flashchip; + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* FLASHCHIP_H */ diff --git a/cpu/esp8266/vendor/esp/gpio_regs.h b/cpu/esp8266/vendor/esp/gpio_regs.h new file mode 100644 index 0000000000..f545e2965c --- /dev/null +++ b/cpu/esp8266/vendor/esp/gpio_regs.h @@ -0,0 +1,192 @@ +/* esp/gpio_regs.h + * + * ESP8266 GPIO register definitions + * + * Not compatible with ESP SDK register access code. + */ + +/* +Copyright (c) 2015, SuperHouse Automation 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: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef GPIO_REGS_H +#define GPIO_REGS_H + +#ifndef DOXYGEN + +#include "esp/types.h" +#include "common_macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define GPIO_BASE 0x60000300 +#define GPIO (*(struct GPIO_REGS *)(GPIO_BASE)) + +/** GPIO output registers GPIO.OUT, GPIO.OUT_SET, GPIO.OUT_CLEAR: + * + * _SET and _CLEAR write-only registers set and clear bits in the main register, + * respectively. + * + * i.e. + * GPIO.OUT_SET = BIT(3); + * and + * GPIO.OUT |= BIT(3); + * + * ... are equivalent, but the former uses fewer CPU cycles. + * + * ENABLE_OUT / ENABLE_OUT_SET / ENABLE_OUT_CLEAR: + * + * Determine whether the corresponding GPIO has its output enabled or not. + * When clear, GPIO can function as an input. When set, GPIO will drive its + * output (and IN register will simply reflect the output state). + * + * (_SET/_CLEAR function similarly to OUT registers) + * + * STATUS / STATUS_SET / STATUS_CLEAR: + * + * Indicates which GPIOs have triggered an interrupt. Interrupt status should + * be reset by writing to STATUS or STATUS_CLEAR. + * + * (_SET/_CLEAR function similarly to OUT registers) + * + * IN: + * + * Low 16 bits represent GPIO0-15 state (see also above). + * + * High 16 bits represent "strapping pins" values captured at reset time: + * bit 31 - GPIO10 (SD_DATA3) + * bit 30 - GPIO9 (SD_DATA2) + * bit 29 - GPIO7 (SD_DATA0) + * bit 18 - GPIO15 (MTDO) + * bit 17 - GPIO0 + * bit 16 - GPIO2 + * (In other words, highest 3 and lowest 3 bits of 16-bit half-word are used). + * BootROM uses strapping pin values to determine boot mode. + * + * Source and more information: 0D-ESP8266__Pin_List*.xlsx document + */ + +struct GPIO_REGS { + uint32_t volatile OUT; // 0x00 + uint32_t volatile OUT_SET; // 0x04 + uint32_t volatile OUT_CLEAR; // 0x08 + uint32_t volatile ENABLE_OUT; // 0x0c + uint32_t volatile ENABLE_OUT_SET; // 0x10 + uint32_t volatile ENABLE_OUT_CLEAR; // 0x14 + uint32_t volatile IN; // 0x18 + uint32_t volatile STATUS; // 0x1c + uint32_t volatile STATUS_SET; // 0x20 + uint32_t volatile STATUS_CLEAR; // 0x24 + uint32_t volatile CONF[16]; // 0x28 - 0x64 + uint32_t volatile PWM; // 0x68 + uint32_t volatile RTC_CALIB; // 0x6c + uint32_t volatile RTC_CALIB_RESULT; // 0x70 +}; + +_Static_assert(sizeof(struct GPIO_REGS) == 0x74, "GPIO_REGS is the wrong size"); + +/* Details for additional OUT register fields */ + +/* Bottom 16 bits of GPIO.OUT are for GPIOs 0-15, but upper 16 bits + are used to configure the input signalling pins for Bluetooth + Coexistence config (see esp/phy.h for a wrapper function). +*/ +#define GPIO_OUT_PIN_MASK 0x0000FFFF +#define GPIO_OUT_BT_COEXIST_MASK 0x03FF0000 +#define GPIO_OUT_BT_ACTIVE_ENABLE BIT(24) +#define GPIO_OUT_BT_PRIORITY_ENABLE BIT(25) +#define GPIO_OUT_BT_ACTIVE_PIN_M 0x0F +#define GPIO_OUT_BT_ACTIVE_PIN_S 16 +#define GPIO_OUT_BT_PRIORITY_PIN_M 0x0F +#define GPIO_OUT_BT_PRIORITY_PIN_S 20 + +/* Details for CONF[i] registers */ + +/* GPIO.CONF[i] control the pin behavior for the corresponding GPIO in/output. + * + * GPIO_CONF_CONFIG (multi-value) + * FIXME: Unclear what these do. Need to find a better name. + * + * GPIO_CONF_WAKEUP_ENABLE (boolean) + * Can an interrupt contion on this pin wake the processor from a sleep + * state? + * + * GPIO_CONF_INTTYPE (multi-value) + * Under what conditions this GPIO input should generate an interrupt. + * (see gpio_inttype_t enum below for values) + * + * GPIO_CONF_OPEN_DRAIN (boolean) + * If this bit is set, the pin is in "open drain" mode - a high output state + * will leave the pin floating but not source any current. If bit is cleared, + * the pin is in push/pull mode so a high output state will drive the pin up + * to +Vcc (3.3V). In either case, a low output state will pull the pin down + * to ground. + * + * GPIO_CONF_OPEN_DRAIN does not appear to work on all pins. + * + * + * GPIO_CONF_SOURCE_PWM (boolean) + * When set, GPIO pin output will be connected to the sigma-delta PWM + * generator (controlled by the GPIO.PWM register). When cleared, pin + * output will function as a normal GPIO output (controlled by the + * GPIO.OUT* registers). + */ + +#define GPIO_CONF_CONFIG_M 0x00000003 +#define GPIO_CONF_CONFIG_S 11 +#define GPIO_CONF_WAKEUP_ENABLE BIT(10) +#define GPIO_CONF_INTTYPE_M 0x00000007 +#define GPIO_CONF_INTTYPE_S 7 +#define GPIO_CONF_OPEN_DRAIN BIT(2) +#define GPIO_CONF_SOURCE_PWM BIT(0) + +/* Valid values for the GPIO_CONF_INTTYPE field */ +typedef enum { + GPIO_INTTYPE_NONE = 0, + GPIO_INTTYPE_EDGE_POS = 1, + GPIO_INTTYPE_EDGE_NEG = 2, + GPIO_INTTYPE_EDGE_ANY = 3, + GPIO_INTTYPE_LEVEL_LOW = 4, + GPIO_INTTYPE_LEVEL_HIGH = 5, +} gpio_inttype_t; + +/* Details for PWM register */ + +#define GPIO_PWM_ENABLE BIT(16) +#define GPIO_PWM_PRESCALER_M 0x000000ff +#define GPIO_PWM_PRESCALER_S 8 +#define GPIO_PWM_TARGET_M 0x000000ff +#define GPIO_PWM_TARGET_S 0 + +/* Details for RTC_CALIB register */ + +#define GPIO_RTC_CALIB_START BIT(31) +#define GPIO_RTC_CALIB_PERIOD_M 0x000003ff +#define GPIO_RTC_CALIB_PERIOD_S 0 + +/* Details for RTC_CALIB_RESULT register */ + +#define GPIO_RTC_CALIB_RESULT_READY BIT(31) +#define GPIO_RTC_CALIB_RESULT_READY_REAL BIT(30) +#define GPIO_RTC_CALIB_RESULT_VALUE_M 0x000fffff +#define GPIO_RTC_CALIB_RESULT_VALUE_S 0 + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* GPIO_REGS_H */ diff --git a/cpu/esp8266/vendor/esp/iomux_regs.h b/cpu/esp8266/vendor/esp/iomux_regs.h new file mode 100644 index 0000000000..42f2064a08 --- /dev/null +++ b/cpu/esp8266/vendor/esp/iomux_regs.h @@ -0,0 +1,172 @@ +/* esp/iomux_regs.h + * + * ESP8266 IOMUX register definitions + * + * Not compatible with ESP SDK register access code. + * + * Note that IOMUX register order is _not_ the same as GPIO order. See + * esp/iomux.h for programmer-friendly IOMUX configuration options. + */ + +/* +Copyright (c) 2015, SuperHouse Automation 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: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef IOMUX_REGS_H +#define IOMUX_REGS_H + +#ifndef DOXYGEN + +#include "esp/types.h" +#include "common_macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IOMUX_BASE 0x60000800 +#define IOMUX (*(struct IOMUX_REGS *)(IOMUX_BASE)) + +struct IOMUX_REGS { + uint32_t volatile CONF; // 0x00 + uint32_t volatile PIN[16]; // 0x04 - 0x40 +}; + +_Static_assert(sizeof(struct IOMUX_REGS) == 0x44, "IOMUX_REGS is the wrong size"); + +/* Details for CONF register */ + +#define IOMUX_CONF_SPI0_CLOCK_EQU_SYS_CLOCK BIT(8) +#define IOMUX_CONF_SPI1_CLOCK_EQU_SYS_CLOCK BIT(9) + +/* Details for PIN registers */ + +#define IOMUX_PIN_OUTPUT_ENABLE BIT(0) +#define IOMUX_PIN_OUTPUT_ENABLE_SLEEP BIT(1) +#define IOMUX_PIN_PULLDOWN_SLEEP BIT(2) +#define IOMUX_PIN_PULLUP_SLEEP BIT(3) +#define IOMUX_PIN_FUNC_LOW_M 0x00000003 +#define IOMUX_PIN_FUNC_LOW_S 4 +#define IOMUX_PIN_PULLDOWN BIT(6) +#define IOMUX_PIN_PULLUP BIT(7) +#define IOMUX_PIN_FUNC_HIGH_M 0x00000004 +#define IOMUX_PIN_FUNC_HIGH_S 6 + +#define IOMUX_PIN_FUNC_MASK 0x00000130 + +/* WARNING: Macro evaluates argument twice */ +#define IOMUX_FUNC(val) (VAL2FIELD_M(IOMUX_PIN_FUNC_LOW, val) | VAL2FIELD_M(IOMUX_PIN_FUNC_HIGH, val)) + +#define IOMUX_GPIO0 IOMUX.PIN[12] +#define IOMUX_GPIO1 IOMUX.PIN[5] +#define IOMUX_GPIO2 IOMUX.PIN[13] +#define IOMUX_GPIO3 IOMUX.PIN[4] +#define IOMUX_GPIO4 IOMUX.PIN[14] +#define IOMUX_GPIO5 IOMUX.PIN[15] +#define IOMUX_GPIO6 IOMUX.PIN[6] +#define IOMUX_GPIO7 IOMUX.PIN[7] +#define IOMUX_GPIO8 IOMUX.PIN[8] +#define IOMUX_GPIO9 IOMUX.PIN[9] +#define IOMUX_GPIO10 IOMUX.PIN[10] +#define IOMUX_GPIO11 IOMUX.PIN[11] +#define IOMUX_GPIO12 IOMUX.PIN[0] +#define IOMUX_GPIO13 IOMUX.PIN[1] +#define IOMUX_GPIO14 IOMUX.PIN[2] +#define IOMUX_GPIO15 IOMUX.PIN[3] + +#define IOMUX_GPIO0_FUNC_GPIO IOMUX_FUNC(0) +#define IOMUX_GPIO0_FUNC_SPI0_CS2 IOMUX_FUNC(1) +#define IOMUX_GPIO0_FUNC_CLOCK_OUT IOMUX_FUNC(4) + +#define IOMUX_GPIO1_FUNC_UART0_TXD IOMUX_FUNC(0) +#define IOMUX_GPIO1_FUNC_SPI0_CS1 IOMUX_FUNC(1) +#define IOMUX_GPIO1_FUNC_GPIO IOMUX_FUNC(3) +#define IOMUX_GPIO1_FUNC_CLOCK_RTC_BLINK IOMUX_FUNC(4) + +#define IOMUX_GPIO2_FUNC_GPIO IOMUX_FUNC(0) +#define IOMUX_GPIO2_FUNC_I2SO_WS IOMUX_FUNC(1) +#define IOMUX_GPIO2_FUNC_UART1_TXD IOMUX_FUNC(2) +#define IOMUX_GPIO2_FUNC_UART0_TXD IOMUX_FUNC(4) + +#define IOMUX_GPIO3_FUNC_UART0_RXD IOMUX_FUNC(0) +#define IOMUX_GPIO3_FUNC_I2SO_DATA IOMUX_FUNC(1) +#define IOMUX_GPIO3_FUNC_GPIO IOMUX_FUNC(3) +#define IOMUX_GPIO3_FUNC_CLOCK_XTAL_BLINK IOMUX_FUNC(4) + +#define IOMUX_GPIO4_FUNC_GPIO IOMUX_FUNC(0) +#define IOMUX_GPIO4_FUNC_CLOCK_XTAL IOMUX_FUNC(1) + +#define IOMUX_GPIO5_FUNC_GPIO IOMUX_FUNC(0) +#define IOMUX_GPIO5_FUNC_CLOCK_RTC IOMUX_FUNC(1) + +#define IOMUX_GPIO6_FUNC_SD_CLK IOMUX_FUNC(0) +#define IOMUX_GPIO6_FUNC_SPI0_CLK IOMUX_FUNC(1) +#define IOMUX_GPIO6_FUNC_GPIO IOMUX_FUNC(3) +#define IOMUX_GPIO6_FUNC_UART1_CTS IOMUX_FUNC(4) + +#define IOMUX_GPIO7_FUNC_SD_DATA0 IOMUX_FUNC(0) +#define IOMUX_GPIO7_FUNC_SPI0_Q_MISO IOMUX_FUNC(1) +#define IOMUX_GPIO7_FUNC_GPIO IOMUX_FUNC(3) +#define IOMUX_GPIO7_FUNC_UART1_TXD IOMUX_FUNC(4) + +#define IOMUX_GPIO8_FUNC_SD_DATA1 IOMUX_FUNC(0) +#define IOMUX_GPIO8_FUNC_SPI0_D_MOSI IOMUX_FUNC(1) +#define IOMUX_GPIO8_FUNC_GPIO IOMUX_FUNC(3) +#define IOMUX_GPIO8_FUNC_UART1_RXD IOMUX_FUNC(4) + +#define IOMUX_GPIO9_FUNC_SD_DATA2 IOMUX_FUNC(0) +#define IOMUX_GPIO9_FUNC_SPI0_HD IOMUX_FUNC(1) +#define IOMUX_GPIO9_FUNC_GPIO IOMUX_FUNC(3) +#define IOMUX_GPIO9_FUNC_SPI1_HD IOMUX_FUNC(4) + +#define IOMUX_GPIO10_FUNC_SD_DATA3 IOMUX_FUNC(0) +#define IOMUX_GPIO10_FUNC_SPI0_WP IOMUX_FUNC(1) +#define IOMUX_GPIO10_FUNC_GPIO IOMUX_FUNC(3) +#define IOMUX_GPIO10_FUNC_SPI1_WP IOMUX_FUNC(4) + +#define IOMUX_GPIO11_FUNC_SD_CMD IOMUX_FUNC(0) +#define IOMUX_GPIO11_FUNC_SPI0_CS0 IOMUX_FUNC(1) +#define IOMUX_GPIO11_FUNC_GPIO IOMUX_FUNC(3) +#define IOMUX_GPIO11_FUNC_UART1_RTS IOMUX_FUNC(4) + +#define IOMUX_GPIO12_FUNC_MTDI IOMUX_FUNC(0) +#define IOMUX_GPIO12_FUNC_I2SI_DATA IOMUX_FUNC(1) +#define IOMUX_GPIO12_FUNC_SPI1_Q_MISO IOMUX_FUNC(2) +#define IOMUX_GPIO12_FUNC_GPIO IOMUX_FUNC(3) +#define IOMUX_GPIO12_FUNC_UART0_DTR IOMUX_FUNC(4) + +#define IOMUX_GPIO13_FUNC_MTCK IOMUX_FUNC(0) +#define IOMUX_GPIO13_FUNC_I2SI_BCK IOMUX_FUNC(1) +#define IOMUX_GPIO13_FUNC_SPI1_D_MOSI IOMUX_FUNC(2) +#define IOMUX_GPIO13_FUNC_GPIO IOMUX_FUNC(3) +#define IOMUX_GPIO13_FUNC_UART0_CTS IOMUX_FUNC(4) + +#define IOMUX_GPIO14_FUNC_MTMS IOMUX_FUNC(0) +#define IOMUX_GPIO14_FUNC_I2SI_WS IOMUX_FUNC(1) +#define IOMUX_GPIO14_FUNC_SPI1_CLK IOMUX_FUNC(2) +#define IOMUX_GPIO14_FUNC_GPIO IOMUX_FUNC(3) +#define IOMUX_GPIO14_FUNC_UART0_DSR IOMUX_FUNC(4) + +#define IOMUX_GPIO15_FUNC_MTDO IOMUX_FUNC(0) +#define IOMUX_GPIO15_FUNC_I2SO_BCK IOMUX_FUNC(1) +#define IOMUX_GPIO15_FUNC_SPI1_CS0 IOMUX_FUNC(2) +#define IOMUX_GPIO15_FUNC_GPIO IOMUX_FUNC(3) +#define IOMUX_GPIO15_FUNC_UART0_RTS IOMUX_FUNC(4) + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* IOMUX_REGS_H */ diff --git a/cpu/esp8266/vendor/esp/phy_info.c b/cpu/esp8266/vendor/esp/phy_info.c new file mode 100644 index 0000000000..d474b2b8e1 --- /dev/null +++ b/cpu/esp8266/vendor/esp/phy_info.c @@ -0,0 +1,200 @@ +/* Routines to allow custom access to the Internal Espressif + SDK PHY datastructures. + + Matches espressif/phy_internal.h + + Part of esp-open-rtos. Copyright (C) 2016 Angus Gratton, + BSD Licensed as described in the file LICENSE. + */ + +/* +Copyright (C) 2016 Angus Gratton +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef MODULE_ESP_SDK +#ifdef RIOT_VERSION +#include +#include "c_types.h" +#include "esp/common_macros.h" +#include "esp/flashchip.h" +#include "esp/phy_info.h" +#include "spi_flash.h" +#include "sdk/rom.h" + +#define sdk_spi_flash_read spi_flash_read +#define sdk_spi_flash_write spi_flash_write + +#else +#include +#include +#include +#endif +#include + +static const sdk_phy_info_t IROM default_phy_info = { + ._reserved00 = { 0x05, 0x00, 0x04, 0x02, 0x05 }, + .version = 5, + ._reserved06 = { 0x05, 0x02, 0x05, 0x00, 0x04, 0x05, 0x05, 0x04, + 0x05, 0x05, 0x04,-0x02,-0x03,-0x01,-0x10,-0x10, + -0x10,-0x20,-0x20, -0x20}, + .spur_freq_primary = 225, + .spur_freq_divisor = 10, + .spur_freq_en_h = 0xFF, + .spur_freq_en_l = 0xFF, + + ._reserved1e = { 0xf8, 0, 0xf8, 0xf8 }, + + .target_power = { 82, 78, 74, 68, 64, 56 }, + .target_power_index_mcs = { 0, 0, 1, 1, 2, 3, 4, 5 }, + + .crystal_freq = CRYSTAL_FREQ_26M, + + .sdio_config = SDIO_CONFIG_AUTO, + + .bt_coexist_config = BT_COEXIST_CONFIG_NONE, + .bt_coexist_protocol = BT_COEXIST_PROTOCOL_WIFI_ONLY, + + .dual_ant_config = DUAL_ANT_CONFIG_NONE, + + ._reserved34 = 0x02, + + .crystal_sleep = CRYSTAL_SLEEP_OFF, + + .spur_freq_2_primary = 225, + .spur_freq_2_divisor = 10, + .spur_freq_2_en_h = 0x00, + .spur_freq_2_en_l = 0x00, + .spur_freq_cfg_msb = 0x00, + .spur_freq_2_cfg_msb = 0x00, + .spur_freq_3_cfg = 0x0000, + .spur_freq_4_cfg = 0x0000, + + ._reserved4a = { 0x01, 0x93, 0x43, 0x00 }, + + .low_power_en = false, + .lp_atten_stage01 = LP_ATTEN_STAGE01_23DB, + .lp_atten_bb = 0, + + .pwr_ind_11b_en = false, + .pwr_ind_11b_0 = 0, + .pwr_ind_11b_1 = 0, + + /* Nominal 3.3V VCC. NOTE: This value is 0 in the + esp-open-rtos SDK default config sector, and may be unused + by that version of the SDK? + */ + .pa_vdd = 33, + + /* Note: untested with the esp-open-rtos SDK default config sector, may be unused? */ + .freq_correct_mode = FREQ_CORRECT_DISABLE, + .force_freq_offset = 0, + + /* Note: is zero with the esp-open-rtos SDK default config sector, may be unused? */ + .rf_cal_mode = RF_CAL_MODE_SAVED, +}; + +sdk_phy_info_t* default_phy_info_ref = (sdk_phy_info_t*)&default_phy_info; +sdk_phy_info_t* get_default_phy_info_ref(void) +{ + return (sdk_phy_info_t*)&default_phy_info; +} + +void get_default_phy_info(sdk_phy_info_t *info) __attribute__((weak, alias("get_sdk_default_phy_info"))); + +void get_sdk_default_phy_info(sdk_phy_info_t *info) +{ + memcpy(info, &default_phy_info, sizeof(sdk_phy_info_t)); +} + +void read_saved_phy_info(sdk_phy_info_t *info) +{ + sdk_spi_flash_read(sdk_flashchip.chip_size - sdk_flashchip.sector_size * 4, (uint32_t *)info, sizeof(sdk_phy_info_t)); +} + +void write_saved_phy_info(const sdk_phy_info_t *info) +{ + sdk_spi_flash_write(sdk_flashchip.chip_size - sdk_flashchip.sector_size * 4, (uint32_t *)info, sizeof(sdk_phy_info_t)); +} + +void dump_phy_info(const sdk_phy_info_t *info, bool raw) +{ + printf("version=%d\n", info->version); + printf("spur_freq = %.3f (%d/%d)\n", + (float)info->spur_freq_primary / info->spur_freq_divisor, + info->spur_freq_primary, + info->spur_freq_divisor); + printf("spur_freq_en = 0x%02x 0x%02x\n", info->spur_freq_en_h, + info->spur_freq_en_l); + printf("target_power\n"); + for(int i = 0; i < 6; i++) { + printf(" %d: %.2fdB (raw 0x%02x)\n", i, + info->target_power[i]/4.0, + info->target_power[i]); + } + printf("target_power_index_mcs:"); + for(int i = 0; i < 8; i++) { + printf(" %d%c", info->target_power_index_mcs[i], + i == 7 ? '\n' : ','); + } + + printf("crystal_freq: %s (raw %d)\n", + (info->crystal_freq == CRYSTAL_FREQ_40M ? "40MHz" : + (info->crystal_freq == CRYSTAL_FREQ_26M ? "26MHz" : + (info->crystal_freq == CRYSTAL_FREQ_24M ? "24MHz" : "???"))), + info->crystal_freq); + + printf("sdio_config: %d\n", info->sdio_config); + printf("bt_coexist config: %d protocol: 0x%02x\n", + info->bt_coexist_config, info->bt_coexist_protocol); + printf("dual_ant_config: %d\n", info->dual_ant_config); + + printf("crystal_sleep: %d\n", info->crystal_sleep); + + printf("spur_freq_2 = %.3f (%d/%d)\n", + (float)info->spur_freq_2_primary / info->spur_freq_2_divisor, + info->spur_freq_2_primary, + info->spur_freq_2_divisor); + printf("spur_freq_2_en = 0x%02x 0x%02x\n", info->spur_freq_2_en_h, + info->spur_freq_2_en_l); + + printf("spur_freq_cfg_msb = 0x%02x\n", info->spur_freq_cfg_msb); + printf("spur_freq_2_)cfg_msb = 0x%02x\n", info->spur_freq_2_cfg_msb); + printf("spur_freq_3_cfg = 0x%04x\n", info->spur_freq_3_cfg); + printf("spur_freq_4_cfg = 0x%04x\n", info->spur_freq_4_cfg); + + printf("low_power_en = %d\n", info->low_power_en); + printf("lp_atten_stage01 = 0x%02x\n", info->lp_atten_stage01); + printf("lp_atten_bb = %.2f (raw 0x%02x)\n", info->lp_atten_bb / 4.0, + info->lp_atten_bb); + + printf("pa_vdd = %d\n", info->pa_vdd); + + printf("freq_correct_mode = 0x%02x\n", info->freq_correct_mode); + printf("force_freq_offset = %d\n", info->force_freq_offset); + printf("rf_cal_mode = 0x%02x\n", info->rf_cal_mode); + + if(raw) { + printf("Raw values:"); + uint8_t *p = (uint8_t *)info; + for(unsigned int i = 0; i < sizeof(sdk_phy_info_t); i ++) { + if(i % 8 == 0) { + printf("\n0x%02x:", i); + } + printf(" %02x", p[i]); + } + printf("\n\n"); + } +} + +#endif diff --git a/cpu/esp8266/vendor/esp/phy_info.h b/cpu/esp8266/vendor/esp/phy_info.h new file mode 100644 index 0000000000..d069befd06 --- /dev/null +++ b/cpu/esp8266/vendor/esp/phy_info.h @@ -0,0 +1,509 @@ +/** Internal Espressif SDK "PHY info" data structure + + The data structure (sdk_phy_info_t) is used to configure the + ESP8266 PHY layer via the SDK. The fields here are not written + directly to hardware, the SDK code (mostly in libphy) parses this + structure and configures the hardware. + + The structure loaded at reset time from a flash configuration + sector (see read_saved_phy_info()) (Espressif's SDK sources this + from a file "esp_init_data_default.bin"). If no valid structure is + found in the flash config sector then the SDK loads default values + (see get_default_phy_info()). It is possible to implement a custom + get_default_phy_info() to change the PHY default settings (see the + 'version' field below). + + @note It is possible that the SDK will quietly write a new + configuration sector to flash itself following internal + calibration, etc. However this does not seem to happen, you need to + flash it explicitly if you want it stored there. + + @note Most of what is below is unconfirmed, except where a @note + says that it has been confirmed to work as expected. Please + consider submitting notes if you find behaviour here that works or + doesn't work as expected. + + Information on the meaning/offset of fields comes from Espressif's + flash download tool, which uses an Excel spreadsheet (in the + init_data directory of the ZIP file) to configure and a Python + script to convert an esp_init_data_custom.bin file to flash: + http://bbs.espressif.com/viewtopic.php?f=5&t=433 + + Many fields remain undocumented (& disassembly of libphy suggests + that some documented fields supported undocumented values.) + + A few additional notes about the phy_info fields can be found + in the ESP Arduino ESP8266 phy_init_data structure (however most of + that content is verbatim from Espressif's spreadsheet): + https://github.com/esp8266/Arduino/blob/master/cores/esp8266/core_esp8266_phy.c#L29 + + Part of esp-open-rtos. Copyright (C) 2016 Angus Gratton, + BSD Licensed as described in the file LICENSE. + */ + +/* +Copyright (C) 2016 Angus Gratton +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef PHY_INFO_H +#define PHY_INFO_H + +#ifndef DOXYGEN + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* CRYSTAL_FREQ_xx values as used by sdk_phy_info_t.crystal_freq */ +#define CRYSTAL_FREQ_40M 0 +#define CRYSTAL_FREQ_26M 1 +#define CRYSTAL_FREQ_24M 2 + +/* SDIO_CONFIG_xx values as used by sdk_phy_info_t.sdio_config */ +#define SDIO_CONFIG_AUTO 0 /* Uses pin strapping to determine */ +#define SDIO_CONFIG_SDIOV1_1 /* Data output on negative edge */ +#define SDIO_CONFIG_SDIOV2_0 /* data output on positive edge */ + +/* BT_COEXIST_CONFIG_xx values as used by sdk_phy_info_t.bt_coexist */ +/* No bluetooth */ +#define BT_COEXIST_CONFIG_NONE 0 +/* Coexistence configuration A: + GPIO 0 - WLAN_ACTIVE + GPIO 14 - BT_ACTIVE + GPIO 13 - BT_PRIORITY + GPIO 3 - ANT_SEL_BT +*/ +#define BT_COEXIST_CONFIG_A 1 +/* No coexistence, but Bluetooth enabled? + Unsure how this works? + */ +#define BT_COEXIST_CONFIG_PRESENT 2 +/* Coexistence configuration B: + GPIO 0 - WLAN_ACTIVE + GPIO 14 - BT_PRIORITY + GPIO 13 - BT_ACTIVE + GPIO 3 - ANT_SEL_BT +*/ +#define BT_COEXIST_CONFIG_B 3 + +/* BT_COEXIST_PROTOCOL_xx values for coexistence protocol, + field sdk_phy_info_t.bt_coexist_protocol + */ +#define BT_COEXIST_PROTOCOL_WIFI_ONLY 0 +#define BT_COEXIST_PROTOCOL_BT_ONLY 1 + +/* Coexistence is enabled, Bluetooth has its own antenna */ +#define BT_COEXIST_PROTOCOL_FLAG_SEPARATE_ANT 2 +/* Coexistence is enabled, Bluetooth shares WiFi antenna */ +#define BT_COEXIST_PROTOCOL_FLAG_SHARE_ANT 4 + +/* Coexistence is enabled, use only BT_ACTIVE signal */ +#define BT_COEXIST_PROTOCOL_FLAG_BT_ACTIVE_ONLY 0 +/* Coexistence is enabled, use both BT_ACTIVE and BT_PRIORITY signals */ +#define BT_COEXIST_PROTOCOL_FLAG_BT_ACTIVE_PRIORITY 1 + +/* DUAL_ANT_CONFIG_xx values for dual antenna config, + field sdk_phy_info_t.dual_ant_config + + (Not really clear how this feature works, if at all.) +*/ +#define DUAL_ANT_CONFIG_NONE 0 +/* antenna diversity for WiFi, use GPIO0 + U0RXD (?) */ +#define DUAL_ANT_CONFIG_DUAL 1 +/* TX/RX switch for external PA & LNA: GPIO 0 high, GPIO 3 low during TX */ +#define DUAL_ANT_CONFIG_TX_GPIO0_HIGH_GPIO3_LOW +/* TX/RX switch for external PA & LNA: GPIO 0 low, GPIO 3 high during TX */ +#define DUAL_ANT_CONFIG_TX_GPIO0_LOW_GPIO3_HIGH + + +/* CRYSTAL_SLEEP_xx values used for sdk_phy_info_t.crystal_sleep + */ +#define CRYSTAL_SLEEP_OFF 0 +#define CRYSTAL_SLEEP_ON 1 +#define CRYSTAL_SLEEP_GPIO16 2 +#define CRYSTAL_SLEEP_GPIO2 3 + +/* RF Stage 0 & 1 attenuation constants. Use for sdk_phy_info_t.lp_atten_stage01 + + @note These values have been tested and are confirmed to work as + expected by measuring RSSI w/ rt73 USB adapter in monitor mode + (some values also checked on spectrum analyzer) - provided + low_power_en is set then the signal is attenuated as per this + setting. + + (It may look like LP_ATTEN_STAGE01_11_5DB is out of order, but + according to monitor mode captures this is the correct ordering of + these constants.) + + Setting the numeric values in between these constants appears to + also attenuate the signal, but not necessarily by the amount you'd + expect. +*/ +#define LP_ATTEN_STAGE01_0DB 0x0f /* 0dB */ +#define LP_ATTEN_STAGE01_2_5DB 0x0e /* -2.5dB */ +#define LP_ATTEN_STAGE01_6DB 0x0d /* -6dB */ +#define LP_ATTEN_STAGE01_8_5DB 0x09 /* -8.5dB */ +#define LP_ATTEN_STAGE01_11_5DB 0x0c /* -11.5dB */ +#define LP_ATTEN_STAGE01_14DB 0x08 /* -14dB */ +#define LP_ATTEN_STAGE01_17_5DB 0x04 /* -17.5dB */ +#define LP_ATTEN_STAGE01_23DB 0x00 /* -23dB */ + +/* Constant for sdk_phy_info_t.pa_vdd */ +#define PA_VDD_MEASURE_VCC 0xFF + +/* Bitmask flags for sdk_phy_info_t.freq_correct_mode */ + +/* Set this flag to disable frequency offset correction */ +#define FREQ_CORRECT_DISABLE 0 + +/* Set this flag to enable frequency offset correction */ +#define FREQ_CORRECT_ENABLE BIT(0) + +/* Set = Baseband PLL frequency is 160MHz (can only apply +ve offset) + * Unset = Baseband PLL frequency is 168MHz (can apply +ve/-ve offset */ +#define FREQ_CORRECT_BB_160M BIT(1) + +/* Set = use force_freq_offset field to correct, Unset = automatically + measure & correct offset +*/ +#define FREQ_CORRECT_FORCE BIT(2) + + +/* RF_CAL_MODE_xx fields used for sdk_phy_info_t.rf_cal_mode + */ +/* Use saved RF CAL data from flash, only. RF init takes 2ms. */ +#define RF_CAL_MODE_SAVED 0 +/* Calibrate TX power control only, use saved RF CAL data for others. + RF init takes 20ms. */ +#define RF_CAL_MODE_TXPOWER_ONLY 1 +/* Unclear if/how this mode is different to 2? */ +#define RF_CAL_MODE_SAVED_2 2 +/* Run full RF CAL routine. RF init takes approx 200ms. */ +#define RF_CAL_MODE_FULL 3 + +/* Data structure that maps to the phy_info configuration block */ +typedef struct __attribute__((packed)) { + uint8_t _reserved00[0x05]; /* 0x00 - 0x04 */ + + /* This "version" field was set to 5 in the SDK phy_info, + and the original SDK startup code checks it is 5 and then loads + default PHY configuration otherwise. + + esp-open-rtos will load phy_info from get_default_phy_info() if + the value stored in flash has a different value to the value + returned in get_default_phy_info(). This means you can + increment the version return by get_default_phy_info() (to any + value but 0xFF), and know that the new defaults will replace + any older stored values. + + @notes It's not clear whether this is actually a version field + (the other 24 bytes here have equally arbitrary numbers in + them.) Changing the "version" to other values does not seem to + effect WiFi performance at all, neither does zeroing out the + first 5 reserved bytes in _reserved00. However zeroing bytes in + the _reserved06 region will break WiFi entirely. + */ + uint8_t version; /* 0x05 */ + int8_t _reserved06[0x14]; /* 0x06 - 0x19 */ + + /* spur_freq = spur_freq_primary / spur_freq_divisor */ + uint8_t spur_freq_primary; /* 0x1a */ + uint8_t spur_freq_divisor; /* 0x1b */ + + /* Bitmask to enable spur_freq for each channel + Appears to be a big endian short word? + */ + uint8_t spur_freq_en_h; /* 0x1c */ + uint8_t spur_freq_en_l; /* 0x1d */ + + uint8_t _reserved1e[4]; /* 0x1e - 0x21 */ + + /* Each value is a target power level. + Units are 1/4 dBm ie value 64 = 16dBm. + + SDK defaults to using these transmit powers: + 20.5dBm, 19.5dBm, 18.5dBm, 17dBm, 16dBm, 14dBm + + @note Adjusting these values is confirmed to reduce + transmit power accordingly. + */ + uint8_t target_power[6]; /* 0x22 - 0x27 */ + + /* Maps 8 MCS (modulation & coding schemes) types for 802.11b, g & + * n to a target_power level index (0-5), set above. + + This mapping of MCS slot to MCS type is derived from the + spreadsheet and also a table sent by Espressif, but is untested + and may be SDK version dependendent (especially any 802.11n + rates). However the general relationship is confirmed to hold + (higher MCS index = higher bit rate). + + MCS 0: 1Mbps/2Mbps/5.5Mbps/11Mbps (802.11b) / 6Mbps/9Mbps (802.11g) + default target_power 0 (default 20.5dBm) + (see also pwr_ind_11b_en) + + MCS 1: 12Mbps (802.11g) + default target_power 0 (default 20.5dBm) + + MCS 2: 18Mbps (802.11g) + default target_power 1 (19.5dBm) + + MCS 3: 24Mbps (802.11g) + default target_power 1 (19.5dBm) + + MCS 4: 36Mbps (802.11g) + default target_power 2 (18.5dBm) + + MCS 5: 48Mbps (802.11g) + default target_power 3 (17dBm) + + MCS 6: 54Mbps (802.11g) + default target_power 4 (16dBm) + + MCS 7: 65Mbps (802.11n) - unclear if ever used? + default target_power 5 (14dBm) + */ + uint8_t target_power_index_mcs[8]; /* 0x28 - 0x2f */ + + /* One of CRYSTAL_FREQ_40M / CRYSTAL_FREQ_26M / CRYSTAL_FREQ_24M + + The crystal configured here is the input to the PLL setting + calculations which are used to derive the CPU & APB peripheral + clock frequency, and probably the WiFi PLLs (unconfirmed.) + */ + uint8_t crystal_freq; /* 0x30 */ + + uint8_t _unused31; /* 0x31: Possibly high byte of crystal freq? */ + + /* One of SDIO_CONFIG_AUTO, SDIO_CONFIG_SDIOV1_1, SDIO_CONFIG_SDIOV2_0 */ + uint8_t sdio_config; /* 0x32 */ + + /* BT coexistence pin configuration. + + One of BT_COEXIST_CONFIG_NONE, BT_COEXIST_CONFIG_A, + BT_COEXIST_CONFIG_PRESENT, BT_COEXIST_CONFIG_B + */ + uint8_t bt_coexist_config; /* 0x33 */ + + /* BT coexistence pin protocol. + + If no coexistence: + Either BT_COEXIST_PROTOCOL_WIFI_ONLY, or + BT_COEXIST_PROTOCOL_BT_ONLY. + + If coexistence: + Combine one of + BT_COEXIST_PROTOCOL_FLAG_SEPARATE_ANT or + BT_COEXIST_PROTOCOL_FLAG_SHARE_ANT + with one of + BT_COEXIST_PROTOCOL_FLAG_BT_ACTIVE_ONLY or + BT_COEXIST_PROTOCOL_FLAG_BT_ACTIVE_BT_PRIORITY + */ + uint8_t bt_coexist_protocol; /* 0x34 */ + + /* Dual antenna configuration + + One of DUAL_ANT_CONFIG_NONE, DUAL_ANT_CONFIG_DUAL, + DUAL_ANT_CONFIG_TX_GPIO0_HIGH_GPIO3_LOW, + DUAL_ANT_CONFIG_TX_GPIO0_LOW_GPIO3_HIGH + */ + uint8_t dual_ant_config; /* 0x35 */ + + uint8_t _reserved34; /* 0x36 */ + + /* For sharing crystal clock with other devices: + one of CRYSTAL_SLEEP_OFF, CRYSTAL_SLEEP_ON, + CRYSTAL_SLEEP_GPIO16, CRYSTAL_SLEEP_GPIO2 + */ + uint8_t crystal_sleep; /* 0x37 */ + + uint8_t _unused38[8]; + + /* spur_freq_2 = spur_freq_2_primary / spur_freq_2_divisor */ + uint8_t spur_freq_2_primary; /* 0x40 */ + uint8_t spur_freq_2_divisor; /* 0x41 */ + + /* Bitmask to enable spur_freq_2 for each channel? + Appears to be a big endian short word? + */ + uint8_t spur_freq_2_en_h; /* 0x42 */ + uint8_t spur_freq_2_en_l; /* 0x43 */ + + /* Not really clear what these do */ + uint8_t spur_freq_cfg_msb; /* 0x44 */ + uint8_t spur_freq_2_cfg_msb; /* 0x45 */ + uint16_t spur_freq_3_cfg; /* 0x46 - 0x47 */ + uint16_t spur_freq_4_cfg; /* 0x48 - 0x49 */ + + uint8_t _reserved4a[4]; /* 0x4a - 0x4d */ + + uint8_t _unused78[15]; /* 0x4e - 0x5c */ + + /* Flag to enable low power mode */ + uint8_t low_power_en; /* 0x5d */ + + /* Low Power attenuation of RF gain stages 0 & 1 + + Attenuates transmit power if/when low_power_en is set. + + Use one of the constants LP_ATTEN_STAGE01_0DB, + LP_ATTEN_STAGE01_2_5DB, LP_ATTEN_STAGE01_6DB, + LP_ATTEN_STAGE01_8_5DB, LP_ATTEN_STAGE01_11_5DB, + LP_ATTEN_STAGE01_14DB, LP_ATTEN_STAGE01_17_5DB, + LP_ATTEN_STAGE01_23DB. + */ + uint8_t lp_atten_stage01; /* 0x5e */ + + /* Low Power(?) attenuation of baseband gain + + Units are minus 1/4 dB, ie value 4 == -1dB. + + Maximum value is 24 (0x18) == -6dB + */ + uint8_t lp_atten_bb; /* 0x5f */ + + /* I believe this means, when pwr_ind_11b_en == 0 then the 802.11g + MCS 0 level from target_power_index_mcs are used to + determine 802.11b transmit power level. + + However, when pwr_ind_11b_en == 1 then the index values in + pwr_ind_11b_0 & pwr_ind_11b_1 are used for 802.11b instead. + + This is all unconfirmed, if you can confirm then please update + this comment. + */ + uint8_t pwr_ind_11b_en; /* 0x60 */ + + /* 802.11b low data rate power index (0~5). + Sets the power level index for operation at 1 & 2Mbps + */ + uint8_t pwr_ind_11b_0; /* 0x61 */ + + /* 802.11b high data rate power index (0~5) + Sets the power level index for operation at 5.5 & 11Mbps + */ + uint8_t pwr_ind_11b_1; /* 0x62 */ + + uint8_t _unused63[8]; /* 0x63 - 0x6a */ + + /* Set the voltage of PA_VDD, which appears to be an internal analog + reference voltage(?) + + This field is called vdd33_const in the Arduino phy fields, + and relates to usage of the TOUT pin (ADC pin). + + Set to PA_VDD_MEASURE_VCC (0xFF) and leave TOUT (ADC) pin + floating in order to use the ADC to measure the 3.3V input + voltage. + + Set to value in the range 18-36 (1.8V to 3.6V) to set a + reference voltage(?) when using TOUT pin as an ADC input. I + think this is the reference voltage used to scale the 0-1V + which is allowed on the pin, in order to get an accurate + reading. So it should be set to a value that matches system + VCC... I think! + */ + uint8_t pa_vdd; /* 0x6b */ + + /* Disable RF calibration cycle for this many times */ + uint8_t disable_rfcal_count; /* 0x6c */ + + uint8_t _unused6d[3]; + + /* Flags for frequency correction + + A bitmask combination of any of: FREQ_CORRECT_DISABLE, + FREQ_CORRECT_ENABLE, FREQ_CORRECT_BB_160M, FREQ_CORRECT_FORCE + */ + uint8_t freq_correct_mode; /* 0x70 */ + + /* Force frequency offset adjustment (instead of auto measuring) + units are 1 = 8kHz, full range +/- 1016kHz. + + Only used if FREQ_CORRECT_ENABLE and FREQ_CORRECT_FORCE are + set in freq_correct_mode. + + Unclear whether setting FREQ_CORRECT_BB_160M (which allows only positive offsets) changes the usable range. + */ + int8_t force_freq_offset; /* 0x71 */ + + /* Use stored data in flash for RF calibration. + + This field was previously called rf_cal_use_flash. + + Acceptable values one of RF_CAL_MODE_SAVED, RF_CAL_MODE_TXPOWER_ONLY, RF_CAL_MODE_SAVED_2, RF_CAL_MODE_FULL. + */ + uint8_t rf_cal_mode; /* 0x72 */ + + uint8_t _unused73[13]; +} sdk_phy_info_t; + +/* Some sanity check static assertions. These can probably be + removed after this structure has been better tested. +*/ +_Static_assert(sizeof(sdk_phy_info_t) == 128, "sdk_phy_info_t is wrong size!"); +_Static_assert(offsetof(sdk_phy_info_t, version) == 5, "version at wrong offset"); +_Static_assert(offsetof(sdk_phy_info_t, target_power) == 34, "target_power_qdb at wrong offset"); +_Static_assert(offsetof(sdk_phy_info_t, bt_coexist_protocol) == 52, "bt_coexist_protocol at wrong offset"); +_Static_assert(offsetof(sdk_phy_info_t, spur_freq_2_primary) == 64, "spur_freq_2_primary at wrong offset"); +_Static_assert(offsetof(sdk_phy_info_t, lp_atten_stage01) == 94, "lp_atten_stage01 at wrong offset"); +_Static_assert(offsetof(sdk_phy_info_t, pa_vdd) == 107, "pa_vdd aka vdd33_const at wrong offset"); +_Static_assert(offsetof(sdk_phy_info_t, rf_cal_mode) == 114, "rf_cal_use_flash at wrong offset!"); + +/* Read the default PHY info into the supplied structure. + + This function is weak-aliased to get_sdk_default_phy_info() so you + can replace it with your own if you want to vary the default values + - suggested way to do this is to call get_sdk_default_phy_info() + and then only update the fields you care about. + + The default PHY info is used at startup whenever the version field + in the default sdk_phy_info_t does not match the version field + stored in flash. So you can increment the version field to force a + reset to defaults, regardless of what values are in flash. +*/ +void get_default_phy_info(sdk_phy_info_t *info); + +/* Read the "SDK default" PHY info as used by the Espressif SDK */ +void get_sdk_default_phy_info(sdk_phy_info_t *info); + +/* Read the PHY info currently stored in the SPI flash SDK configuration sector. + + This PHY info is updated by the SDK following RF calibration, etc. + + Note that the saved data may be corrupt - read the 'version' field to verify. +*/ +void read_saved_phy_info(sdk_phy_info_t *info); + +/* Update the saved PHY info in the SPI flash. A reset is necessary to use these values. + + Note that the SDK may clobber these values, so it's recommended you reset ASAP after updating them. +*/ +void write_saved_phy_info(const sdk_phy_info_t *info); + +/* Dump known fields in the phy info structure to stdout, + if 'raw' flag is set then the raw hex values are also dumped. +*/ +void dump_phy_info(const sdk_phy_info_t *info, bool raw); + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* PHY_INFO_H */ diff --git a/cpu/esp8266/vendor/esp/rom.h b/cpu/esp8266/vendor/esp/rom.h new file mode 100644 index 0000000000..71721c55a5 --- /dev/null +++ b/cpu/esp8266/vendor/esp/rom.h @@ -0,0 +1,57 @@ +/* "Boot ROM" function signatures + + Note that a lot of the ROM functions used in the IoT SDK aren't + referenced from the Espressif RTOS SDK, and are probably incompatible. + */ + +/* +Copyright (c) 2015, SuperHouse Automation 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: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef ROM_H +#define ROM_H + +#include "esp/types.h" +#include "flashchip.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void Cache_Read_Disable(void); + +/* http://esp8266-re.foogod.com/wiki/Cache_Read_Enable + + Note: when compiling non-OTA we use the ROM version of this + function, but for OTA we use the version in extras/rboot-ota that + maps the correct flash page for OTA support. + */ +void Cache_Read_Enable(uint32_t odd_even, uint32_t mb_count, uint32_t no_idea); + +/* Low-level SPI flash read/write routines */ +int Enable_QMode(sdk_flashchip_t *chip); +int Disable_QMode(sdk_flashchip_t *chip); +int SPI_page_program(sdk_flashchip_t *chip, uint32_t dest_addr, uint32_t *src_addr, uint32_t size); +int SPI_read_data(sdk_flashchip_t *chip, uint32_t src_addr, uint32_t *dest_addr, uint32_t size); +int SPI_write_enable(sdk_flashchip_t *chip); +int SPI_sector_erase(sdk_flashchip_t *chip, uint32_t addr); +int SPI_read_status(sdk_flashchip_t *chip, uint32_t *status); +int SPI_write_status(sdk_flashchip_t *chip, uint32_t status); +int Wait_SPI_Idle(sdk_flashchip_t *chip); + +#ifdef __cplusplus +} +#endif + +#endif /* ROM_H */ diff --git a/cpu/esp8266/vendor/esp/rtc_regs.h b/cpu/esp8266/vendor/esp/rtc_regs.h new file mode 100644 index 0000000000..8ad130d37d --- /dev/null +++ b/cpu/esp8266/vendor/esp/rtc_regs.h @@ -0,0 +1,130 @@ +/* esp/rtc_regs.h + * + * ESP8266 RTC register definitions + * + * Not compatible with ESP SDK register access code. + * + * RTC peripheral remains powered during deep sleep, and RTC clock + * is used to wake from deep sleep when RTC.COUNTER == RTC.COUNTER_ALARM. + * + * "GPIO16" is a special GPIO pin connected to the RTC subsystem, + * GPIO16 must be connected to reset to allow wake from deep sleep. + * + * The contents of scratch registers RTC.SCRATCH[] are preserved + * across reset, including wake from sleep (unconfirmed). Contents of + * RTCMEM are also preserved. + */ + +/* +Copyright (c) 2015, SuperHouse Automation 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: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef RTC_REGS_H +#define RTC_REGS_H + +#ifndef DOXYGEN + +#include "esp/types.h" +#include "common_macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define RTC_BASE 0x60000700 +#define RTC (*(struct RTC_REGS *)(RTC_BASE)) + +//FIXME: need to understand/clarify distinction between GPIO_CONF and GPIO_CFG[] +// Note: GPIO_CFG[3] is also known as PAD_XPD_DCDC_CONF in eagle_soc.h + +struct RTC_REGS { + uint32_t volatile CTRL0; // 0x00 + uint32_t volatile COUNTER_ALARM; // 0x04 + uint32_t volatile RESET_REASON0; // 0x08 //FIXME: need better name + uint32_t volatile _unknownc; // 0x0c + uint32_t volatile _unknown10; // 0x10 + uint32_t volatile RESET_REASON1; // 0x14 //FIXME: need better name + uint32_t volatile RESET_REASON2; // 0x18 //FIXME: need better name + uint32_t volatile COUNTER; // 0x1c + uint32_t volatile INT_SET; // 0x20 + uint32_t volatile INT_CLEAR; // 0x24 + uint32_t volatile INT_ENABLE; // 0x28 + uint32_t volatile _unknown2c; // 0x2c + uint32_t volatile SCRATCH[4]; // 0x30 - 3c + uint32_t volatile _unknown40; // 0x40 + uint32_t volatile _unknown44; // 0x44 + uint32_t volatile _unknown48; // 0x48 + uint32_t volatile _unknown4c[7]; // 0x4c - 0x64 + uint32_t volatile GPIO_OUT; // 0x68 + uint32_t volatile _unknown6c[2]; // 0x6c - 0x70 + uint32_t volatile GPIO_ENABLE; // 0x74 + uint32_t volatile _unknown80[5]; // 0x78 - 0x88 + uint32_t volatile GPIO_IN; // 0x8c + uint32_t volatile GPIO_CONF; // 0x90 + uint32_t volatile GPIO_CFG[6]; // 0x94 - 0xa8 +}; + +_Static_assert(sizeof(struct RTC_REGS) == 0xac, "RTC_REGS is the wrong size"); + +/* Details for CTRL0 register */ + +/* Writing this bit causes a software reset but + the device then fails in ets_main.c (needs other parameters set?) */ +#define RTC_CTRL0_BIT31 BIT(31) + +/* Details for RESET_REASONx registers */ + +/* The following are used in sdk_rtc_get_reset_reason(). Details are still a + * bit sketchy regarding exactly what they mean/do.. */ + +#define RTC_RESET_REASON1_CODE_M 0x0000000f +#define RTC_RESET_REASON1_CODE_S 0 + +#define RTC_RESET_REASON2_CODE_M 0x0000003f +#define RTC_RESET_REASON2_CODE_S 8 + +/* Writing this bit causes the ESP to go into some kind of unrecoverable boot loop */ +#define RTC_RESET_REASON0_BIT20 BIT(20) + +/* Both bits 20 & 21 can be set & cleared from software, + BIT21 appears to be checked inside sdk_rtc_get_reset_reason() */ +#define RTC_RESET_REASON0_BIT21 BIT(21) +#define RTC_RESET_REASON0_BIT22 BIT(22) + +/* Details for GPIO_CONF register */ + +#define RTC_GPIO_CONF_OUT_ENABLE BIT(0) + +/* Details for GPIO_CFG[3] register controlling GPIO16 (possibly others?) */ + +#define RTC_GPIO_CFG3_PIN_PULLUP BIT(2) +#define RTC_GPIO_CFG3_PIN_PULLDOWN BIT(3) +#define RTC_GPIO_CFG3_PIN_PULLUP_SLEEP BIT(4) +#define RTC_GPIO_CFG3_PIN_PULLDOWN_SLEEP BIT(5) + +/* The PIN_FUNC values here are probably similar to the + values used to set the iomux registers...? */ +#define RTC_GPIO_CFG3_PIN_FUNC_M 0x00000043 +#define RTC_GPIO_CFG3_PIN_FUNC_S 0 + +/* This should be the function value needed to have GPIO16 be the alarm + output from the RTC. FIXME: Needs to be validated. */ +#define RTC_GPIO_CFG3_PIN_FUNC_RTC_GPIO0 BIT(0) + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* RTC_REGS_H */ diff --git a/cpu/esp8266/vendor/esp/rtcmem_regs.h b/cpu/esp8266/vendor/esp/rtcmem_regs.h new file mode 100644 index 0000000000..ca7d0bdd15 --- /dev/null +++ b/cpu/esp8266/vendor/esp/rtcmem_regs.h @@ -0,0 +1,67 @@ +/* esp/rtcmem_regs.h + * + * ESP8266 RTC semi-persistent memory register definitions + * + * Not compatible with ESP SDK register access code. + */ + +/* +Copyright (c) 2015, SuperHouse Automation 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: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef RTCMEM_REGS_H +#define RTCMEM_REGS_H + +#include "esp/types.h" +#include "common_macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* The RTC memory is a range of 256 words (1 KB) of general-purpose memory + * within the Real Time Clock peripheral. Because it's part of the RTC, it + * continues to be powered (and retains its contents) even when the ESP8266 is + * in its deepest sleep mode (and other RAM is lost). It can therefore be + * useful for keeping data which must be persisted through sleep or a reset. + * + * Note, however, that it is not "battery backed", or flash memory, and thus + * will not keep its contents if power is removed entirely. + */ + +// We could just define these as 'volatile uint32_t *', but doing things this +// way means that the RTCMEM* defines will include array size information, so +// the C compiler can do bounds-checking for static arguments. + +typedef volatile uint32_t rtcmem_array64_t[64]; +typedef volatile uint32_t rtcmem_array128_t[128]; +typedef volatile uint32_t rtcmem_array256_t[256]; + +#define RTCMEM_BASE 0x60001000 + +/* RTCMEM is an array covering the entire semi-persistent memory range */ +#define RTCMEM (*(rtcmem_array256_t *)(RTCMEM_BASE)) + +/* RTCMEM_BACKUP / RTCMEM_SYSTEM / RTCMEM_USER are the same range, divided up + * into chunks by application/use, as defined by Espressif */ + +#define RTCMEM_BACKUP (*(rtcmem_array64_t *)(RTCMEM_BASE)) +#define RTCMEM_SYSTEM (*(rtcmem_array64_t *)(RTCMEM_BASE + 0x100)) +#define RTCMEM_USER (*(rtcmem_array128_t *)(RTCMEM_BASE + 0x200)) + +#ifdef __cplusplus +} +#endif + +#endif /* RTCMEM_REGS_H */ diff --git a/cpu/esp8266/vendor/esp/spi_regs.h b/cpu/esp8266/vendor/esp/spi_regs.h new file mode 100644 index 0000000000..58000fda88 --- /dev/null +++ b/cpu/esp8266/vendor/esp/spi_regs.h @@ -0,0 +1,271 @@ +/** esp/spi.h + * + * Configuration of SPI registers. + * + * Part of esp-open-rtos + * Copyright (C) 2015 Superhouse Automation Pty Ltd + * BSD Licensed as described in the file LICENSE + */ + +/* +Copyright (c) 2015, SuperHouse Automation 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: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef SPI_REGS_H +#define SPI_REGS_H + +#ifndef DOXYGEN + +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp/types.h" +#include "common_macros.h" + +/* Register definitions for the SPI peripherals on the ESP8266. + * + * There are twp SPI devices built into the ESP8266: + * SPI(0) is at 0x60000200 + * SPI(1) is at 0x60000100 + * (note that the device number order is reversed in memory) + * + * Each device is allocated a block of 64 32-bit registers (256 bytes of + * address space) to communicate with application code. + */ + +#define SPI_BASE 0x60000200 +#define SPI(i) (*(struct SPI_REGS *)(0x60000200 - (i)*0x100)) + +#define SPI0_BASE SPI_BASE +#define SPI1_BASE (SPI_BASE - 0x100) + +struct SPI_REGS { + uint32_t volatile CMD; // 0x00 + uint32_t volatile ADDR; // 0x04 + uint32_t volatile CTRL0; // 0x08 + uint32_t volatile CTRL1; // 0x0c + uint32_t volatile RSTATUS; // 0x10 + uint32_t volatile CTRL2; // 0x14 + uint32_t volatile CLOCK; // 0x18 + uint32_t volatile USER0; // 0x1c + uint32_t volatile USER1; // 0x20 + uint32_t volatile USER2; // 0x24 + uint32_t volatile WSTATUS; // 0x28 + uint32_t volatile PIN; // 0x2c + uint32_t volatile SLAVE0; // 0x30 + uint32_t volatile SLAVE1; // 0x34 + uint32_t volatile SLAVE2; // 0x38 + uint32_t volatile SLAVE3; // 0x3c + uint32_t volatile W[16]; // 0x40 - 0x7c + uint32_t volatile _unused[28]; // 0x80 - 0xec + uint32_t volatile EXT0; // 0xf0 + uint32_t volatile EXT1; // 0xf4 + uint32_t volatile EXT2; // 0xf8 + uint32_t volatile EXT3; // 0xfc +}; + +_Static_assert(sizeof(struct SPI_REGS) == 0x100, "SPI_REGS is the wrong size"); + +/* Details for CMD register */ + +#define SPI_CMD_READ BIT(31) +#define SPI_CMD_WRITE_ENABLE BIT(30) +#define SPI_CMD_WRITE_DISABLE BIT(29) +#define SPI_CMD_READ_ID BIT(28) +#define SPI_CMD_READ_SR BIT(27) +#define SPI_CMD_WRITE_SR BIT(26) +#define SPI_CMD_PP BIT(25) +#define SPI_CMD_SE BIT(24) +#define SPI_CMD_BE BIT(23) +#define SPI_CMD_CE BIT(22) +#define SPI_CMD_DP BIT(21) +#define SPI_CMD_RES BIT(20) +#define SPI_CMD_HPM BIT(19) +#define SPI_CMD_USR BIT(18) + +/* Details for CTRL0 register */ + +#define SPI_CTRL0_WR_BIT_ORDER BIT(26) +#define SPI_CTRL0_RD_BIT_ORDER BIT(25) +#define SPI_CTRL0_QIO_MODE BIT(24) +#define SPI_CTRL0_DIO_MODE BIT(23) +#define SPI_CTRL0_QOUT_MODE BIT(20) +#define SPI_CTRL0_DOUT_MODE BIT(14) +#define SPI_CTRL0_FASTRD_MODE BIT(13) +#define SPI_CTRL0_CLOCK_EQU_SYS_CLOCK BIT(12) +#define SPI_CTRL0_CLOCK_NUM_M 0x0000000F +#define SPI_CTRL0_CLOCK_NUM_S 8 +#define SPI_CTRL0_CLOCK_HIGH_M 0x0000000F +#define SPI_CTRL0_CLOCK_HIGH_S 4 +#define SPI_CTRL0_CLOCK_LOW_M 0x0000000F +#define SPI_CTRL0_CLOCK_LOW_S 0 + +/* Mask for the CLOCK_NUM/CLOCK_HIGH/CLOCK_LOW combined, in case one wants + * to set them all as a single value. + */ +#define SPI_CTRL0_CLOCK_M 0x00000FFF +#define SPI_CTRL0_CLOCK_S 0 + +/* Details for CTRL2 register */ + +#define SPI_CTRL2_CS_DELAY_NUM_M 0x0000000F +#define SPI_CTRL2_CS_DELAY_NUM_S 28 +#define SPI_CTRL2_CS_DELAY_MODE_M 0x00000003 +#define SPI_CTRL2_CS_DELAY_MODE_S 26 +#define SPI_CTRL2_MOSI_DELAY_NUM_M 0x00000007 +#define SPI_CTRL2_MOSI_DELAY_NUM_S 23 +#define SPI_CTRL2_MOSI_DELAY_MODE_M 0x00000003 +#define SPI_CTRL2_MOSI_DELAY_MODE_S 21 +#define SPI_CTRL2_MISO_DELAY_NUM_M 0x00000007 +#define SPI_CTRL2_MISO_DELAY_NUM_S 18 +#define SPI_CTRL2_MISO_DELAY_MODE_M 0x00000003 +#define SPI_CTRL2_MISO_DELAY_MODE_S 16 + +/* Details for CLOCK register */ + +#define SPI_CLOCK_EQU_SYS_CLOCK BIT(31) +#define SPI_CLOCK_DIV_PRE_M 0x00001FFF +#define SPI_CLOCK_DIV_PRE_S 18 +#define SPI_CLOCK_COUNT_NUM_M 0x0000003F +#define SPI_CLOCK_COUNT_NUM_S 12 +#define SPI_CLOCK_COUNT_HIGH_M 0x0000003F +#define SPI_CLOCK_COUNT_HIGH_S 6 +#define SPI_CLOCK_COUNT_LOW_M 0x0000003F +#define SPI_CLOCK_COUNT_LOW_S 0 + +/* Mask for the COUNT_NUM/COUNT_HIGH/COUNT_LOW combined, in case one wants + * to set them all as a single value. + */ +#define SPI_CTRL0_COUNT_M 0x0003FFFF +#define SPI_CTRL0_COUNT_S 0 + +/* Details for USER0 register */ + +#define SPI_USER0_COMMAND BIT(31) +#define SPI_USER0_ADDR BIT(30) +#define SPI_USER0_DUMMY BIT(29) +#define SPI_USER0_MISO BIT(28) +#define SPI_USER0_MOSI BIT(27) +#define SPI_USER0_MOSI_HIGHPART BIT(25) +#define SPI_USER0_MISO_HIGHPART BIT(24) +#define SPI_USER0_SIO BIT(16) +#define SPI_USER0_FWRITE_QIO BIT(15) +#define SPI_USER0_FWRITE_DIO BIT(14) +#define SPI_USER0_FWRITE_QUAD BIT(13) +#define SPI_USER0_FWRITE_DUAL BIT(12) +#define SPI_USER0_WR_BYTE_ORDER BIT(11) +#define SPI_USER0_RD_BYTE_ORDER BIT(10) +#define SPI_USER0_CLOCK_OUT_EDGE BIT(7) +#define SPI_USER0_CLOCK_IN_EDGE BIT(6) +#define SPI_USER0_CS_SETUP BIT(5) +#define SPI_USER0_CS_HOLD BIT(4) +#define SPI_USER0_FLASH_MODE BIT(2) +#define SPI_USER0_DUPLEX BIT(0) + +/* Details for USER1 register */ + +#define SPI_USER1_ADDR_BITLEN_M 0x0000003F +#define SPI_USER1_ADDR_BITLEN_S 26 +#define SPI_USER1_MOSI_BITLEN_M 0x000001FF +#define SPI_USER1_MOSI_BITLEN_S 17 +#define SPI_USER1_MISO_BITLEN_M 0x000001FF +#define SPI_USER1_MISO_BITLEN_S 8 +#define SPI_USER1_DUMMY_CYCLELEN_M 0x000000FF +#define SPI_USER1_DUMMY_CYCLELEN_S 0 + +/* Details for USER2 register */ + +#define SPI_USER2_COMMAND_BITLEN_M 0x0000000F +#define SPI_USER2_COMMAND_BITLEN_S 28 +#define SPI_USER2_COMMAND_VALUE_M 0x0000FFFF +#define SPI_USER2_COMMAND_VALUE_S 0 + +/* Details for PIN register */ + +#define SPI_PIN_IDLE_EDGE BIT(29) ///< CPOL +#define SPI_PIN_CS2_DISABLE BIT(2) +#define SPI_PIN_CS1_DISABLE BIT(1) +#define SPI_PIN_CS0_DISABLE BIT(0) + +/* Details for SLAVE0 register */ + +#define SPI_SLAVE0_SYNC_RESET BIT(31) +#define SPI_SLAVE0_MODE BIT(30) +#define SPI_SLAVE0_WR_RD_BUF_EN BIT(29) +#define SPI_SLAVE0_WR_RD_STA_EN BIT(28) +#define SPI_SLAVE0_CMD_DEFINE BIT(27) +#define SPI_SLAVE0_TRANS_COUNT_M 0x0000000F +#define SPI_SLAVE0_TRANS_COUNT_S 23 +#define SPI_SLAVE0_TRANS_DONE_EN BIT(9) +#define SPI_SLAVE0_WR_STA_DONE_EN BIT(8) +#define SPI_SLAVE0_RD_STA_DONE_EN BIT(7) +#define SPI_SLAVE0_WR_BUF_DONE_EN BIT(6) +#define SPI_SLAVE0_RD_BUF_DONE_EN BIT(5) +#define SPI_SLAVE0_INT_EN_M 0x0000001f +#define SPI_SLAVE0_INT_EN_S 5 +#define SPI_SLAVE0_TRANS_DONE BIT(4) +#define SPI_SLAVE0_WR_STA_DONE BIT(3) +#define SPI_SLAVE0_RD_STA_DONE BIT(2) +#define SPI_SLAVE0_WR_BUF_DONE BIT(1) +#define SPI_SLAVE0_RD_BUF_DONE BIT(0) + +/* Details for SLAVE1 register */ + +#define SPI_SLAVE1_STATUS_BITLEN_M 0x0000001F +#define SPI_SLAVE1_STATUS_BITLEN_S 27 +#define SPI_SLAVE1_BUF_BITLEN_M 0x000001FF +#define SPI_SLAVE1_BUF_BITLEN_S 16 +#define SPI_SLAVE1_RD_ADDR_BITLEN_M 0x0000003F +#define SPI_SLAVE1_RD_ADDR_BITLEN_S 10 +#define SPI_SLAVE1_WR_ADDR_BITLEN_M 0x0000003F +#define SPI_SLAVE1_WR_ADDR_BITLEN_S 4 +#define SPI_SLAVE1_WRSTA_DUMMY_ENABLE BIT(3) +#define SPI_SLAVE1_RDSTA_DUMMY_ENABLE BIT(2) +#define SPI_SLAVE1_WRBUF_DUMMY_ENABLE BIT(1) +#define SPI_SLAVE1_RDBUF_DUMMY_ENABLE BIT(0) + +/* Details for SLAVE2 register */ + +#define SPI_SLAVE2_WRBUF_DUMMY_CYCLELEN_M 0x000000FF +#define SPI_SLAVE2_WRBUF_DUMMY_CYCLELEN_S 24 +#define SPI_SLAVE2_RDBUF_DUMMY_CYCLELEN_M 0x000000FF +#define SPI_SLAVE2_RDBUF_DUMMY_CYCLELEN_S 16 +#define SPI_SLAVE2_WRSTR_DUMMY_CYCLELEN_M 0x000000FF +#define SPI_SLAVE2_WRSTR_DUMMY_CYCLELEN_S 8 +#define SPI_SLAVE2_RDSTR_DUMMY_CYCLELEN_M 0x000000FF +#define SPI_SLAVE2_RDSTR_DUMMY_CYCLELEN_S 0 + +/* Details for SLAVE3 register */ + +#define SPI_SLAVE3_WRSTA_CMD_VALUE_M 0x000000FF +#define SPI_SLAVE3_WRSTA_CMD_VALUE_S 24 +#define SPI_SLAVE3_RDSTA_CMD_VALUE_M 0x000000FF +#define SPI_SLAVE3_RDSTA_CMD_VALUE_S 16 +#define SPI_SLAVE3_WRBUF_CMD_VALUE_M 0x000000FF +#define SPI_SLAVE3_WRBUF_CMD_VALUE_S 8 +#define SPI_SLAVE3_RDBUF_CMD_VALUE_M 0x000000FF +#define SPI_SLAVE3_RDBUF_CMD_VALUE_S 0 + +/* Details for EXT3 register */ + +#define SPI_EXT3_INT_HOLD_ENABLE_M 0x00000003 +#define SPI_EXT3_INT_HOLD_ENABLE_S 0 + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* SPI_REGS_H */ diff --git a/cpu/esp8266/vendor/esp/spiflash.c b/cpu/esp8266/vendor/esp/spiflash.c new file mode 100644 index 0000000000..20b7d1b87d --- /dev/null +++ b/cpu/esp8266/vendor/esp/spiflash.c @@ -0,0 +1,267 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 sheinz (https://github.com/sheinz) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifdef RIOT_VERSION +#include "esp/spiflash.h" +#include "esp/flashchip.h" +#include "esp/rom.h" +#include "esp/spi_regs.h" +#include "esp/FreeRTOS.h" +#else +#include "include/spiflash.h" +#include "include/flashchip.h" +#include "include/esp/rom.h" +#include "include/esp/spi_regs.h" +#include +#endif + +#include + +/** + * Note about Wait_SPI_Idle. + * + * Each write/erase flash operation sets BUSY bit in flash status register. + * If attempt to access flash while BUSY bit is set operation will fail. + * Function Wait_SPI_Idle loops until this bit is not cleared. + * + * The approach in the following code is that each write function that is + * accessible from the outside should leave flash in Idle state. + * The read operations doesn't set BUSY bit in a flash. So they do not wait. + * They relay that previous operation is completely finished. + * + * This approach is different from ESP8266 bootrom where Wait_SPI_Idle is + * called where it needed and not. + */ + +#define SPI_WRITE_MAX_SIZE 64 + +// 64 bytes read causes hang +// http://bbs.espressif.com/viewtopic.php?f=6&t=2439 +#define SPI_READ_MAX_SIZE 60 + + +/** + * Low level SPI flash write. Write block of data up to 64 bytes. + */ +static inline void IRAM spi_write_data(sdk_flashchip_t *chip, uint32_t addr, + uint8_t *buf, uint32_t size) +{ + uint32_t words = size >> 2; + if (size & 0b11) { + words++; + } + + Wait_SPI_Idle(chip); // wait for previous write to finish + + SPI(0).ADDR = (addr & 0x00FFFFFF) | (size << 24); + + memcpy((void*)SPI(0).W, buf, words<<2); + + __asm__ volatile("memw"); + + SPI_write_enable(chip); + + SPI(0).CMD = SPI_CMD_PP; + while (SPI(0).CMD) {} +} + +/** + * Write a page of flash. Data block should not cross page boundary. + */ +static bool IRAM spi_write_page(sdk_flashchip_t *flashchip, uint32_t dest_addr, + uint8_t *buf, uint32_t size) +{ + // check if block to write doesn't cross page boundary + if (flashchip->page_size < size + (dest_addr % flashchip->page_size)) { + return false; + } + + if (size < 1) { + return true; + } + + while (size >= SPI_WRITE_MAX_SIZE) { + spi_write_data(flashchip, dest_addr, buf, SPI_WRITE_MAX_SIZE); + + size -= SPI_WRITE_MAX_SIZE; + dest_addr += SPI_WRITE_MAX_SIZE; + buf += SPI_WRITE_MAX_SIZE; + + if (size < 1) { + return true; + } + } + + spi_write_data(flashchip, dest_addr, buf, size); + + return true; +} + +/** + * Split block of data into pages and write pages. + */ +static bool IRAM spi_write(uint32_t addr, uint8_t *dst, uint32_t size) +{ + if (sdk_flashchip.chip_size < (addr + size)) { + return false; + } + + uint32_t write_bytes_to_page = sdk_flashchip.page_size - + (addr % sdk_flashchip.page_size); // TODO: place for optimization + + if (size < write_bytes_to_page) { + if (!spi_write_page(&sdk_flashchip, addr, dst, size)) { + return false; + } + } else { + if (!spi_write_page(&sdk_flashchip, addr, dst, write_bytes_to_page)) { + return false; + } + + uint32_t offset = write_bytes_to_page; + uint32_t pages_to_write = (size - offset) / sdk_flashchip.page_size; + for (uint32_t i = 0; i < pages_to_write; i++) { + if (!spi_write_page(&sdk_flashchip, addr + offset, + dst + offset, sdk_flashchip.page_size)) { + return false; + } + offset += sdk_flashchip.page_size; + } + + if (!spi_write_page(&sdk_flashchip, addr + offset, + dst + offset, size - offset)) { + return false; + } + } + + return true; +} + +bool IRAM spiflash_write(uint32_t addr, uint8_t *buf, uint32_t size) +{ + bool result = false; + + if (buf) { + vPortEnterCritical(); + Cache_Read_Disable(); + + result = spi_write(addr, buf, size); + + // make sure all write operations is finished before exiting + Wait_SPI_Idle(&sdk_flashchip); + + Cache_Read_Enable(0, 0, 1); + vPortExitCritical(); + } + + return result; +} + +/** + * Read SPI flash up to 64 bytes. + */ +static inline void IRAM read_block(sdk_flashchip_t *chip, uint32_t addr, + uint8_t *buf, uint32_t size) +{ + SPI(0).ADDR = (addr & 0x00FFFFFF) | (size << 24); + SPI(0).CMD = SPI_CMD_READ; + + while (SPI(0).CMD) {}; + + __asm__ volatile("memw"); + + memcpy(buf, (const void*)SPI(0).W, size); +} + +/** + * Read SPI flash data. Data region doesn't need to be page aligned. + */ +static inline bool IRAM read_data(sdk_flashchip_t *flashchip, uint32_t addr, + uint8_t *dst, uint32_t size) +{ + if (size < 1) { + return true; + } + + if ((addr + size) > flashchip->chip_size) { + return false; + } + + while (size >= SPI_READ_MAX_SIZE) { + read_block(flashchip, addr, dst, SPI_READ_MAX_SIZE); + dst += SPI_READ_MAX_SIZE; + size -= SPI_READ_MAX_SIZE; + addr += SPI_READ_MAX_SIZE; + } + + if (size > 0) { + read_block(flashchip, addr, dst, size); + } + + return true; +} + +bool IRAM spiflash_read(uint32_t dest_addr, uint8_t *buf, uint32_t size) +{ + bool result = false; + + if (buf) { + vPortEnterCritical(); + Cache_Read_Disable(); + + result = read_data(&sdk_flashchip, dest_addr, buf, size); + + Cache_Read_Enable(0, 0, 1); + vPortExitCritical(); + } + + return result; +} + +bool IRAM spiflash_erase_sector(uint32_t addr) +{ + if ((addr + sdk_flashchip.sector_size) > sdk_flashchip.chip_size) { + return false; + } + + if (addr & 0xFFF) { + return false; + } + + vPortEnterCritical(); + Cache_Read_Disable(); + + SPI_write_enable(&sdk_flashchip); + + SPI(0).ADDR = addr & 0x00FFFFFF; + SPI(0).CMD = SPI_CMD_SE; + while (SPI(0).CMD) {}; + + Wait_SPI_Idle(&sdk_flashchip); + + Cache_Read_Enable(0, 0, 1); + vPortExitCritical(); + + return true; +} diff --git a/cpu/esp8266/vendor/esp/spiflash.h b/cpu/esp8266/vendor/esp/spiflash.h new file mode 100644 index 0000000000..bf93f629dd --- /dev/null +++ b/cpu/esp8266/vendor/esp/spiflash.h @@ -0,0 +1,72 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 sheinz (https://github.com/sheinz) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef SPIFLASH_H +#define SPIFLASH_H + +#include +#include +#include "common_macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPI_FLASH_SECTOR_SIZE 4096 + +/** + * Read data from SPI flash. + * + * @param addr Address to read from. Can be not aligned. + * @param buf Buffer to read to. Doesn't have to be aligned. + * @param size Size of data to read. Buffer size must be >= than data size. + * + * @return true if success, otherwise false + */ +bool IRAM spiflash_read(uint32_t addr, uint8_t *buf, uint32_t size); + +/** + * Write data to SPI flash. + * + * @param addr Address to write to. Can be not aligned. + * @param buf Buffer of data to write to flash. Doesn't have to be aligned. + * @param size Size of data to write. Buffer size must be >= than data size. + * + * @return true if success, otherwise false + */ +bool IRAM spiflash_write(uint32_t addr, uint8_t *buf, uint32_t size); + +/** + * Erase a sector. + * + * @param addr Address of sector to erase. Must be sector aligned. + * + * @return true if success, otherwise false + */ +bool IRAM spiflash_erase_sector(uint32_t addr); + +#ifdef __cplusplus +} +#endif + +#endif /* SPIFLASH_H */ diff --git a/cpu/esp8266/vendor/esp/timer_regs.h b/cpu/esp8266/vendor/esp/timer_regs.h new file mode 100644 index 0000000000..5b299684c8 --- /dev/null +++ b/cpu/esp8266/vendor/esp/timer_regs.h @@ -0,0 +1,151 @@ +/* esp/timer_regs.h + * + * ESP8266 Timer register definitions + * + * Not compatible with ESP SDK register access code. + */ + +/* +Copyright (c) 2015, SuperHouse Automation 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: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef TIMER_REGS_H +#define TIMER_REGS_H + +#ifndef DOXYGEN + +#include "esp/types.h" +#include "common_macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TIMER_BASE 0x60000600 +#define TIMER(i) (*(struct TIMER_REGS *)(TIMER_BASE + (i)*0x20)) +#define TIMER_FRC1 TIMER(0) +#define TIMER_FRC2 TIMER(1) + +/* TIMER registers + * + * ESP8266 has two hardware timer counters, FRC1 and FRC2. + * + * FRC1 is a 24-bit countdown timer, triggers interrupt when reaches zero. + * FRC2 is a 32-bit countup timer, can set a variable match value to trigger an interrupt. + * + * FreeRTOS tick timer appears to come from XTensa core tick timer0, + * not either of these. FRC2 is used in the FreeRTOS SDK however. It + * is set to free-run, interrupting periodically via updates to the + * ALARM register. sdk_ets_timer_init configures FRC2 and assigns FRC2 + * interrupt handler at sdk_vApplicationTickHook+0x68 + */ + +struct TIMER_REGS { // FRC1 FRC2 + uint32_t volatile LOAD; // 0x00 0x20 + uint32_t volatile COUNT; // 0x04 0x24 + uint32_t volatile CTRL; // 0x08 0x28 + uint32_t volatile STATUS; // 0x0c 0x2c + uint32_t volatile ALARM; // 0x30 +}; + +_Static_assert(sizeof(struct TIMER_REGS) == 0x14, "TIMER_REGS is the wrong size"); + +#define TIMER_FRC1_MAX_LOAD 0x7fffff + +/* Details for LOAD registers */ + +/* Behavior for FRC1: + * + * When TIMER_CTRL_RELOAD is cleared in TIMER(0).CTRL, FRC1 will + * reload to its max value once underflowed (unless the load + * value is rewritten in the interrupt handler.) + * + * When TIMER_CTRL_RELOAD is set in TIMER(0).CTRL, FRC1 will reload + * from the load register value once underflowed. + * + * Behavior for FRC2: + * + * If TIMER_CTRL_RELOAD is cleared in TIMER(1).CTRL, writing to + * this register will update the FRC2 COUNT value. + * + * If TIMER_CTRL_RELOAD is set in TIMER(1).CTRL, the behaviour + * appears to be the same except that writing 0 to the load register + * both sets the COUNT register to 0 and disables the timer, even if + * the TIMER_CTRL_RUN bit is set. + * + * Offsets 0x34, 0x38, 0x3c all seem to read back the LOAD_REG value + * also (but have no known function.) + */ + +/* Details for CTRL registers */ + +/* Observed behaviour is like this: + * + * * When TIMER_CTRL_INT_HOLD is set, the interrupt status bit + * TIMER_CTRL_INT_STATUS remains set when the timer interrupt + * triggers, unless manually cleared by writing 0 to + * TIMER(x).STATUS. While the interrupt status bit stays set + * the timer will continue to run normally, but the interrupt + * (INUM_TIMER_FRC1 or INUM_TIMER_FRC2) won't trigger again. + * + * * When TIMER_CTRL_INT_HOLD is cleared (default), there's no need to + * manually write to TIMER(x).STATUS. The interrupt status bit + * TIMER_CTRL_INT_STATUS automatically clears after the interrupt + * triggers, and the interrupt handler will run again + * automatically. + */ + +/* The values for TIMER_CTRL_CLKDIV control how many CPU clock cycles amount to + * one timer clock cycle. For valid values, see the timer_clkdiv_t enum below. + */ + +/* TIMER_CTRL_INT_STATUS gets set when interrupt fires, and cleared on a write + * to TIMER(x).STATUS (or cleared automatically if TIMER_CTRL_INT_HOLD is not + * set). + */ + +#define TIMER_CTRL_INT_HOLD BIT(0) +#define TIMER_CTRL_CLKDIV_M 0x00000003 +#define TIMER_CTRL_CLKDIV_S 2 +#define TIMER_CTRL_RELOAD BIT(6) +#define TIMER_CTRL_RUN BIT(7) +#define TIMER_CTRL_INT_STATUS BIT(8) + +typedef enum { + TIMER_CLKDIV_1 = 0, + TIMER_CLKDIV_16 = 1, + TIMER_CLKDIV_256 = 2, +} timer_clkdiv_t; + +/* Details for STATUS registers */ + +/* Reading this register always returns the value in + * TIMER(x).LOAD + * + * Writing zero to this register clears the FRC1 + * interrupt status. + */ + +/* Details for FRC2.ALARM register */ + +/* Interrupt match value for FRC2. When COUNT == ALARM, + the interrupt fires. +*/ + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* TIMER_REGS_H */ diff --git a/cpu/esp8266/vendor/esp/types.h b/cpu/esp8266/vendor/esp/types.h new file mode 100644 index 0000000000..a83a796d51 --- /dev/null +++ b/cpu/esp8266/vendor/esp/types.h @@ -0,0 +1,33 @@ +/* +Copyright (c) 2015, SuperHouse Automation 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: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef TYPES_H +#define TYPES_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef volatile uint32_t *esp_reg_t; + +#ifdef __cplusplus +} +#endif + +#endif /* TYPES_H */ diff --git a/cpu/esp8266/vendor/esp/uart_regs.h b/cpu/esp8266/vendor/esp/uart_regs.h new file mode 100644 index 0000000000..86df492971 --- /dev/null +++ b/cpu/esp8266/vendor/esp/uart_regs.h @@ -0,0 +1,211 @@ +/** esp/uart.h + * + * Configuration of UART registers. + * + * Part of esp-open-rtos + * Copyright (C) 2015 Superhouse Automation Pty Ltd + * BSD Licensed as described in the file LICENSE + */ + +/* +Copyright (c) 2015, SuperHouse Automation 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: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ +#ifndef UART_REGS_H +#define UART_REGS_H + +#ifndef DOXYGEN + +#include "esp/types.h" +#include "common_macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Register definitions for the UART peripherals on the ESP8266. + * + * There are twp UART devices built into the ESP8266: + * UART(0) is at 0x60000000 + * UART(1) is at 0x60000F00 + * + * Each device is allocated a block of 64 32-bit registers (256 bytes of + * address space) to communicate with application code. + */ + +#define UART_BASE 0x60000000 +#define UART(i) (*(struct UART_REGS *)(UART_BASE + (i)*0xf00)) + +#define UART0_BASE UART_BASE +#define UART1_BASE (UART_BASE + 0xf00) + +struct UART_REGS { + uint32_t volatile FIFO; // 0x00 + uint32_t volatile INT_RAW; // 0x04 + uint32_t volatile INT_STATUS; // 0x08 + uint32_t volatile INT_ENABLE; // 0x0c + uint32_t volatile INT_CLEAR; // 0x10 + uint32_t volatile CLOCK_DIVIDER; // 0x14 + uint32_t volatile AUTOBAUD; // 0x18 + uint32_t volatile STATUS; // 0x1c + uint32_t volatile CONF0; // 0x20 + uint32_t volatile CONF1; // 0x24 + uint32_t volatile LOW_PULSE; // 0x28 + uint32_t volatile HIGH_PULSE; // 0x2c + uint32_t volatile PULSE_COUNT; // 0x30 + uint32_t volatile _unused[17]; // 0x34 - 0x74 + uint32_t volatile DATE; // 0x78 + uint32_t volatile ID; // 0x7c +}; + +_Static_assert(sizeof(struct UART_REGS) == 0x80, "UART_REGS is the wrong size"); + +/* Details for FIFO register */ + +#define UART_FIFO_DATA_M 0x000000ff +#define UART_FIFO_DATA_S 0 + +/* Details for INT_RAW register */ + +#define UART_INT_RAW_RXFIFO_TIMEOUT BIT(8) +#define UART_INT_RAW_BREAK_DETECTED BIT(7) +#define UART_INT_RAW_CTS_CHANGED BIT(6) +#define UART_INT_RAW_DSR_CHANGED BIT(5) +#define UART_INT_RAW_RXFIFO_OVERFLOW BIT(4) +#define UART_INT_RAW_FRAMING_ERR BIT(3) +#define UART_INT_RAW_PARITY_ERR BIT(2) +#define UART_INT_RAW_TXFIFO_EMPTY BIT(1) +#define UART_INT_RAW_RXFIFO_FULL BIT(0) + +/* Details for INT_STATUS register */ + +#define UART_INT_STATUS_RXFIFO_TIMEOUT BIT(8) +#define UART_INT_STATUS_BREAK_DETECTED BIT(7) +#define UART_INT_STATUS_CTS_CHANGED BIT(6) +#define UART_INT_STATUS_DSR_CHANGED BIT(5) +#define UART_INT_STATUS_RXFIFO_OVERFLOW BIT(4) +#define UART_INT_STATUS_FRAMING_ERR BIT(3) +#define UART_INT_STATUS_PARITY_ERR BIT(2) +#define UART_INT_STATUS_TXFIFO_EMPTY BIT(1) +#define UART_INT_STATUS_RXFIFO_FULL BIT(0) + +/* Details for INT_ENABLE register */ + +#define UART_INT_ENABLE_RXFIFO_TIMEOUT BIT(8) +#define UART_INT_ENABLE_BREAK_DETECTED BIT(7) +#define UART_INT_ENABLE_CTS_CHANGED BIT(6) +#define UART_INT_ENABLE_DSR_CHANGED BIT(5) +#define UART_INT_ENABLE_RXFIFO_OVERFLOW BIT(4) +#define UART_INT_ENABLE_FRAMING_ERR BIT(3) +#define UART_INT_ENABLE_PARITY_ERR BIT(2) +#define UART_INT_ENABLE_TXFIFO_EMPTY BIT(1) +#define UART_INT_ENABLE_RXFIFO_FULL BIT(0) + +/* Details for INT_CLEAR register */ + +#define UART_INT_CLEAR_RXFIFO_TIMEOUT BIT(8) +#define UART_INT_CLEAR_BREAK_DETECTED BIT(7) +#define UART_INT_CLEAR_CTS_CHANGED BIT(6) +#define UART_INT_CLEAR_DSR_CHANGED BIT(5) +#define UART_INT_CLEAR_RXFIFO_OVERFLOW BIT(4) +#define UART_INT_CLEAR_FRAMING_ERR BIT(3) +#define UART_INT_CLEAR_PARITY_ERR BIT(2) +#define UART_INT_CLEAR_TXFIFO_EMPTY BIT(1) +#define UART_INT_CLEAR_RXFIFO_FULL BIT(0) + +/* Details for CLOCK_DIVIDER register */ + +#define UART_CLOCK_DIVIDER_VALUE_M 0x000fffff +#define UART_CLOCK_DIVIDER_VALUE_S 0 + +/* Details for AUTOBAUD register */ + +#define UART_AUTOBAUD_GLITCH_FILTER_M 0x000000FF +#define UART_AUTOBAUD_GLITCH_FILTER_S 8 +#define UART_AUTOBAUD_ENABLE BIT(0) + +/* Details for STATUS register */ + +#define UART_STATUS_TXD BIT(31) +#define UART_STATUS_RTS BIT(30) +#define UART_STATUS_DTR BIT(29) +#define UART_STATUS_TXFIFO_COUNT_M 0x000000ff +#define UART_STATUS_TXFIFO_COUNT_S 16 +#define UART_STATUS_RXD BIT(15) +#define UART_STATUS_CTS BIT(14) +#define UART_STATUS_DSR BIT(13) +#define UART_STATUS_RXFIFO_COUNT_M 0x000000ff +#define UART_STATUS_RXFIFO_COUNT_S 0 + +/* Details for CONF0 register */ + +#define UART_CONF0_DTR_INVERTED BIT(24) +#define UART_CONF0_RTS_INVERTED BIT(23) +#define UART_CONF0_TXD_INVERTED BIT(22) +#define UART_CONF0_DSR_INVERTED BIT(21) +#define UART_CONF0_CTS_INVERTED BIT(20) +#define UART_CONF0_RXD_INVERTED BIT(19) +#define UART_CONF0_TXFIFO_RESET BIT(18) +#define UART_CONF0_RXFIFO_RESET BIT(17) +#define UART_CONF0_IRDA_ENABLE BIT(16) +#define UART_CONF0_TX_FLOW_ENABLE BIT(15) +#define UART_CONF0_LOOPBACK BIT(14) +#define UART_CONF0_IRDA_RX_INVERTED BIT(13) +#define UART_CONF0_IRDA_TX_INVERTED BIT(12) +#define UART_CONF0_IRDA_WCTL BIT(11) +#define UART_CONF0_IRDA_TX_ENABLE BIT(10) +#define UART_CONF0_IRDA_DUPLEX BIT(9) +#define UART_CONF0_TXD_BREAK BIT(8) +#define UART_CONF0_SW_DTR BIT(7) +#define UART_CONF0_SW_RTS BIT(6) +#define UART_CONF0_STOP_BITS_M 0x00000003 +#define UART_CONF0_STOP_BITS_S 4 +#define UART_CONF0_BYTE_LEN_M 0x00000003 +#define UART_CONF0_BYTE_LEN_S 2 +#define UART_CONF0_PARITY_ENABLE BIT(1) +#define UART_CONF0_PARITY BIT(0) //FIXME: does this indicate odd or even? + +/* Details for CONF1 register */ + +#define UART_CONF1_RX_TIMEOUT_ENABLE BIT(31) +#define UART_CONF1_RX_TIMEOUT_THRESHOLD_M 0x0000007f +#define UART_CONF1_RX_TIMEOUT_THRESHOLD_S 24 +#define UART_CONF1_RX_FLOWCTRL_ENABLE BIT(23) +#define UART_CONF1_RX_FLOWCTRL_THRESHOLD_M 0x0000007f +#define UART_CONF1_RX_FLOWCTRL_THRESHOLD_S 16 +#define UART_CONF1_TXFIFO_EMPTY_THRESHOLD_M 0x0000007f +#define UART_CONF1_TXFIFO_EMPTY_THRESHOLD_S 8 +#define UART_CONF1_RXFIFO_FULL_THRESHOLD_M 0x0000007f +#define UART_CONF1_RXFIFO_FULL_THRESHOLD_S 0 + +/* Details for LOW_PULSE register */ + +#define UART_LOW_PULSE_MIN_M 0x000fffff +#define UART_LOW_PULSE_MIN_S 0 + +/* Details for HIGH_PULSE register */ + +#define UART_HIGH_PULSE_MIN_M 0x000fffff +#define UART_HIGH_PULSE_MIN_S 0 + +/* Details for PULSE_COUNT register */ + +#define UART_PULSE_COUNT_VALUE_M 0x000003ff +#define UART_PULSE_COUNT_VALUE_S 0 + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* UART_REGS_H */ diff --git a/cpu/esp8266/vendor/esp/wdev_regs.h b/cpu/esp8266/vendor/esp/wdev_regs.h new file mode 100644 index 0000000000..e832b5e887 --- /dev/null +++ b/cpu/esp8266/vendor/esp/wdev_regs.h @@ -0,0 +1,67 @@ +/* esp/wdev_regs.h + * + * ESP8266 register definitions for the "wdev" region (0x3FF2xxx) + * + * In the DPORT memory space, alongside DPORT regs. However mostly + * concerned with the WiFi hardware interface. + * + * Not compatible with ESP SDK register access code. + */ + +/* +Copyright (c) 2015, SuperHouse Automation 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: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef WDEV_REGS_H +#define WDEV_REGS_H + +#ifndef DOXYGEN + +#include "esp/types.h" +#include "common_macros.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WDEV_BASE 0x3FF20000 +#define WDEV (*(struct WDEV_REGS *)(WDEV_BASE)) + +/* Note: This memory region is not currently well understood. Pretty much all + * of the definitions here are from reverse-engineering the Espressif SDK code, + * many are just educated guesses, and almost certainly some are misleading or + * wrong. If you can improve on any of this, please contribute! + */ + +struct WDEV_REGS { + uint32_t volatile _unknown0[768]; // 0x0000 - 0x0bfc + uint32_t volatile SYS_TIME; // 0x0c00 + uint32_t volatile _unknown1[144]; // 0x0c04 - 0x0e40 + uint32_t volatile HWRNG; // 0xe44 HW RNG, see http://esp8266-re.foogod.com/wiki/Random_Number_Generator +} __attribute__ (( packed )); + +_Static_assert(sizeof(struct WDEV_REGS) == 0xe48, "WDEV_REGS is the wrong size"); + +/* Extra paranoid check about the HWRNG address, as if this becomes + wrong there will be no obvious symptoms apart from a lack of + entropy. +*/ +_Static_assert(&WDEV.HWRNG == (void*)0x3FF20E44, "HWRNG register is at wrong address"); + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* WDEV_REGS_H */ diff --git a/cpu/esp8266/vendor/esp/xtensa_ops.h b/cpu/esp8266/vendor/esp/xtensa_ops.h new file mode 100644 index 0000000000..12006843aa --- /dev/null +++ b/cpu/esp8266/vendor/esp/xtensa_ops.h @@ -0,0 +1,65 @@ +/** xtensa_ops.h + * + * Special macros/etc which deal with Xtensa-specific architecture/CPU + * considerations. + * + * Part of esp-open-rtos + * Copyright (C) 2015 Superhouse Automation Pty Ltd + * BSD Licensed as described in the file LICENSE + */ + +/* +Copyright (c) 2015, SuperHouse Automation 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: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. 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. + +3. Neither the name of the copyright holder 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. +*/ + +#ifndef XTENSA_OPS_H +#define XTENSA_OPS_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Read stack pointer to variable. + * + * Note that the compiler will push a stack frame (minimum 16 bytes) + * in the prelude of a C function that calls any other functions. + */ +#define SP(var) __asm__ volatile ("mov %0, a1" : "=r" (var)) + +/* Read the function return address to a variable. + * + * Depends on the containing function being simple enough that a0 is + * being used as a working register. + */ +#define RETADDR(var) __asm__ volatile ("mov %0, a0" : "=r" (var)) + +// GCC macros for reading, writing, and exchanging Xtensa processor special +// registers: + +#define RSR(var, reg) __asm__ volatile ("rsr %0, " #reg : "=r" (var)); +#define WSR(var, reg) __asm__ volatile ("wsr %0, " #reg : : "r" (var)); +#define XSR(var, reg) __asm__ volatile ("xsr %0, " #reg : "+r" (var)); + +// GCC macros for performing associated "*sync" opcodes + +#define ISYNC() __asm__ volatile ( "isync" ) +#define RSYNC() __asm__ volatile ( "rsync" ) +#define ESYNC() __asm__ volatile ( "esync" ) +#define DSYNC() __asm__ volatile ( "dsync" ) + +#ifdef __cplusplus +} +#endif + +#endif /* XTENSA_OPS_H */ diff --git a/cpu/esp8266/vendor/espressif/README.md b/cpu/esp8266/vendor/espressif/README.md new file mode 100644 index 0000000000..4507ffe490 --- /dev/null +++ b/cpu/esp8266/vendor/espressif/README.md @@ -0,0 +1 @@ +The files in this directory are either from the [ESP8266_NONOS_SDK](https://github.com/espressif/ESP8266_NONOS_SDK.git) or from the [ESP_RTOS_SDK](https://github.com/espressif/ESP8266_RTOS_SDK.git) for ESP8266. All of these files are copyright of Espressif Systems (Shanghai) Pte., Ltd. Please note the copyright notice in these files. diff --git a/cpu/esp8266/vendor/espressif/c_types.h b/cpu/esp8266/vendor/espressif/c_types.h new file mode 100644 index 0000000000..c712044bb7 --- /dev/null +++ b/cpu/esp8266/vendor/espressif/c_types.h @@ -0,0 +1,137 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef C_TYPES_H +#define C_TYPES_H + +/* Following header guards are necessary to avoid conflicts with original */ +/* header in SDK where _C_TYPES_H_ is used */ +#ifndef _C_TYPES_H_ +#define _C_TYPES_H_ + +#ifndef DOXYGEN +#ifndef _DTLS_GLOBAL_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef signed char sint8_t; +typedef signed short sint16_t; +typedef signed long sint32_t; +typedef signed long long sint64_t; +typedef unsigned long long u_int64_t; +typedef float real32_t; +typedef double real64_t; + +typedef unsigned char uint8; +typedef unsigned char u8; +typedef signed char sint8; +typedef signed char int8; +typedef signed char s8; +typedef unsigned short uint16; +typedef unsigned short u16; +typedef signed short sint16; +typedef signed short s16; +typedef unsigned int uint32; +typedef unsigned int u_int; +typedef unsigned int u32; +typedef signed int sint32; +typedef signed int s32; +typedef int int32; +typedef signed long long sint64; +typedef unsigned long long uint64; +typedef unsigned long long u64; +typedef float real32; +typedef double real64; + +#define __le16 u16 + +typedef unsigned int size_t; + +/* #define __packed __attribute__((packed)) */ + +#define LOCAL static + +#ifndef NULL +#define NULL (void *)0 +#endif /* NULL */ + +/* probably should not put STATUS here */ +typedef enum { + OK = 0, + FAIL, + PENDING, + BUSY, + CANCEL, +} STATUS; + +#ifndef BIT +#define BIT(nr) (1UL << (nr)) +#endif + +#define REG_SET_BIT(_r, _b) (*(volatile uint32_t*)(_r) |= (_b)) +#define REG_CLR_BIT(_r, _b) (*(volatile uint32_t*)(_r) &= ~(_b)) + +#define DMEM_ATTR __attribute__((section(".bss"))) +#define SHMEM_ATTR + +#ifdef ICACHE_FLASH +#define ICACHE_FLASH_ATTR __attribute__((section(".irom0.text"))) +#define ICACHE_RODATA_ATTR __attribute__((section(".irom.text"))) +#else +#define ICACHE_FLASH_ATTR +#define ICACHE_RODATA_ATTR +#endif /* ICACHE_FLASH */ + +#define STORE_ATTR __attribute__((aligned(4))) + +#ifndef __cplusplus +#define BOOL bool +#ifndef true +#define true (1) +#endif +#ifndef false +#define false (0) +#endif +#ifndef TRUE +#define TRUE true +#endif +#ifndef FALSE +#define FALSE false +#endif + +#endif /* !__cplusplus */ + +#ifdef __cplusplus +} +#endif + +#endif /* _DTLS_GLOBAL_H_ */ +#endif /* DOXYGEN */ +#endif /* _C_TYPES_H_ */ +#endif /* C_TYPES_H */ diff --git a/cpu/esp8266/vendor/espressif/eagle_soc.h b/cpu/esp8266/vendor/espressif/eagle_soc.h new file mode 100644 index 0000000000..fdfe61a07e --- /dev/null +++ b/cpu/esp8266/vendor/espressif/eagle_soc.h @@ -0,0 +1,289 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef EAGLE_SOC_H +#define EAGLE_SOC_H + +#ifndef DOXYGEN + +#ifdef __cplusplus +extern "C" { +#endif + +//Register Bits{{ +#define BIT31 0x80000000 +#define BIT30 0x40000000 +#define BIT29 0x20000000 +#define BIT28 0x10000000 +#define BIT27 0x08000000 +#define BIT26 0x04000000 +#define BIT25 0x02000000 +#define BIT24 0x01000000 +#define BIT23 0x00800000 +#define BIT22 0x00400000 +#define BIT21 0x00200000 +#define BIT20 0x00100000 +#define BIT19 0x00080000 +#define BIT18 0x00040000 +#define BIT17 0x00020000 +#define BIT16 0x00010000 +#define BIT15 0x00008000 +#define BIT14 0x00004000 +#define BIT13 0x00002000 +#define BIT12 0x00001000 +#define BIT11 0x00000800 +#define BIT10 0x00000400 +#define BIT9 0x00000200 +#define BIT8 0x00000100 +#define BIT7 0x00000080 +#define BIT6 0x00000040 +#define BIT5 0x00000020 +#define BIT4 0x00000010 +#define BIT3 0x00000008 +#define BIT2 0x00000004 +#define BIT1 0x00000002 +#define BIT0 0x00000001 +//}} + +//Registers Operation {{ +#define ETS_UNCACHED_ADDR(addr) (addr) +#define ETS_CACHED_ADDR(addr) (addr) + + +#define READ_PERI_REG(addr) (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) +#define WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val) +#define CLEAR_PERI_REG_MASK(reg, mask) WRITE_PERI_REG((reg), (READ_PERI_REG(reg)&(~(mask)))) +#define SET_PERI_REG_MASK(reg, mask) WRITE_PERI_REG((reg), (READ_PERI_REG(reg)|(mask))) +#define GET_PERI_REG_BITS(reg, hipos,lowpos) ((READ_PERI_REG(reg)>>(lowpos))&((1<<((hipos)-(lowpos)+1))-1)) +#define SET_PERI_REG_BITS(reg,bit_map,value,shift) (WRITE_PERI_REG((reg),(READ_PERI_REG(reg)&(~((bit_map)<<(shift))))|((value)<<(shift)) )) +//}} + +//Periheral Clock {{ +#define APB_CLK_FREQ 80*1000000 //unit: Hz +#define UART_CLK_FREQ APB_CLK_FREQ +#define TIMER_CLK_FREQ (APB_CLK_FREQ>>8) //divided by 256 +//}} + +//Peripheral device base address define{{ +#define PERIPHS_DPORT_BASEADDR 0x3ff00000 +#define PERIPHS_GPIO_BASEADDR 0x60000300 +#define PERIPHS_TIMER_BASEDDR 0x60000600 +#define PERIPHS_RTC_BASEADDR 0x60000700 +#define PERIPHS_IO_MUX 0x60000800 +//}} + +//Interrupt remap control registers define{{ +#define EDGE_INT_ENABLE_REG (PERIPHS_DPORT_BASEADDR+0x04) +#define TM1_EDGE_INT_ENABLE() SET_PERI_REG_MASK(EDGE_INT_ENABLE_REG, BIT1) +#define TM1_EDGE_INT_DISABLE() CLEAR_PERI_REG_MASK(EDGE_INT_ENABLE_REG, BIT1) +//}} + +//GPIO reg {{ +#define GPIO_REG_READ(reg) READ_PERI_REG(PERIPHS_GPIO_BASEADDR + reg) +#define GPIO_REG_WRITE(reg, val) WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + reg, val) +#define GPIO_OUT_ADDRESS 0x00 +#define GPIO_OUT_W1TS_ADDRESS 0x04 +#define GPIO_OUT_W1TC_ADDRESS 0x08 + +#define GPIO_ENABLE_ADDRESS 0x0c +#define GPIO_ENABLE_W1TS_ADDRESS 0x10 +#define GPIO_ENABLE_W1TC_ADDRESS 0x14 +#define GPIO_OUT_W1TC_DATA_MASK 0x0000ffff + +#define GPIO_IN_ADDRESS 0x18 + +#define GPIO_STATUS_ADDRESS 0x1c +#define GPIO_STATUS_W1TS_ADDRESS 0x20 +#define GPIO_STATUS_W1TC_ADDRESS 0x24 +#define GPIO_STATUS_INTERRUPT_MASK 0x0000ffff + +#define GPIO_RTC_CALIB_SYNC PERIPHS_GPIO_BASEADDR+0x6c +#define RTC_CALIB_START BIT31 //first write to zero, then to one to start +#define RTC_PERIOD_NUM_MASK 0x3ff //max 8ms +#define GPIO_RTC_CALIB_VALUE PERIPHS_GPIO_BASEADDR+0x70 +#define RTC_CALIB_RDY_S 31 //after measure, flag to one, when start from zero to one, turn to zero +#define RTC_CALIB_VALUE_MASK 0xfffff + +#define GPIO_PIN0_ADDRESS 0x28 + +#define GPIO_ID_PIN0 0 +#define GPIO_ID_PIN(n) (GPIO_ID_PIN0+(n)) +#define GPIO_LAST_REGISTER_ID GPIO_ID_PIN(15) +#define GPIO_ID_NONE 0xffffffff + +#define GPIO_PIN_COUNT 16 + +#define GPIO_PIN_CONFIG_MSB 12 +#define GPIO_PIN_CONFIG_LSB 11 +#define GPIO_PIN_CONFIG_MASK 0x00001800 +#define GPIO_PIN_CONFIG_GET(x) (((x) & GPIO_PIN_CONFIG_MASK) >> GPIO_PIN_CONFIG_LSB) +#define GPIO_PIN_CONFIG_SET(x) (((x) << GPIO_PIN_CONFIG_LSB) & GPIO_PIN_CONFIG_MASK) + +#define GPIO_WAKEUP_ENABLE 1 +#define GPIO_WAKEUP_DISABLE (~GPIO_WAKEUP_ENABLE) +#define GPIO_PIN_WAKEUP_ENABLE_MSB 10 +#define GPIO_PIN_WAKEUP_ENABLE_LSB 10 +#define GPIO_PIN_WAKEUP_ENABLE_MASK 0x00000400 +#define GPIO_PIN_WAKEUP_ENABLE_GET(x) (((x) & GPIO_PIN_WAKEUP_ENABLE_MASK) >> GPIO_PIN_WAKEUP_ENABLE_LSB) +#define GPIO_PIN_WAKEUP_ENABLE_SET(x) (((x) << GPIO_PIN_WAKEUP_ENABLE_LSB) & GPIO_PIN_WAKEUP_ENABLE_MASK) + +#define GPIO_PIN_INT_TYPE_MASK 0x380 +#define GPIO_PIN_INT_TYPE_MSB 9 +#define GPIO_PIN_INT_TYPE_LSB 7 +#define GPIO_PIN_INT_TYPE_GET(x) (((x) & GPIO_PIN_INT_TYPE_MASK) >> GPIO_PIN_INT_TYPE_LSB) +#define GPIO_PIN_INT_TYPE_SET(x) (((x) << GPIO_PIN_INT_TYPE_LSB) & GPIO_PIN_INT_TYPE_MASK) + +#define GPIO_PAD_DRIVER_ENABLE 1 +#define GPIO_PAD_DRIVER_DISABLE (~GPIO_PAD_DRIVER_ENABLE) +#define GPIO_PIN_PAD_DRIVER_MSB 2 +#define GPIO_PIN_PAD_DRIVER_LSB 2 +#define GPIO_PIN_PAD_DRIVER_MASK 0x00000004 +#define GPIO_PIN_PAD_DRIVER_GET(x) (((x) & GPIO_PIN_PAD_DRIVER_MASK) >> GPIO_PIN_PAD_DRIVER_LSB) +#define GPIO_PIN_PAD_DRIVER_SET(x) (((x) << GPIO_PIN_PAD_DRIVER_LSB) & GPIO_PIN_PAD_DRIVER_MASK) + +#define GPIO_AS_PIN_SOURCE 0 +#define SIGMA_AS_PIN_SOURCE (~GPIO_AS_PIN_SOURCE) +#define GPIO_PIN_SOURCE_MSB 0 +#define GPIO_PIN_SOURCE_LSB 0 +#define GPIO_PIN_SOURCE_MASK 0x00000001 +#define GPIO_PIN_SOURCE_GET(x) (((x) & GPIO_PIN_SOURCE_MASK) >> GPIO_PIN_SOURCE_LSB) +#define GPIO_PIN_SOURCE_SET(x) (((x) << GPIO_PIN_SOURCE_LSB) & GPIO_PIN_SOURCE_MASK) +// }} + +// TIMER reg {{ +#define RTC_REG_READ(addr) READ_PERI_REG(PERIPHS_TIMER_BASEDDR + addr) +#define RTC_REG_WRITE(addr, val) WRITE_PERI_REG(PERIPHS_TIMER_BASEDDR + addr, val) +#define RTC_CLR_REG_MASK(reg, mask) CLEAR_PERI_REG_MASK(PERIPHS_TIMER_BASEDDR +reg, mask) +/* Returns the current time according to the timer timer. */ +#define NOW() RTC_REG_READ(FRC2_COUNT_ADDRESS) + +//load initial_value to timer1 +#define FRC1_LOAD_ADDRESS 0x00 + +//timer1's counter value(count from initial_value to 0) +#define FRC1_COUNT_ADDRESS 0x04 + +#define FRC1_CTRL_ADDRESS 0x08 + +//clear timer1's interrupt when write this address +#define FRC1_INT_ADDRESS 0x0c +#define FRC1_INT_CLR_MASK 0x00000001 + +//timer2's counter value(count from initial_value to 0) +#define FRC2_COUNT_ADDRESS 0x24 +// }} + +//RTC reg {{ +#define REG_RTC_BASE PERIPHS_RTC_BASEADDR + +#define RTC_STORE0 (REG_RTC_BASE + 0x030) +#define RTC_STORE1 (REG_RTC_BASE + 0x034) +#define RTC_STORE2 (REG_RTC_BASE + 0x038) +#define RTC_STORE3 (REG_RTC_BASE + 0x03C) + +#define RTC_GPIO_OUT (REG_RTC_BASE + 0x068) +#define RTC_GPIO_ENABLE (REG_RTC_BASE + 0x074) +#define RTC_GPIO_IN_DATA (REG_RTC_BASE + 0x08C) +#define RTC_GPIO_CONF (REG_RTC_BASE + 0x090) +#define PAD_XPD_DCDC_CONF (REG_RTC_BASE + 0x0A0) +//}} + +//PIN Mux reg {{ +#define PERIPHS_IO_MUX_FUNC 0x13 +#define PERIPHS_IO_MUX_FUNC_S 4 +#define PERIPHS_IO_MUX_PULLUP BIT7 +#define PERIPHS_IO_MUX_PULLUP2 BIT6 +#define PERIPHS_IO_MUX_SLEEP_PULLUP BIT3 +#define PERIPHS_IO_MUX_SLEEP_PULLUP2 BIT2 +#define PERIPHS_IO_MUX_SLEEP_OE BIT1 +#define PERIPHS_IO_MUX_OE BIT0 + +#define PERIPHS_IO_MUX_CONF_U (PERIPHS_IO_MUX + 0x00) +#define SPI0_CLK_EQU_SYS_CLK BIT8 +#define SPI1_CLK_EQU_SYS_CLK BIT9 +#define PERIPHS_IO_MUX_MTDI_U (PERIPHS_IO_MUX + 0x04) +#define FUNC_GPIO12 3 +#define PERIPHS_IO_MUX_MTCK_U (PERIPHS_IO_MUX + 0x08) +#define FUNC_GPIO13 3 +#define PERIPHS_IO_MUX_MTMS_U (PERIPHS_IO_MUX + 0x0C) +#define FUNC_GPIO14 3 +#define PERIPHS_IO_MUX_MTDO_U (PERIPHS_IO_MUX + 0x10) +#define FUNC_GPIO15 3 +#define FUNC_U0RTS 4 +#define PERIPHS_IO_MUX_U0RXD_U (PERIPHS_IO_MUX + 0x14) +#define FUNC_GPIO3 3 +#define PERIPHS_IO_MUX_U0TXD_U (PERIPHS_IO_MUX + 0x18) +#define FUNC_U0TXD 0 +#define FUNC_GPIO1 3 +#define PERIPHS_IO_MUX_SD_CLK_U (PERIPHS_IO_MUX + 0x1c) +#define FUNC_SDCLK 0 +#define FUNC_SPICLK 1 +#define PERIPHS_IO_MUX_SD_DATA0_U (PERIPHS_IO_MUX + 0x20) +#define FUNC_SDDATA0 0 +#define FUNC_SPIQ 1 +#define FUNC_U1TXD 4 +#define PERIPHS_IO_MUX_SD_DATA1_U (PERIPHS_IO_MUX + 0x24) +#define FUNC_SDDATA1 0 +#define FUNC_SPID 1 +#define FUNC_U1RXD 4 +#define FUNC_SDDATA1_U1RXD 7 +#define PERIPHS_IO_MUX_SD_DATA2_U (PERIPHS_IO_MUX + 0x28) +#define FUNC_SDDATA2 0 +#define FUNC_SPIHD 1 +#define FUNC_GPIO9 3 +#define PERIPHS_IO_MUX_SD_DATA3_U (PERIPHS_IO_MUX + 0x2c) +#define FUNC_SDDATA3 0 +#define FUNC_SPIWP 1 +#define FUNC_GPIO10 3 +#define PERIPHS_IO_MUX_SD_CMD_U (PERIPHS_IO_MUX + 0x30) +#define FUNC_SDCMD 0 +#define FUNC_SPICS0 1 +#define PERIPHS_IO_MUX_GPIO0_U (PERIPHS_IO_MUX + 0x34) +#define FUNC_GPIO0 0 +#define PERIPHS_IO_MUX_GPIO2_U (PERIPHS_IO_MUX + 0x38) +#define FUNC_GPIO2 0 +#define FUNC_U1TXD_BK 2 +#define FUNC_U0TXD_BK 4 +#define PERIPHS_IO_MUX_GPIO4_U (PERIPHS_IO_MUX + 0x3C) +#define FUNC_GPIO4 0 +#define PERIPHS_IO_MUX_GPIO5_U (PERIPHS_IO_MUX + 0x40) +#define FUNC_GPIO5 0 + +#define PIN_PULLUP_DIS(PIN_NAME) CLEAR_PERI_REG_MASK(PIN_NAME, PERIPHS_IO_MUX_PULLUP) +#define PIN_PULLUP_EN(PIN_NAME) SET_PERI_REG_MASK(PIN_NAME, PERIPHS_IO_MUX_PULLUP) + +#define PIN_FUNC_SELECT(PIN_NAME, FUNC) do { \ + WRITE_PERI_REG(PIN_NAME, \ + (READ_PERI_REG(PIN_NAME) \ + & (~(PERIPHS_IO_MUX_FUNC< + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef ETS_SYS_H +#define ETS_SYS_H + +/* Following header guards are necessary to avoid conflicts with original */ +/* header in SDK where _ETS_SYS_H is used */ +#ifndef _ETS_SYS_H +#define _ETS_SYS_H + +#ifndef DOXYGEN + +#include "c_types.h" +#include "eagle_soc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint32_t ETSSignal; +typedef uint32_t ETSParam; + +typedef struct ETSEventTag ETSEvent; + +struct ETSEventTag { + ETSSignal sig; + ETSParam par; +}; + +typedef void (*ETSTask)(ETSEvent *e); + +/* timer related */ +typedef uint32_t ETSHandle; +typedef void ETSTimerFunc(void *timer_arg); + +typedef struct _ETSTIMER_ { + struct _ETSTIMER_ *timer_next; + uint32_t timer_expire; + uint32_t timer_period; + ETSTimerFunc *timer_func; + void *timer_arg; +} ETSTimer; + +/* interrupt related */ +#define ETS_SDIO_INUM 1 +#define ETS_SPI_INUM 2 +#define ETS_GPIO_INUM 4 +#define ETS_UART_INUM 5 +#define ETS_UART1_INUM 5 +#define ETS_FRC_TIMER1_INUM 9 /* use edge*/ + +typedef void (* ets_isr_t)(void *); + +void ets_intr_lock(void); +void ets_intr_unlock(void); +void ets_isr_attach(int i, ets_isr_t func, void *arg); + +void NmiTimSetFunc(void (*func)(void)); + +#define ETS_INTR_LOCK() \ + ets_intr_lock() + +#define ETS_INTR_UNLOCK() \ + ets_intr_unlock() + +#define ETS_FRC_TIMER1_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_FRC_TIMER1_INUM, (func), (void *)(arg)) + +#define ETS_FRC_TIMER1_NMI_INTR_ATTACH(func) \ + NmiTimSetFunc(func) + +#define ETS_SDIO_INTR_ATTACH(func, arg)\ + ets_isr_attach(ETS_SDIO_INUM, (func), (void *)(arg)) + +#define ETS_GPIO_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_GPIO_INUM, (func), (void *)(arg)) + +#define ETS_UART_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_UART_INUM, (func), (void *)(arg)) + +#define ETS_SPI_INTR_ATTACH(func, arg) \ + ets_isr_attach(ETS_SPI_INUM, (func), (void *)(arg)) + +#define ETS_INTR_ENABLE(inum) \ + ets_isr_unmask((1< + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef GPIO_H +#define GPIO_H + +#ifndef DOXYGEN + +#ifdef __cplusplus +extern "C" { +#endif + +#define GPIO_PIN_ADDR(i) (GPIO_PIN0_ADDRESS + i*4) + +#define GPIO_ID_IS_PIN_REGISTER(reg_id) \ + ((reg_id >= GPIO_ID_PIN0) && (reg_id <= GPIO_ID_PIN(GPIO_PIN_COUNT-1))) + +#define GPIO_REGID_TO_PINIDX(reg_id) ((reg_id) - GPIO_ID_PIN0) + +typedef enum { + GPIO_PIN_INTR_DISABLE = 0, + GPIO_PIN_INTR_POSEDGE = 1, + GPIO_PIN_INTR_NEGEDGE = 2, + GPIO_PIN_INTR_ANYEDGE = 3, + GPIO_PIN_INTR_LOLEVEL = 4, + GPIO_PIN_INTR_HILEVEL = 5 +} GPIO_INT_TYPE; + +#define GPIO_OUTPUT_SET(gpio_no, bit_value) \ + gpio_output_set((bit_value)<>gpio_no)&BIT0) + +/* GPIO interrupt handler, registered through gpio_intr_handler_register */ +typedef void (* gpio_intr_handler_fn_t)(uint32 intr_mask, void *arg); + + +/* + * Initialize GPIO. This includes reading the GPIO Configuration DataSet + * to initialize "output enables" and pin configurations for each gpio pin. + * Must be called once during startup. + */ +// conflicts with RIOT's gpio.h // void gpio_init(void); + +/* + * Change GPIO pin output by setting, clearing, or disabling pins. + * In general, it is expected that a bit will be set in at most one + * of these masks. If a bit is clear in all masks, the output state + * remains unchanged. + * + * There is no particular ordering guaranteed; so if the order of + * writes is significant, calling code should divide a single call + * into multiple calls. + */ +void gpio_output_set(uint32 set_mask, + uint32 clear_mask, + uint32 enable_mask, + uint32 disable_mask); + +/* + * Sample the value of GPIO input pins and returns a bitmask. + */ +uint32 gpio_input_get(void); + +/* + * Set the specified GPIO register to the specified value. + * This is a very general and powerful interface that is not + * expected to be used during normal operation. It is intended + * mainly for debug, or for unusual requirements. + */ +void gpio_register_set(uint32 reg_id, uint32 value); + +/* Get the current value of the specified GPIO register. */ +uint32 gpio_register_get(uint32 reg_id); + +/* + * Register an application-specific interrupt handler for GPIO pin + * interrupts. Once the interrupt handler is called, it will not + * be called again until after a call to gpio_intr_ack. Any GPIO + * interrupts that occur during the interim are masked. + * + * The application-specific handler is called with a mask of + * pending GPIO interrupts. After processing pin interrupts, the + * application-specific handler may wish to use gpio_intr_pending + * to check for any additional pending interrupts before it returns. + */ +void gpio_intr_handler_register(gpio_intr_handler_fn_t fn, void *arg); + +/* Determine which GPIO interrupts are pending. */ +uint32 gpio_intr_pending(void); + +/* + * Acknowledge GPIO interrupts. + * Intended to be called from the gpio_intr_handler_fn. + */ +void gpio_intr_ack(uint32 ack_mask); + +void gpio_pin_wakeup_enable(uint32 i, GPIO_INT_TYPE intr_state); + +void gpio_pin_wakeup_disable(void); + +void gpio_pin_intr_state_set(uint32 i, GPIO_INT_TYPE intr_state); + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* GPIO_H */ diff --git a/cpu/esp8266/vendor/espressif/osapi.h b/cpu/esp8266/vendor/espressif/osapi.h new file mode 100644 index 0000000000..5700e54754 --- /dev/null +++ b/cpu/esp8266/vendor/espressif/osapi.h @@ -0,0 +1,103 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef OSAPI_H +#define OSAPI_H + +#ifndef DOXYGEN + +#include +#include "os_type.h" +#include "user_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void ets_bzero(void *s, size_t n); +void ets_delay_us(uint16_t us); +void ets_install_putc1(void (*p)(char c)); + +#define os_bzero ets_bzero +#define os_delay_us ets_delay_us +#define os_install_putc1 ets_install_putc1 + +int ets_memcmp(const void *str1, const void *str2, unsigned int nbyte); +void *ets_memcpy(void *dest, const void *src, unsigned int nbyte); +void *ets_memmove(void *dest, const void *src, unsigned int nbyte); +void *ets_memset(void *dest, int val, unsigned int nbyte); + +int ets_strcmp(const char *s1, const char *s2); +char *ets_strcpy(char *s1, const char *s2); +int ets_strlen(const char *s); +int ets_strncmp(const char *s1, const char *s2, unsigned int n); +char *ets_strncpy(char *s1, const char *s2, unsigned int n); +char *ets_strstr(const char *s1, const char *s2); + +#define os_memcmp ets_memcmp +#define os_memcpy ets_memcpy +#define os_memmove ets_memmove +#define os_memset ets_memset +#define os_strcat strcat +#define os_strchr strchr +#define os_strcmp ets_strcmp +#define os_strcpy ets_strcpy +#define os_strlen ets_strlen +#define os_strncmp ets_strncmp +#define os_strncpy ets_strncpy +#define os_strstr ets_strstr + +void ets_timer_arm_new(os_timer_t *ptimer, uint32_t time, bool repeat_flag, bool ms_flag); +void ets_timer_disarm(os_timer_t *ptimer); +void ets_timer_setfn(os_timer_t *ptimer, os_timer_func_t *pfunction, void *parg); + +#ifdef USE_US_TIMER +#define os_timer_arm_us(a, b, c) ets_timer_arm_new(a, b, c, 0) +#endif +#define os_timer_arm(a, b, c) ets_timer_arm_new(a, b, c, 1) +#define os_timer_disarm ets_timer_disarm +#define os_timer_setfn ets_timer_setfn + +int ets_sprintf(char *str, const char *format, ...) __attribute__ ((format (printf, 2, 3))); +int os_printf_plus(const char *format, ...) __attribute__ ((format (printf, 1, 2))); + +#define os_sprintf ets_sprintf + +#ifdef USE_OPTIMIZE_PRINTF +#define os_printf(fmt, ...) do { \ + static const char flash_str[] ICACHE_RODATA_ATTR STORE_ATTR = fmt; \ + os_printf_plus(flash_str, ##__VA_ARGS__); \ + } while(0) +#else +#define os_printf os_printf_plus +#endif + +unsigned long os_random(void); +int os_get_random(unsigned char *buf, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* OSAPI_H */ diff --git a/cpu/esp8266/vendor/espressif/spi_flash.h b/cpu/esp8266/vendor/espressif/spi_flash.h new file mode 100644 index 0000000000..215afd07b3 --- /dev/null +++ b/cpu/esp8266/vendor/espressif/spi_flash.h @@ -0,0 +1,71 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef SPI_FLASH_H +#define SPI_FLASH_H + +#ifndef DOXYGEN + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + SPI_FLASH_RESULT_OK, + SPI_FLASH_RESULT_ERR, + SPI_FLASH_RESULT_TIMEOUT +} SpiFlashOpResult; + +typedef struct{ + uint32 deviceId; + uint32 chip_size; // chip size in byte + uint32 block_size; + uint32 sector_size; + uint32 page_size; + uint32 status_mask; +} SpiFlashChip; + +#define SPI_FLASH_SEC_SIZE 4096 + +uint32 spi_flash_get_id(void); +SpiFlashOpResult spi_flash_erase_sector(uint16 sec); +SpiFlashOpResult spi_flash_write(uint32 des_addr, uint32 *src_addr, uint32 size); +SpiFlashOpResult spi_flash_read(uint32 src_addr, uint32 *des_addr, uint32 size); + +typedef SpiFlashOpResult (* user_spi_flash_read)( + SpiFlashChip *spi, + uint32 src_addr, + uint32 *des_addr, + uint32 size); + +void spi_flash_set_read_func(user_spi_flash_read read); + +bool spi_flash_erase_protect_enable(void); +bool spi_flash_erase_protect_disable(void); + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* SPI_FLASH_H */ diff --git a/cpu/esp8266/vendor/espressif/user_interface.h b/cpu/esp8266/vendor/espressif/user_interface.h new file mode 100644 index 0000000000..d0cf3e53ab --- /dev/null +++ b/cpu/esp8266/vendor/espressif/user_interface.h @@ -0,0 +1,658 @@ +/* + * ESPRESSIF MIT License + * + * Copyright (c) 2016 + * + * Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, + * it is free of charge, to any person obtaining a copy of this software and associated + * documentation files (the "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef USER_INTERFACE_H +#define USER_INTERFACE_H + +#ifndef DOXYGEN + +#include "os_type.h" +#ifdef LWIP_OPEN_SRC +#include "lwip/ip_addr.h" +#else +#include "ip_addr.h" +#endif + +#include "queue.h" +#include "user_config.h" +#include "spi_flash.h" +#include "gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MAC2STR +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" +#endif + +enum rst_reason { + REASON_DEFAULT_RST = 0, + REASON_WDT_RST = 1, + REASON_EXCEPTION_RST = 2, + REASON_SOFT_WDT_RST = 3, + REASON_SOFT_RESTART = 4, + REASON_DEEP_SLEEP_AWAKE = 5, + REASON_EXT_SYS_RST = 6 +}; + +struct rst_info{ + uint32 reason; + uint32 exccause; + uint32 epc1; + uint32 epc2; + uint32 epc3; + uint32 excvaddr; + uint32 depc; +}; + +struct rst_info* system_get_rst_info(void); + +#define UPGRADE_FW_BIN1 0x00 +#define UPGRADE_FW_BIN2 0x01 + +void system_restore(void); +void system_restart(void); + +bool system_deep_sleep_set_option(uint8 option); +bool system_deep_sleep(uint64 time_in_us); +bool system_deep_sleep_instant(uint64 time_in_us); + +uint8 system_upgrade_userbin_check(void); +void system_upgrade_reboot(void); +uint8 system_upgrade_flag_check(void); +void system_upgrade_flag_set(uint8 flag); + +void system_timer_reinit(void); +uint32 system_get_time(void); + +/* user task's prio must be 0/1/2 !!!*/ +enum { + USER_TASK_PRIO_0 = 0, + USER_TASK_PRIO_1, + USER_TASK_PRIO_2, + USER_TASK_PRIO_MAX +}; + +bool system_os_task(os_task_t task, uint8 prio, os_event_t *queue, uint8 qlen); +bool system_os_post(uint8 prio, os_signal_t sig, os_param_t par); + +void system_print_meminfo(void); +uint32 system_get_free_heap_size(void); + +void system_set_os_print(uint8 onoff); +uint8 system_get_os_print(void); + +uint64 system_mktime(uint32 year, uint32 mon, uint32 day, uint32 hour, uint32 min, uint32 sec); + +uint32 system_get_chip_id(void); + +typedef void (* init_done_cb_t)(void); + +void system_init_done_cb(init_done_cb_t cb); + +uint32 system_rtc_clock_cali_proc(void); +uint32 system_get_rtc_time(void); + +bool system_rtc_mem_read(uint8 src_addr, void *des_addr, uint16 load_size); +bool system_rtc_mem_write(uint8 des_addr, const void *src_addr, uint16 save_size); + +void system_uart_swap(void); +void system_uart_de_swap(void); + +uint16 system_adc_read(void); +void system_adc_read_fast(uint16 *adc_addr, uint16 adc_num, uint8 adc_clk_div); +uint16 system_get_vdd33(void); + +const char *system_get_sdk_version(void); + +#define SYS_BOOT_ENHANCE_MODE 0 +#define SYS_BOOT_NORMAL_MODE 1 + +#define SYS_BOOT_NORMAL_BIN 0 +#define SYS_BOOT_TEST_BIN 1 + +uint8 system_get_boot_version(void); +uint32 system_get_userbin_addr(void); +uint8 system_get_boot_mode(void); +bool system_restart_enhance(uint8 bin_type, uint32 bin_addr); + +#define SYS_CPU_80MHZ 80 +#define SYS_CPU_160MHZ 160 + +bool system_update_cpu_freq(uint8 freq); +uint8 system_get_cpu_freq(void); + +enum flash_size_map { + FLASH_SIZE_4M_MAP_256_256 = 0, /**< Flash size : 4Mbits. Map : 256KBytes + 256KBytes */ + FLASH_SIZE_2M, /**< Flash size : 2Mbits. Map : 256KBytes */ + FLASH_SIZE_8M_MAP_512_512, /**< Flash size : 8Mbits. Map : 512KBytes + 512KBytes */ + FLASH_SIZE_16M_MAP_512_512, /**< Flash size : 16Mbits. Map : 512KBytes + 512KBytes */ + FLASH_SIZE_32M_MAP_512_512, /**< Flash size : 32Mbits. Map : 512KBytes + 512KBytes */ + FLASH_SIZE_16M_MAP_1024_1024, /**< Flash size : 16Mbits. Map : 1024KBytes + 1024KBytes */ + FLASH_SIZE_32M_MAP_1024_1024, /**< Flash size : 32Mbits. Map : 1024KBytes + 1024KBytes */ + FLASH_SIZE_32M_MAP_2048_2048, /**< attention: don't support now ,just compatible for nodemcu; + Flash size : 32Mbits. Map : 2048KBytes + 2048KBytes */ + FLASH_SIZE_64M_MAP_1024_1024, /**< Flash size : 64Mbits. Map : 1024KBytes + 1024KBytes */ + FLASH_SIZE_128M_MAP_1024_1024 /**< Flash size : 128Mbits. Map : 1024KBytes + 1024KBytes */ +}; + +enum flash_size_map system_get_flash_size_map(void); + +void system_phy_set_max_tpw(uint8 max_tpw); +void system_phy_set_tpw_via_vdd33(uint16 vdd33); +void system_phy_set_rfoption(uint8 option); +void system_phy_set_powerup_option(uint8 option); +void system_phy_freq_trace_enable(bool enable); + +bool system_param_save_with_protect(uint16 start_sec, void *param, uint16 len); +bool system_param_load(uint16 start_sec, uint16 offset, void *param, uint16 len); + +void system_soft_wdt_stop(void); +void system_soft_wdt_restart(void); +void system_soft_wdt_feed(void); + +void system_show_malloc(void); + +#define NULL_MODE 0x00 +#define STATION_MODE 0x01 +#define SOFTAP_MODE 0x02 +#define STATIONAP_MODE 0x03 + +typedef enum _auth_mode { + AUTH_OPEN = 0, + AUTH_WEP, + AUTH_WPA_PSK, + AUTH_WPA2_PSK, + AUTH_WPA_WPA2_PSK, + AUTH_MAX +} AUTH_MODE; + +uint8 wifi_get_opmode(void); +uint8 wifi_get_opmode_default(void); +bool wifi_set_opmode(uint8 opmode); +bool wifi_set_opmode_current(uint8 opmode); +uint8 wifi_get_broadcast_if(void); +bool wifi_set_broadcast_if(uint8 interface); + +struct bss_info { + STAILQ_ENTRY(bss_info) next; + + uint8 bssid[6]; + uint8 ssid[32]; + uint8 ssid_len; + uint8 channel; + sint8 rssi; + AUTH_MODE authmode; + uint8 is_hidden; + sint16 freq_offset; + sint16 freqcal_val; + uint8 *esp_mesh_ie; + uint8 simple_pair; +}; + +typedef struct _scaninfo { + STAILQ_HEAD(, bss_info) *pbss; + struct espconn *pespconn; + uint8 totalpage; + uint8 pagenum; + uint8 page_sn; + uint8 data_cnt; +} scaninfo; + +typedef void (* scan_done_cb_t)(void *arg, STATUS status); + +struct station_config { + uint8 ssid[32]; + uint8 password[64]; + uint8 bssid_set; // Note: If bssid_set is 1, station will just connect to the router + // with both ssid[] and bssid[] matched. Please check about this. + uint8 bssid[6]; +}; + +bool wifi_station_get_config(struct station_config *config); +bool wifi_station_get_config_default(struct station_config *config); +bool wifi_station_set_config(struct station_config *config); +bool wifi_station_set_config_current(struct station_config *config); + +bool wifi_station_connect(void); +bool wifi_station_disconnect(void); + +sint8 wifi_station_get_rssi(void); + +struct scan_config { + uint8 *ssid; // Note: ssid == NULL, don't filter ssid. + uint8 *bssid; // Note: bssid == NULL, don't filter bssid. + uint8 channel; // Note: channel == 0, scan all channels, otherwise scan set channel. + uint8 show_hidden; // Note: show_hidden == 1, can get hidden ssid routers' info. +}; + +bool wifi_station_scan(struct scan_config *config, scan_done_cb_t cb); + +uint8 wifi_station_get_auto_connect(void); +bool wifi_station_set_auto_connect(uint8 set); + +bool wifi_station_set_reconnect_policy(bool set); + +enum { + STATION_IDLE = 0, + STATION_CONNECTING, + STATION_WRONG_PASSWORD, + STATION_NO_AP_FOUND, + STATION_CONNECT_FAIL, + STATION_GOT_IP +}; + +enum dhcp_status { + DHCP_STOPPED, + DHCP_STARTED +}; + +uint8 wifi_station_get_connect_status(void); + +uint8 wifi_station_get_current_ap_id(void); +bool wifi_station_ap_change(uint8 current_ap_id); +bool wifi_station_ap_number_set(uint8 ap_number); +uint8 wifi_station_get_ap_info(struct station_config config[]); + +bool wifi_station_dhcpc_start(void); +bool wifi_station_dhcpc_stop(void); +enum dhcp_status wifi_station_dhcpc_status(void); +bool wifi_station_dhcpc_set_maxtry(uint8 num); + +char* wifi_station_get_hostname(void); +bool wifi_station_set_hostname(char *name); + +int wifi_station_set_cert_key(uint8 *client_cert, int client_cert_len, + uint8 *private_key, int private_key_len, + uint8 *private_key_passwd, int private_key_passwd_len); +void wifi_station_clear_cert_key(void); +int wifi_station_set_username(uint8 *username, int len); +void wifi_station_clear_username(void); + +struct softap_config { + uint8 ssid[32]; + uint8 password[64]; + uint8 ssid_len; // Note: Recommend to set it according to your ssid + uint8 channel; // Note: support 1 ~ 13 + AUTH_MODE authmode; // Note: Don't support AUTH_WEP in softAP mode. + uint8 ssid_hidden; // Note: default 0 + uint8 max_connection; // Note: default 4, max 4 + uint16 beacon_interval; // Note: support 100 ~ 60000 ms, default 100 +}; + +bool wifi_softap_get_config(struct softap_config *config); +bool wifi_softap_get_config_default(struct softap_config *config); +bool wifi_softap_set_config(struct softap_config *config); +bool wifi_softap_set_config_current(struct softap_config *config); + +struct station_info { + STAILQ_ENTRY(station_info) next; + + uint8 bssid[6]; + struct ip_addr ip; +}; + +struct dhcps_lease { + bool enable; + struct ip_addr start_ip; + struct ip_addr end_ip; +}; + +enum dhcps_offer_option{ + OFFER_START = 0x00, + OFFER_ROUTER = 0x01, + OFFER_END +}; + +uint8 wifi_softap_get_station_num(void); +struct station_info * wifi_softap_get_station_info(void); +void wifi_softap_free_station_info(void); + +bool wifi_softap_dhcps_start(void); +bool wifi_softap_dhcps_stop(void); + +bool wifi_softap_set_dhcps_lease(struct dhcps_lease *please); +bool wifi_softap_get_dhcps_lease(struct dhcps_lease *please); +uint32 wifi_softap_get_dhcps_lease_time(void); +bool wifi_softap_set_dhcps_lease_time(uint32 minute); +bool wifi_softap_reset_dhcps_lease_time(void); + +enum dhcp_status wifi_softap_dhcps_status(void); +bool wifi_softap_set_dhcps_offer_option(uint8 level, void* optarg); + +#define STATION_IF 0x00 +#define SOFTAP_IF 0x01 + +bool wifi_get_ip_info(uint8 if_index, struct ip_info *info); +bool wifi_set_ip_info(uint8 if_index, struct ip_info *info); +bool wifi_get_macaddr(uint8 if_index, uint8 *macaddr); +bool wifi_set_macaddr(uint8 if_index, uint8 *macaddr); + +uint8 wifi_get_channel(void); +bool wifi_set_channel(uint8 channel); + +void wifi_status_led_install(uint8 gpio_id, uint32 gpio_name, uint8 gpio_func); +void wifi_status_led_uninstall(void); + +/** Get the absolute difference between 2 u32_t values (correcting overflows) + * 'a' is expected to be 'higher' (without overflow) than 'b'. */ +#define ESP_U32_DIFF(a, b) (((a) >= (b)) ? ((a) - (b)) : (((a) + ((b) ^ 0xFFFFFFFF) + 1))) + +void wifi_promiscuous_enable(uint8 promiscuous); + +typedef void (* wifi_promiscuous_cb_t)(uint8 *buf, uint16 len); + +void wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb_t cb); + +void wifi_promiscuous_set_mac(const uint8_t *address); + +enum phy_mode { + PHY_MODE_11B = 1, + PHY_MODE_11G = 2, + PHY_MODE_11N = 3 +}; + +enum phy_mode wifi_get_phy_mode(void); +bool wifi_set_phy_mode(enum phy_mode mode); + +enum sleep_type { + NONE_SLEEP_T = 0, + LIGHT_SLEEP_T, + MODEM_SLEEP_T +}; + +bool wifi_set_sleep_type(enum sleep_type type); +enum sleep_type wifi_get_sleep_type(void); + +void wifi_fpm_open(void); +void wifi_fpm_close(void); +void wifi_fpm_do_wakeup(void); +sint8 wifi_fpm_do_sleep(uint32 sleep_time_in_us); +void wifi_fpm_set_sleep_type(enum sleep_type type); +enum sleep_type wifi_fpm_get_sleep_type(void); + +typedef void (*fpm_wakeup_cb)(void); +void wifi_fpm_set_wakeup_cb(fpm_wakeup_cb cb); + +void wifi_fpm_auto_sleep_set_in_null_mode(uint8 req); + +enum { + EVENT_STAMODE_CONNECTED = 0, + EVENT_STAMODE_DISCONNECTED, + EVENT_STAMODE_AUTHMODE_CHANGE, + EVENT_STAMODE_GOT_IP, + EVENT_STAMODE_DHCP_TIMEOUT, + EVENT_SOFTAPMODE_STACONNECTED, + EVENT_SOFTAPMODE_STADISCONNECTED, + EVENT_SOFTAPMODE_PROBEREQRECVED, + EVENT_OPMODE_CHANGED, + EVENT_MAX +}; + +enum { + REASON_UNSPECIFIED = 1, + REASON_AUTH_EXPIRE = 2, + REASON_AUTH_LEAVE = 3, + REASON_ASSOC_EXPIRE = 4, + REASON_ASSOC_TOOMANY = 5, + REASON_NOT_AUTHED = 6, + REASON_NOT_ASSOCED = 7, + REASON_ASSOC_LEAVE = 8, + REASON_ASSOC_NOT_AUTHED = 9, + REASON_DISASSOC_PWRCAP_BAD = 10, /* 11h */ + REASON_DISASSOC_SUPCHAN_BAD = 11, /* 11h */ + REASON_IE_INVALID = 13, /* 11i */ + REASON_MIC_FAILURE = 14, /* 11i */ + REASON_4WAY_HANDSHAKE_TIMEOUT = 15, /* 11i */ + REASON_GROUP_KEY_UPDATE_TIMEOUT = 16, /* 11i */ + REASON_IE_IN_4WAY_DIFFERS = 17, /* 11i */ + REASON_GROUP_CIPHER_INVALID = 18, /* 11i */ + REASON_PAIRWISE_CIPHER_INVALID = 19, /* 11i */ + REASON_AKMP_INVALID = 20, /* 11i */ + REASON_UNSUPP_RSN_IE_VERSION = 21, /* 11i */ + REASON_INVALID_RSN_IE_CAP = 22, /* 11i */ + REASON_802_1X_AUTH_FAILED = 23, /* 11i */ + REASON_CIPHER_SUITE_REJECTED = 24, /* 11i */ + + REASON_BEACON_TIMEOUT = 200, + REASON_NO_AP_FOUND = 201, + REASON_AUTH_FAIL = 202, + REASON_ASSOC_FAIL = 203, + REASON_HANDSHAKE_TIMEOUT = 204, +}; + +typedef struct { + uint8 ssid[32]; + uint8 ssid_len; + uint8 bssid[6]; + uint8 channel; +} Event_StaMode_Connected_t; + +typedef struct { + uint8 ssid[32]; + uint8 ssid_len; + uint8 bssid[6]; + uint8 reason; +} Event_StaMode_Disconnected_t; + +typedef struct { + uint8 old_mode; + uint8 new_mode; +} Event_StaMode_AuthMode_Change_t; + +typedef struct { + struct ip_addr ip; + struct ip_addr mask; + struct ip_addr gw; +} Event_StaMode_Got_IP_t; + +typedef struct { + uint8 mac[6]; + uint8 aid; +} Event_SoftAPMode_StaConnected_t; + +typedef struct { + uint8 mac[6]; + uint8 aid; +} Event_SoftAPMode_StaDisconnected_t; + +typedef struct { + int rssi; + uint8 mac[6]; +} Event_SoftAPMode_ProbeReqRecved_t; + +typedef struct { + uint8 old_opmode; + uint8 new_opmode; +} Event_OpMode_Change_t; + +typedef union { + Event_StaMode_Connected_t connected; + Event_StaMode_Disconnected_t disconnected; + Event_StaMode_AuthMode_Change_t auth_change; + Event_StaMode_Got_IP_t got_ip; + Event_SoftAPMode_StaConnected_t sta_connected; + Event_SoftAPMode_StaDisconnected_t sta_disconnected; + Event_SoftAPMode_ProbeReqRecved_t ap_probereqrecved; + Event_OpMode_Change_t opmode_changed; +} Event_Info_u; + +typedef struct _esp_event { + uint32 event; + Event_Info_u event_info; +} System_Event_t; + +typedef void (* wifi_event_handler_cb_t)(System_Event_t *event); + +void wifi_set_event_handler_cb(wifi_event_handler_cb_t cb); + +typedef enum wps_type { + WPS_TYPE_DISABLE = 0, + WPS_TYPE_PBC, + WPS_TYPE_PIN, + WPS_TYPE_DISPLAY, + WPS_TYPE_MAX, +} WPS_TYPE_t; + +enum wps_cb_status { + WPS_CB_ST_SUCCESS = 0, + WPS_CB_ST_FAILED, + WPS_CB_ST_TIMEOUT, + WPS_CB_ST_WEP, +}; + +bool wifi_wps_enable(WPS_TYPE_t wps_type); +bool wifi_wps_disable(void); +bool wifi_wps_start(void); + +typedef void (*wps_st_cb_t)(int status); +bool wifi_set_wps_cb(wps_st_cb_t cb); + +typedef void (*freedom_outside_cb_t)(uint8 status); +int wifi_register_send_pkt_freedom_cb(freedom_outside_cb_t cb); +void wifi_unregister_send_pkt_freedom_cb(void); +int wifi_send_pkt_freedom(uint8 *buf, int len, bool sys_seq); + +int wifi_rfid_locp_recv_open(void); +void wifi_rfid_locp_recv_close(void); + +typedef void (*rfid_locp_cb_t)(uint8 *frm, int len, int rssi); +int wifi_register_rfid_locp_recv_cb(rfid_locp_cb_t cb); +void wifi_unregister_rfid_locp_recv_cb(void); + +enum FIXED_RATE { + PHY_RATE_48 = 0x8, + PHY_RATE_24 = 0x9, + PHY_RATE_12 = 0xA, + PHY_RATE_6 = 0xB, + PHY_RATE_54 = 0xC, + PHY_RATE_36 = 0xD, + PHY_RATE_18 = 0xE, + PHY_RATE_9 = 0xF, +}; + +#define FIXED_RATE_MASK_NONE 0x00 +#define FIXED_RATE_MASK_STA 0x01 +#define FIXED_RATE_MASK_AP 0x02 +#define FIXED_RATE_MASK_ALL 0x03 + +int wifi_set_user_fixed_rate(uint8 enable_mask, uint8 rate); +int wifi_get_user_fixed_rate(uint8 *enable_mask, uint8 *rate); + +enum support_rate { + RATE_11B5M = 0, + RATE_11B11M = 1, + RATE_11B1M = 2, + RATE_11B2M = 3, + RATE_11G6M = 4, + RATE_11G12M = 5, + RATE_11G24M = 6, + RATE_11G48M = 7, + RATE_11G54M = 8, + RATE_11G9M = 9, + RATE_11G18M = 10, + RATE_11G36M = 11, +}; + +int wifi_set_user_sup_rate(uint8 min, uint8 max); + +enum RATE_11B_ID { + RATE_11B_B11M = 0, + RATE_11B_B5M = 1, + RATE_11B_B2M = 2, + RATE_11B_B1M = 3, +}; + +enum RATE_11G_ID { + RATE_11G_G54M = 0, + RATE_11G_G48M = 1, + RATE_11G_G36M = 2, + RATE_11G_G24M = 3, + RATE_11G_G18M = 4, + RATE_11G_G12M = 5, + RATE_11G_G9M = 6, + RATE_11G_G6M = 7, + RATE_11G_B5M = 8, + RATE_11G_B2M = 9, + RATE_11G_B1M = 10 +}; + +enum RATE_11N_ID { + RATE_11N_MCS7S = 0, + RATE_11N_MCS7 = 1, + RATE_11N_MCS6 = 2, + RATE_11N_MCS5 = 3, + RATE_11N_MCS4 = 4, + RATE_11N_MCS3 = 5, + RATE_11N_MCS2 = 6, + RATE_11N_MCS1 = 7, + RATE_11N_MCS0 = 8, + RATE_11N_B5M = 9, + RATE_11N_B2M = 10, + RATE_11N_B1M = 11 +}; + +#define RC_LIMIT_11B 0 +#define RC_LIMIT_11G 1 +#define RC_LIMIT_11N 2 +#define RC_LIMIT_P2P_11G 3 +#define RC_LIMIT_P2P_11N 4 +#define RC_LIMIT_NUM 5 + +#define LIMIT_RATE_MASK_NONE 0x00 +#define LIMIT_RATE_MASK_STA 0x01 +#define LIMIT_RATE_MASK_AP 0x02 +#define LIMIT_RATE_MASK_ALL 0x03 + +bool wifi_set_user_rate_limit(uint8 mode, uint8 ifidx, uint8 max, uint8 min); +uint8 wifi_get_user_limit_rate_mask(void); +bool wifi_set_user_limit_rate_mask(uint8 enable_mask); + +enum { + USER_IE_BEACON = 0, + USER_IE_PROBE_REQ, + USER_IE_PROBE_RESP, + USER_IE_ASSOC_REQ, + USER_IE_ASSOC_RESP, + USER_IE_MAX +}; + +typedef void (*user_ie_manufacturer_recv_cb_t)(uint8 type, const uint8 sa[6], const uint8 m_oui[3], uint8 *ie, uint8 ie_len, int rssi); + +bool wifi_set_user_ie(bool enable, uint8 *m_oui, uint8 type, uint8 *user_ie, uint8 len); +int wifi_register_user_ie_manufacturer_recv_cb(user_ie_manufacturer_recv_cb_t cb); +void wifi_unregister_user_ie_manufacturer_recv_cb(void); + +void wifi_enable_gpio_wakeup(uint32 i, GPIO_INT_TYPE intr_status); +void wifi_disable_gpio_wakeup(void); + +void uart_div_modify(uint8 uart_no, uint32 DivLatchValue); + +#ifdef __cplusplus +} +#endif + +#endif // DOXYGEN +#endif /* USER_INTERFACE_H */ diff --git a/cpu/esp8266/vendor/xtensa/Makefile b/cpu/esp8266/vendor/xtensa/Makefile new file mode 100644 index 0000000000..350d5aaf0c --- /dev/null +++ b/cpu/esp8266/vendor/xtensa/Makefile @@ -0,0 +1,3 @@ +MODULE=xtensa + +include $(RIOTBASE)/Makefile.base diff --git a/cpu/esp8266/vendor/xtensa/README.md b/cpu/esp8266/vendor/xtensa/README.md new file mode 100644 index 0000000000..6cce4e5f16 --- /dev/null +++ b/cpu/esp8266/vendor/xtensa/README.md @@ -0,0 +1,30 @@ +All files in this directory are from the [FreeRTOS port for Xtensa](https://github.com/tensilica/freertos) configurable processors and Diamond processors. All of these files are copyright of Cadence Design Systems Inc., see below. + +Some of the files are slightly modified for the RIOT OS port. + +Please note the following copyright notices for all these files: + +``` +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ +``` diff --git a/cpu/esp8266/vendor/xtensa/portasm.S b/cpu/esp8266/vendor/xtensa/portasm.S new file mode 100644 index 0000000000..32391dc016 --- /dev/null +++ b/cpu/esp8266/vendor/xtensa/portasm.S @@ -0,0 +1,620 @@ +/* +//----------------------------------------------------------------------------- +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//----------------------------------------------------------------------------- +*/ + +#ifdef RIOT_VERSION +#include "xtensa_conf.h" + +#define pxCurrentTCB sched_active_thread +#define port_xSchedulerRunning sched_num_threads +#define port_switch_flag sched_context_switch_request +#define port_interruptNesting irq_interrupt_nesting +#define vTaskSwitchContext sched_run +#define configISR_STACK_SIZE ISR_STACKSIZE + +.extern sched_active_thread +.extern sched_num_threads +.extern sched_context_switch_request +.extern irq_interrupt_nesting +#endif + +#include "xtensa_context.h" + +#define TOPOFSTACK_OFFS 0x00 /* StackType_t *pxTopOfStack */ +#define CP_TOPOFSTACK_OFFS 0x04 /* xMPU_SETTINGS.coproc_area */ + +/* +******************************************************************************* +* Interrupt stack. The size of the interrupt stack is determined by the config +* parameter "configISR_STACK_SIZE" in FreeRTOSConfig.h +******************************************************************************* +*/ + .data + .align 16 + .global port_IntStack +port_IntStack: + .space configISR_STACK_SIZE + .global port_IntStackTop +port_IntStackTop: + .word 0 + +#ifndef RIOT_VERSION +port_switch_flag: + .word 0 +#endif + + .text + .literal_position + +/* +******************************************************************************* +* _frxt_setup_switch +* void _frxt_setup_switch(void); +* +* Sets an internal flag indicating that a task switch is required on return +* from interrupt handling. +* +******************************************************************************* +*/ + .global _frxt_setup_switch + .type _frxt_setup_switch,@function + .align 4 +_frxt_setup_switch: + + ENTRY(16) + + movi a2, port_switch_flag + movi a3, 1 + s32i a3, a2, 0 + + RET(16) + +/* +******************************************************************************* +* _frxt_int_enter +* void _frxt_int_enter(void) +* +* Implements the Xtensa RTOS porting layer's XT_RTOS_INT_ENTER function for +* freeRTOS. Saves the rest of the interrupt context (not already saved). +* May only be called from assembly code by the 'call0' instruction, with +* interrupts disabled. +* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h. +* +******************************************************************************* +*/ + .globl _frxt_int_enter + .type _frxt_int_enter,@function + .align 4 +_frxt_int_enter: + + /* Save a12-13 in the stack frame as required by _xt_context_save. */ + s32i a12, a1, XT_STK_A12 + s32i a13, a1, XT_STK_A13 + + /* Save return address in a safe place (free a0). */ + mov a12, a0 + + /* Save the rest of the interrupted context (preserves A12-13). */ + call0 _xt_context_save + + /* + Save interrupted task's SP in TCB only if not nesting. + Manage nesting directly rather than call the generic IntEnter() + (in windowed ABI we can't call a C function here anyway because PS.EXCM is still set). + */ + + movi a2, port_xSchedulerRunning + movi a3, port_interruptNesting + l32i a2, a2, 0 /* a2 = port_xSchedulerRunning */ + beqz a2, 1f /* scheduler not running, no tasks */ + l32i a2, a3, 0 /* a2 = port_interruptNesting */ + addi a2, a2, 1 /* increment nesting count */ + s32i a2, a3, 0 /* save nesting count */ + bnei a2, 1, .Lnested /* !=0 before incr, so nested */ + + movi a2, pxCurrentTCB + l32i a2, a2, 0 /* a2 = current TCB */ + beqz a2, 1f + s32i a1, a2, TOPOFSTACK_OFFS /* pxCurrentTCB->pxTopOfStack = SP */ + movi a1, port_IntStackTop /* a1 = top of intr stack */ + +.Lnested: +1: + mov a0, a12 /* restore return addr and return */ + ret + +/* +******************************************************************************* +* _frxt_int_exit +* void _frxt_int_exit(void) +* +* Implements the Xtensa RTOS porting layer's XT_RTOS_INT_EXIT function for +* FreeRTOS. If required, calls vPortYieldFromInt() to perform task context +* switching, restore the (possibly) new task's context, and return to the +* exit dispatcher saved in the task's stack frame at XT_STK_EXIT. +* May only be called from assembly code by the 'call0' instruction. Does not +* return to caller. +* See the description of the XT_RTOS_ENTER macro in xtensa_rtos.h. +* +******************************************************************************* +*/ + .globl _frxt_int_exit + .type _frxt_int_exit,@function + .align 4 +_frxt_int_exit: + + movi a2, port_xSchedulerRunning + movi a3, port_interruptNesting + rsil a0, XCHAL_EXCM_LEVEL /* lock out interrupts */ + l32i a2, a2, 0 /* a2 = port_xSchedulerRunning */ + beqz a2, .Lnoswitch /* scheduler not running, no tasks */ + l32i a2, a3, 0 /* a2 = port_interruptNesting */ + addi a2, a2, -1 /* decrement nesting count */ + s32i a2, a3, 0 /* save nesting count */ + bnez a2, .Lnesting /* !=0 after decr so still nested */ + + movi a2, pxCurrentTCB + l32i a2, a2, 0 /* a2 = current TCB */ + beqz a2, 1f /* no task ? go to dispatcher */ + l32i a1, a2, TOPOFSTACK_OFFS /* SP = pxCurrentTCB->pxTopOfStack */ + + movi a2, port_switch_flag /* address of switch flag */ + l32i a3, a2, 0 /* a3 = port_switch_flag */ + beqz a3, .Lnoswitch /* flag = 0 means no switch reqd */ + movi a3, 0 + s32i a3, a2, 0 /* zero out the flag for next time */ + +1: + /* + Call0 ABI callee-saved regs a12-15 need to be saved before possible preemption. + However a12-13 were already saved by _frxt_int_enter(). + */ + #ifdef __XTENSA_CALL0_ABI__ + s32i a14, a1, XT_STK_A14 + s32i a15, a1, XT_STK_A15 + #endif + + #ifdef __XTENSA_CALL0_ABI__ + call0 vPortYieldFromInt /* call dispatch inside the function; never returns */ + #else + call4 vPortYieldFromInt /* this one returns */ + call0 _frxt_dispatch /* tail-call dispatcher */ + /* Never returns here. */ + #endif + +.Lnoswitch: + /* + If we came here then about to resume the interrupted task. + */ + +.Lnesting: + /* + We come here only if there was no context switch, that is if this + is a nested interrupt, or the interrupted task was not preempted. + In either case there's no need to load the SP. + */ + + /* Restore full context from interrupt stack frame */ + call0 _xt_context_restore + + /* + Must return via the exit dispatcher corresponding to the entrypoint from which + this was called. Interruptee's A0, A1, PS, PC are restored and the interrupt + stack frame is deallocated in the exit dispatcher. + */ + l32i a0, a1, XT_STK_EXIT + ret + +/* +********************************************************************************************************** +* _frxt_timer_int +* void _frxt_timer_int(void) +* +* Implements the Xtensa RTOS porting layer's XT_RTOS_TIMER_INT function for FreeRTOS. +* Called every timer interrupt. +* Manages the tick timer and calls xPortSysTickHandler() every tick. +* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h. +* +* Callable from C (obeys ABI conventions). Implemented in assmebly code for performance. +* +********************************************************************************************************** +*/ + .globl _frxt_timer_int + .type _frxt_timer_int,@function + .align 4 +_frxt_timer_int: + + /* + Xtensa timers work by comparing a cycle counter with a preset value. Once the match occurs + an interrupt is generated, and the handler has to set a new cycle count into the comparator. + To avoid clock drift due to interrupt latency, the new cycle count is computed from the old, + not the time the interrupt was serviced. However if a timer interrupt is ever serviced more + than one tick late, it is necessary to process multiple ticks until the new cycle count is + in the future, otherwise the next timer interrupt would not occur until after the cycle + counter had wrapped (2^32 cycles later). + + do { + ticks++; + old_ccompare = read_ccompare_i(); + write_ccompare_i( old_ccompare + divisor ); + service one tick; + diff = read_ccount() - old_ccompare; + } while ( diff > divisor ); + */ + + ENTRY(16) + /* In RIOT-OS the timer is used in a different way and is realized in C functions. */ + #if 0 + +.L_xt_timer_int_catchup: + + /* Update the timer comparator for the next tick. */ + #ifdef XT_CLOCK_FREQ + movi a2, XT_TICK_DIVISOR /* a2 = comparator increment */ + #else + movi a3, _xt_tick_divisor + l32i a2, a3, 0 /* a2 = comparator increment */ + #endif + rsr a3, XT_CCOMPARE /* a3 = old comparator value */ + add a4, a3, a2 /* a4 = new comparator value */ + wsr a4, XT_CCOMPARE /* update comp. and clear interrupt */ + esync + + #ifdef __XTENSA_CALL0_ABI__ + /* Preserve a2 and a3 across C calls. */ + s32i a2, sp, 4 + s32i a3, sp, 8 + #endif + + /* Call the FreeRTOS tick handler (see port.c). */ + #ifdef __XTENSA_CALL0_ABI__ + call0 xPortSysTickHandler + #else + call4 xPortSysTickHandler + #endif + + #ifdef __XTENSA_CALL0_ABI__ + /* Restore a2 and a3. */ + l32i a2, sp, 4 + l32i a3, sp, 8 + #endif + + /* Check if we need to process more ticks to catch up. */ + esync /* ensure comparator update complete */ + rsr a4, CCOUNT /* a4 = cycle count */ + sub a4, a4, a3 /* diff = ccount - old comparator */ + blt a2, a4, .L_xt_timer_int_catchup /* repeat while diff > divisor */ + + #endif + RET(16) + + /* +********************************************************************************************************** +* _frxt_tick_timer_init +* void _frxt_tick_timer_init(void) +* +* Initialize timer and timer interrrupt handler (_xt_tick_divisor_init() has already been been called). +* Callable from C (obeys ABI conventions on entry). +* +********************************************************************************************************** +*/ +#if 0 + .globl _frxt_tick_timer_init + .type _frxt_tick_timer_init,@function + .align 4 +_frxt_tick_timer_init: + + ENTRY(16) + + /* Set up the periodic tick timer (assume enough time to complete init). */ + #ifdef XT_CLOCK_FREQ + movi a3, XT_TICK_DIVISOR + #else + movi a2, _xt_tick_divisor + l32i a3, a2, 0 + #endif + rsr a2, CCOUNT /* current cycle count */ + add a2, a2, a3 /* time of first timer interrupt */ + wsr a2, XT_CCOMPARE /* set the comparator */ + + /* + Enable the timer interrupt at the device level. Don't write directly + to the INTENABLE register because it may be virtualized. + */ + #ifdef __XTENSA_CALL0_ABI__ + movi a2, XT_TIMER_INTEN + call0 xt_ints_on + #else + movi a6, XT_TIMER_INTEN + call4 xt_ints_on + #endif + + RET(16) +#endif + +/* +********************************************************************************************************** +* DISPATCH THE HIGH READY TASK +* void _frxt_dispatch(void) +* +* Switch context to the highest priority ready task, restore its state and dispatch control to it. +* +* This is a common dispatcher that acts as a shared exit path for all the context switch functions +* including vPortYield() and vPortYieldFromInt(), all of which tail-call this dispatcher +* (for windowed ABI vPortYieldFromInt() calls it indirectly via _frxt_int_exit() ). +* +* The Xtensa port uses different stack frames for solicited and unsolicited task suspension (see +* comments on stack frames in xtensa_context.h). This function restores the state accordingly. +* If restoring a task that solicited entry, restores the minimal state and leaves CPENABLE clear. +* If restoring a task that was preempted, restores all state including the task's CPENABLE. +* +* Entry: +* pxCurrentTCB points to the TCB of the task to suspend, +* Because it is tail-called without a true function entrypoint, it needs no 'entry' instruction. +* +* Exit: +* If incoming task called vPortYield() (solicited), this function returns as if from vPortYield(). +* If incoming task was preempted by an interrupt, this function jumps to exit dispatcher. +* +********************************************************************************************************** +*/ + .globl _frxt_dispatch + .type _frxt_dispatch,@function + .align 4 +_frxt_dispatch: + + #ifdef __XTENSA_CALL0_ABI__ + call0 vTaskSwitchContext // Get next TCB to resume + movi a2, pxCurrentTCB + #else + movi a2, pxCurrentTCB + call4 vTaskSwitchContext // Get next TCB to resume + #endif + l32i a3, a2, 0 + l32i sp, a3, TOPOFSTACK_OFFS /* SP = next_TCB->pxTopOfStack; */ + s32i a3, a2, 0 + + /* Determine the type of stack frame. */ + l32i a2, sp, XT_STK_EXIT /* exit dispatcher or solicited flag */ + bnez a2, .L_frxt_dispatch_stk + +.L_frxt_dispatch_sol: + + /* Solicited stack frame. Restore minimal context and return from vPortYield(). */ + l32i a3, sp, XT_SOL_PS + #ifdef __XTENSA_CALL0_ABI__ + l32i a12, sp, XT_SOL_A12 + l32i a13, sp, XT_SOL_A13 + l32i a14, sp, XT_SOL_A14 + l32i a15, sp, XT_SOL_A15 + #endif + l32i a0, sp, XT_SOL_PC + #if XCHAL_CP_NUM > 0 + /* Ensure wsr.CPENABLE is complete (should be, it was cleared on entry). */ + rsync + #endif + /* As soons as PS is restored, interrupts can happen. No need to sync PS. */ + wsr a3, PS + #ifdef __XTENSA_CALL0_ABI__ + addi sp, sp, XT_SOL_FRMSZ + ret + #else + retw + #endif + +.L_frxt_dispatch_stk: + + #if XCHAL_CP_NUM > 0 + /* Restore CPENABLE from task's co-processor save area. */ + movi a3, pxCurrentTCB /* cp_state = */ + l32i a3, a3, 0 + l32i a2, a3, CP_TOPOFSTACK_OFFS /* StackType_t *pxStack; */ + l16ui a3, a2, XT_CPENABLE /* CPENABLE = cp_state->cpenable; */ + wsr a3, CPENABLE + #endif + + /* Interrupt stack frame. Restore full context and return to exit dispatcher. */ + call0 _xt_context_restore + + /* In Call0 ABI, restore callee-saved regs (A12, A13 already restored). */ + #ifdef __XTENSA_CALL0_ABI__ + l32i a14, sp, XT_STK_A14 + l32i a15, sp, XT_STK_A15 + #endif + + #if XCHAL_CP_NUM > 0 + /* Ensure wsr.CPENABLE has completed. */ + rsync + #endif + + /* + Must return via the exit dispatcher corresponding to the entrypoint from which + this was called. Interruptee's A0, A1, PS, PC are restored and the interrupt + stack frame is deallocated in the exit dispatcher. + */ + l32i a0, sp, XT_STK_EXIT + ret + + +/* +********************************************************************************************************** +* PERFORM A SOLICTED CONTEXT SWITCH (from a task) +* void vPortYield(void) +* +* This function saves the minimal state needed for a solicited task suspension, clears CPENABLE, +* then tail-calls the dispatcher _frxt_dispatch() to perform the actual context switch +* +* At Entry: +* pxCurrentTCB points to the TCB of the task to suspend +* Callable from C (obeys ABI conventions on entry). +* +* Does not return to caller. +* +********************************************************************************************************** +*/ + .globl vPortYield + .type vPortYield,@function + .align 4 +vPortYield: + + #ifdef __XTENSA_CALL0_ABI__ + addi sp, sp, -XT_SOL_FRMSZ + #else + entry sp, XT_SOL_FRMSZ + #endif + + rsr a2, PS + s32i a0, sp, XT_SOL_PC + s32i a2, sp, XT_SOL_PS + #ifdef __XTENSA_CALL0_ABI__ + s32i a12, sp, XT_SOL_A12 /* save callee-saved registers */ + s32i a13, sp, XT_SOL_A13 + s32i a14, sp, XT_SOL_A14 + s32i a15, sp, XT_SOL_A15 + #else + /* Spill register windows. Calling xthal_window_spill() causes extra */ + /* spills and reloads, so we will set things up to call the _nw version */ + /* instead to save cycles. */ + movi a6, ~(PS_WOE_MASK|PS_INTLEVEL_MASK) /* spills a4-a7 if needed */ + and a2, a2, a6 /* clear WOE, INTLEVEL */ + addi a2, a2, XCHAL_EXCM_LEVEL /* set INTLEVEL */ + wsr a2, PS + rsync + call0 xthal_window_spill_nw + l32i a2, sp, XT_SOL_PS /* restore PS */ + wsr a2, PS + #endif + + rsil a2, XCHAL_EXCM_LEVEL /* disable low/med interrupts */ + + #if XCHAL_CP_NUM > 0 + /* Save coprocessor callee-saved state (if any). At this point CPENABLE */ + /* should still reflect which CPs were in use (enabled). */ + call0 _xt_coproc_savecs + #endif + + movi a2, pxCurrentTCB + movi a3, 0 + l32i a2, a2, 0 /* a2 = pxCurrentTCB */ + s32i a3, sp, XT_SOL_EXIT /* 0 to flag as solicited frame */ + s32i sp, a2, TOPOFSTACK_OFFS /* pxCurrentTCB->pxTopOfStack = SP */ + + #if XCHAL_CP_NUM > 0 + /* Clear CPENABLE, also in task's co-processor state save area. */ + l32i a2, a2, CP_TOPOFSTACK_OFFS /* a2 = pxCurrentTCB->cp_state */ + movi a3, 0 + wsr a3, CPENABLE + beqz a2, 1f + s16i a3, a2, XT_CPENABLE /* clear saved cpenable */ +1: + #endif + + /* Tail-call dispatcher. */ + call0 _frxt_dispatch + /* Never reaches here. */ + + +/* +********************************************************************************************************** +* PERFORM AN UNSOLICITED CONTEXT SWITCH (from an interrupt) +* void vPortYieldFromInt(void) +* +* This calls the context switch hook (removed), saves and clears CPENABLE, then tail-calls the dispatcher +* _frxt_dispatch() to perform the actual context switch. +* +* At Entry: +* Interrupted task context has been saved in an interrupt stack frame at pxCurrentTCB->pxTopOfStack. +* pxCurrentTCB points to the TCB of the task to suspend, +* Callable from C (obeys ABI conventions on entry). +* +* At Exit: +* Windowed ABI defers the actual context switch until the stack is unwound to interrupt entry. +* Call0 ABI tail-calls the dispatcher directly (no need to unwind) so does not return to caller. +* +********************************************************************************************************** +*/ + .globl vPortYieldFromInt + .type vPortYieldFromInt,@function + .align 4 +vPortYieldFromInt: + + ENTRY(16) + + #if XCHAL_CP_NUM > 0 + /* Save CPENABLE in task's co-processor save area, and clear CPENABLE. */ + movi a3, pxCurrentTCB /* cp_state = */ + l32i a3, a3, 0 + l32i a2, a3, CP_TOPOFSTACK_OFFS + + rsr a3, CPENABLE + s16i a3, a2, XT_CPENABLE /* cp_state->cpenable = CPENABLE; */ + movi a3, 0 + wsr a3, CPENABLE /* disable all co-processors */ + #endif + + #ifdef __XTENSA_CALL0_ABI__ + /* Tail-call dispatcher. */ + call0 _frxt_dispatch + /* Never reaches here. */ + #else + RET(16) + #endif + +/* +********************************************************************************************************** +* _frxt_task_coproc_state +* void _frxt_task_coproc_state(void) +* +* Implements the Xtensa RTOS porting layer's XT_RTOS_CP_STATE function for FreeRTOS. +* +* May only be called when a task is running, not within an interrupt handler (returns 0 in that case). +* May only be called from assembly code by the 'call0' instruction. Does NOT obey ABI conventions. +* Returns in A15 a pointer to the base of the co-processor state save area for the current task. +* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h. +* +********************************************************************************************************** +*/ +#if XCHAL_CP_NUM > 0 + + .globl _frxt_task_coproc_state + .type _frxt_task_coproc_state,@function + .align 4 +_frxt_task_coproc_state: + + movi a15, port_xSchedulerRunning /* if (port_xSchedulerRunning */ + l32i a15, a15, 0 + beqz a15, 1f + movi a15, port_interruptNesting /* && port_interruptNesting == 0 */ + l32i a15, a15, 0 + bnez a15, 1f + movi a15, pxCurrentTCB + l32i a15, a15, 0 /* && pxCurrentTCB != 0) { */ + beqz a15, 2f + l32i a15, a15, CP_TOPOFSTACK_OFFS + ret + +1: movi a15, 0 +2: ret + +#endif /* XCHAL_CP_NUM > 0 */ diff --git a/cpu/esp8266/vendor/xtensa/xtensa_api.h b/cpu/esp8266/vendor/xtensa/xtensa_api.h new file mode 100644 index 0000000000..025b3d1676 --- /dev/null +++ b/cpu/esp8266/vendor/xtensa/xtensa_api.h @@ -0,0 +1,127 @@ +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + +/****************************************************************************** + Xtensa-specific API for RTOS ports. +******************************************************************************/ + +#ifndef XTENSA_API_H +#define XTENSA_API_H + +#include + +#include "xtensa_context.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Typedef for C-callable interrupt handler function */ +typedef void (*xt_handler)(void *); + +/* Typedef for C-callable exception handler function */ +typedef void (*xt_exc_handler)(XtExcFrame *); + + +/* +------------------------------------------------------------------------------- + Call this function to set a handler for the specified exception. + + n - Exception number (type) + f - Handler function address, NULL to uninstall handler. + + The handler will be passed a pointer to the exception frame, which is created + on the stack of the thread that caused the exception. + + If the handler returns, the thread context will be restored and the faulting + instruction will be retried. Any values in the exception frame that are + modified by the handler will be restored as part of the context. For details + of the exception frame structure see xtensa_context.h. +------------------------------------------------------------------------------- +*/ +extern xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f); + + +/* +------------------------------------------------------------------------------- + Call this function to set a handler for the specified interrupt. + + n - Interrupt number. + f - Handler function address, NULL to uninstall handler. + arg - Argument to be passed to handler. +------------------------------------------------------------------------------- +*/ +extern xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg); + + +/* +------------------------------------------------------------------------------- + Call this function to enable the specified interrupts. + + mask - Bit mask of interrupts to be enabled. + + Returns the previous state of the interrupt enables. +------------------------------------------------------------------------------- +*/ +extern unsigned int xt_ints_on(unsigned int mask); + + +/* +------------------------------------------------------------------------------- + Call this function to disable the specified interrupts. + + mask - Bit mask of interrupts to be disabled. + + Returns the previous state of the interrupt enables. +------------------------------------------------------------------------------- +*/ +extern unsigned int xt_ints_off(unsigned int mask); + + +/* +------------------------------------------------------------------------------- + Call this function to set the specified (s/w) interrupt. +------------------------------------------------------------------------------- +*/ +static inline void xt_set_intset(unsigned int arg) +{ + xthal_set_intset(arg); +} + + +/* +------------------------------------------------------------------------------- + Call this function to clear the specified (s/w or edge-triggered) + interrupt. +------------------------------------------------------------------------------- +*/ +static inline void xt_set_intclear(unsigned int arg) +{ + xthal_set_intclear(arg); +} + +#ifdef __cplusplus +} +#endif + +#endif /* XTENSA_API_H */ diff --git a/cpu/esp8266/vendor/xtensa/xtensa_context.S b/cpu/esp8266/vendor/xtensa/xtensa_context.S new file mode 100644 index 0000000000..c67d86a7fa --- /dev/null +++ b/cpu/esp8266/vendor/xtensa/xtensa_context.S @@ -0,0 +1,623 @@ +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + + XTENSA CONTEXT SAVE AND RESTORE ROUTINES + +Low-level Call0 functions for handling generic context save and restore of +registers not specifically addressed by the interrupt vectors and handlers. +Those registers (not handled by these functions) are PC, PS, A0, A1 (SP). +Except for the calls to RTOS functions, this code is generic to Xtensa. + +Note that in Call0 ABI, interrupt handlers are expected to preserve the callee- +save regs (A12-A15), which is always the case if the handlers are coded in C. +However A12, A13 are made available as scratch registers for interrupt dispatch +code, so are presumed saved anyway, and are always restored even in Call0 ABI. +Only A14, A15 are truly handled as callee-save regs. + +Because Xtensa is a configurable architecture, this port supports all user +generated configurations (except restrictions stated in the release notes). +This is accomplished by conditional compilation using macros and functions +defined in the Xtensa HAL (hardware adaptation layer) for your configuration. +Only the processor state included in your configuration is saved and restored, +including any processor state added by user configuration options or TIE. + +*******************************************************************************/ + +/* Warn nicely if this file gets named with a lowercase .s instead of .S: */ +#define NOERROR # +NOERROR: .error "C preprocessor needed for this file: make sure its filename\ + ends in uppercase .S, or use xt-xcc's -x assembler-with-cpp option." + +//#include "xtensa_rtos.h" +#include "xtensa_context.h" + +#ifdef XT_USE_OVLY +#include +#endif + + .text + +/******************************************************************************* + +_xt_context_save + + !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !! + +Saves all Xtensa processor state except PC, PS, A0, A1 (SP), A12, A13, in the +interrupt stack frame defined in xtensa_rtos.h. +Its counterpart is _xt_context_restore (which also restores A12, A13). + +Caller is expected to have saved PC, PS, A0, A1 (SP), A12, A13 in the frame. +This function preserves A12 & A13 in order to provide the caller with 2 scratch +regs that need not be saved over the call to this function. The choice of which +2 regs to provide is governed by xthal_window_spill_nw and xthal_save_extra_nw, +to avoid moving data more than necessary. Caller can assign regs accordingly. + +Entry Conditions: + A0 = Return address in caller. + A1 = Stack pointer of interrupted thread or handler ("interruptee"). + Original A12, A13 have already been saved in the interrupt stack frame. + Other processor state except PC, PS, A0, A1 (SP), A12, A13, is as at the + point of interruption. + If windowed ABI, PS.EXCM = 1 (exceptions disabled). + +Exit conditions: + A0 = Return address in caller. + A1 = Stack pointer of interrupted thread or handler ("interruptee"). + A12, A13 as at entry (preserved). + If windowed ABI, PS.EXCM = 1 (exceptions disabled). + +*******************************************************************************/ + + .global _xt_context_save + .type _xt_context_save,@function + .align 4 +_xt_context_save: + + s32i a2, sp, XT_STK_A2 + s32i a3, sp, XT_STK_A3 + s32i a4, sp, XT_STK_A4 + s32i a5, sp, XT_STK_A5 + s32i a6, sp, XT_STK_A6 + s32i a7, sp, XT_STK_A7 + s32i a8, sp, XT_STK_A8 + s32i a9, sp, XT_STK_A9 + s32i a10, sp, XT_STK_A10 + s32i a11, sp, XT_STK_A11 + + /* + Call0 ABI callee-saved regs a12-15 do not need to be saved here. + a12-13 are the caller's responsibility so it can use them as scratch. + So only need to save a14-a15 here for Windowed ABI (not Call0). + */ + #ifndef __XTENSA_CALL0_ABI__ + s32i a14, sp, XT_STK_A14 + s32i a15, sp, XT_STK_A15 + #endif + + rsr a3, SAR + s32i a3, sp, XT_STK_SAR + + #if XCHAL_HAVE_LOOPS + rsr a3, LBEG + s32i a3, sp, XT_STK_LBEG + rsr a3, LEND + s32i a3, sp, XT_STK_LEND + rsr a3, LCOUNT + s32i a3, sp, XT_STK_LCOUNT + #endif + + #if XT_USE_SWPRI + /* Save virtual priority mask */ + movi a3, _xt_vpri_mask + l32i a3, a3, 0 + s32i a3, sp, XT_STK_VPRI + #endif + + #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__) + mov a9, a0 /* preserve ret addr */ + #endif + + #ifndef __XTENSA_CALL0_ABI__ + /* + To spill the reg windows, temp. need pre-interrupt stack ptr and a4-15. + Need to save a9,12,13 temporarily (in frame temps) and recover originals. + Interrupts need to be disabled below XCHAL_EXCM_LEVEL and window overflow + and underflow exceptions disabled (assured by PS.EXCM == 1). + */ + s32i a12, sp, XT_STK_TMP0 /* temp. save stuff in stack frame */ + s32i a13, sp, XT_STK_TMP1 + s32i a9, sp, XT_STK_TMP2 + + /* + Save the overlay state if we are supporting overlays. Since we just saved + three registers, we can conveniently use them here. Note that as of now, + overlays only work for windowed calling ABI. + */ + #ifdef XT_USE_OVLY + l32i a9, sp, XT_STK_PC /* recover saved PC */ + _xt_overlay_get_state a9, a12, a13 + s32i a9, sp, XT_STK_OVLY /* save overlay state */ + #endif + + l32i a12, sp, XT_STK_A12 /* recover original a9,12,13 */ + l32i a13, sp, XT_STK_A13 + l32i a9, sp, XT_STK_A9 + addi sp, sp, XT_STK_FRMSZ /* restore the interruptee's SP */ + call0 xthal_window_spill_nw /* preserves only a4,5,8,9,12,13 */ + addi sp, sp, -XT_STK_FRMSZ + l32i a12, sp, XT_STK_TMP0 /* recover stuff from stack frame */ + l32i a13, sp, XT_STK_TMP1 + l32i a9, sp, XT_STK_TMP2 + #endif + + #if XCHAL_EXTRA_SA_SIZE > 0 + /* + NOTE: Normally the xthal_save_extra_nw macro only affects address + registers a2-a5. It is theoretically possible for Xtensa processor + designers to write TIE that causes more address registers to be + affected, but it is generally unlikely. If that ever happens, + more registers need to be saved/restored around this macro invocation. + Here we assume a9,12,13 are preserved. + Future Xtensa tools releases might limit the regs that can be affected. + */ + addi a2, sp, XT_STK_EXTRA /* where to save it */ + # if XCHAL_EXTRA_SA_ALIGN > 16 + movi a3, -XCHAL_EXTRA_SA_ALIGN + and a2, a2, a3 /* align dynamically >16 bytes */ + # endif + call0 xthal_save_extra_nw /* destroys a0,2,3,4,5 */ + #endif + + #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__) + mov a0, a9 /* retrieve ret addr */ + #endif + + ret + +/******************************************************************************* + +_xt_context_restore + + !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !! + +Restores all Xtensa processor state except PC, PS, A0, A1 (SP) (and in Call0 +ABI, A14, A15 which are preserved by all interrupt handlers) from an interrupt +stack frame defined in xtensa_rtos.h . +Its counterpart is _xt_context_save (whose caller saved A12, A13). + +Caller is responsible to restore PC, PS, A0, A1 (SP). + +Entry Conditions: + A0 = Return address in caller. + A1 = Stack pointer of interrupted thread or handler ("interruptee"). + +Exit conditions: + A0 = Return address in caller. + A1 = Stack pointer of interrupted thread or handler ("interruptee"). + Other processor state except PC, PS, A0, A1 (SP), is as at the point + of interruption. + +*******************************************************************************/ + + .global _xt_context_restore + .type _xt_context_restore,@function + .align 4 +_xt_context_restore: + + #if XCHAL_EXTRA_SA_SIZE > 0 + /* + NOTE: Normally the xthal_restore_extra_nw macro only affects address + registers a2-a5. It is theoretically possible for Xtensa processor + designers to write TIE that causes more address registers to be + affected, but it is generally unlikely. If that ever happens, + more registers need to be saved/restored around this macro invocation. + Here we only assume a13 is preserved. + Future Xtensa tools releases might limit the regs that can be affected. + */ + mov a13, a0 /* preserve ret addr */ + addi a2, sp, XT_STK_EXTRA /* where to find it */ + # if XCHAL_EXTRA_SA_ALIGN > 16 + movi a3, -XCHAL_EXTRA_SA_ALIGN + and a2, a2, a3 /* align dynamically >16 bytes */ + # endif + call0 xthal_restore_extra_nw /* destroys a0,2,3,4,5 */ + mov a0, a13 /* retrieve ret addr */ + #endif + + #if XCHAL_HAVE_LOOPS + l32i a2, sp, XT_STK_LBEG + l32i a3, sp, XT_STK_LEND + wsr a2, LBEG + l32i a2, sp, XT_STK_LCOUNT + wsr a3, LEND + wsr a2, LCOUNT + #endif + + #ifdef XT_USE_OVLY + /* + If we are using overlays, this is a good spot to check if we need + to restore an overlay for the incoming task. Here we have a bunch + of registers to spare. Note that this step is going to use a few + bytes of storage below SP (SP-20 to SP-32) if an overlay is going + to be restored. + */ + l32i a2, sp, XT_STK_PC /* retrieve PC */ + l32i a3, sp, XT_STK_PS /* retrieve PS */ + l32i a4, sp, XT_STK_OVLY /* retrieve overlay state */ + l32i a5, sp, XT_STK_A1 /* retrieve stack ptr */ + _xt_overlay_check_map a2, a3, a4, a5, a6 + s32i a2, sp, XT_STK_PC /* save updated PC */ + s32i a3, sp, XT_STK_PS /* save updated PS */ + #endif + + #ifdef XT_USE_SWPRI + /* Restore virtual interrupt priority and interrupt enable */ + movi a3, _xt_intdata + l32i a4, a3, 0 /* a4 = _xt_intenable */ + l32i a5, sp, XT_STK_VPRI /* a5 = saved _xt_vpri_mask */ + and a4, a4, a5 + wsr a4, INTENABLE /* update INTENABLE */ + s32i a5, a3, 4 /* restore _xt_vpri_mask */ + #endif + + l32i a3, sp, XT_STK_SAR + l32i a2, sp, XT_STK_A2 + wsr a3, SAR + l32i a3, sp, XT_STK_A3 + l32i a4, sp, XT_STK_A4 + l32i a5, sp, XT_STK_A5 + l32i a6, sp, XT_STK_A6 + l32i a7, sp, XT_STK_A7 + l32i a8, sp, XT_STK_A8 + l32i a9, sp, XT_STK_A9 + l32i a10, sp, XT_STK_A10 + l32i a11, sp, XT_STK_A11 + + /* + Call0 ABI callee-saved regs a12-15 do not need to be restored here. + However a12-13 were saved for scratch before XT_RTOS_INT_ENTER(), + so need to be restored anyway, despite being callee-saved in Call0. + */ + l32i a12, sp, XT_STK_A12 + l32i a13, sp, XT_STK_A13 + #ifndef __XTENSA_CALL0_ABI__ + l32i a14, sp, XT_STK_A14 + l32i a15, sp, XT_STK_A15 + #endif + + ret + + +/******************************************************************************* + +_xt_coproc_init + +Initializes global co-processor management data, setting all co-processors +to "unowned". Leaves CPENABLE as it found it (does NOT clear it). + +Called during initialization of the RTOS, before any threads run. + +This may be called from normal Xtensa single-threaded application code which +might use co-processors. The Xtensa run-time initialization enables all +co-processors. They must remain enabled here, else a co-processor exception +might occur outside of a thread, which the exception handler doesn't expect. + +Entry Conditions: + Xtensa single-threaded run-time environment is in effect. + No thread is yet running. + +Exit conditions: + None. + +Obeys ABI conventions per prototype: + void _xt_coproc_init(void) + +*******************************************************************************/ + +#if XCHAL_CP_NUM > 0 + + .global _xt_coproc_init + .type _xt_coproc_init,@function + .align 4 +_xt_coproc_init: + ENTRY0 + + /* Initialize thread co-processor ownerships to 0 (unowned). */ + movi a2, _xt_coproc_owner_sa /* a2 = base of owner array */ + addi a3, a2, XCHAL_CP_MAX << 2 /* a3 = top+1 of owner array */ + movi a4, 0 /* a4 = 0 (unowned) */ +1: s32i a4, a2, 0 + addi a2, a2, 4 + bltu a2, a3, 1b + + RET0 + +#endif + + +/******************************************************************************* + +_xt_coproc_release + +Releases any and all co-processors owned by a given thread. The thread is +identified by it's co-processor state save area defined in xtensa_context.h . + +Must be called before a thread's co-proc save area is deleted to avoid +memory corruption when the exception handler tries to save the state. +May be called when a thread terminates or completes but does not delete +the co-proc save area, to avoid the exception handler having to save the +thread's co-proc state before another thread can use it (optimization). + +Entry Conditions: + A2 = Pointer to base of co-processor state save area. + +Exit conditions: + None. + +Obeys ABI conventions per prototype: + void _xt_coproc_release(void * coproc_sa_base) + +*******************************************************************************/ + +#if XCHAL_CP_NUM > 0 + + .global _xt_coproc_release + .type _xt_coproc_release,@function + .align 4 +_xt_coproc_release: + ENTRY0 /* a2 = base of save area */ + + movi a3, _xt_coproc_owner_sa /* a3 = base of owner array */ + addi a4, a3, XCHAL_CP_MAX << 2 /* a4 = top+1 of owner array */ + movi a5, 0 /* a5 = 0 (unowned) */ + + rsil a6, XCHAL_EXCM_LEVEL /* lock interrupts */ + +1: l32i a7, a3, 0 /* a7 = owner at a3 */ + bne a2, a7, 2f /* if (coproc_sa_base == owner) */ + s32i a5, a3, 0 /* owner = unowned */ +2: addi a3, a3, 1<<2 /* a3 = next entry in owner array */ + bltu a3, a4, 1b /* repeat until end of array */ + +3: wsr a6, PS /* restore interrupts */ + + RET0 + +#endif + + +/******************************************************************************* +_xt_coproc_savecs + +If there is a current thread and it has a coprocessor state save area, then +save all callee-saved state into this area. This function is called from the +solicited context switch handler. It calls a system-specific function to get +the coprocessor save area base address. + +Entry conditions: + - The thread being switched out is still the current thread. + - CPENABLE state reflects which coprocessors are active. + - Registers have been saved/spilled already. + +Exit conditions: + - All necessary CP callee-saved state has been saved. + - Registers a2-a7, a13-a15 have been trashed. + +Must be called from assembly code only, using CALL0. +*******************************************************************************/ +#if XCHAL_CP_NUM > 0 + + .extern _xt_coproc_sa_offset /* external reference */ + + .global _xt_coproc_savecs + .type _xt_coproc_savecs,@function + .align 4 +_xt_coproc_savecs: + + /* At entry, CPENABLE should be showing which CPs are enabled. */ + + rsr a2, CPENABLE /* a2 = which CPs are enabled */ + beqz a2, .Ldone /* quick exit if none */ + mov a14, a0 /* save return address */ + call0 XT_RTOS_CP_STATE /* get address of CP save area */ + mov a0, a14 /* restore return address */ + beqz a15, .Ldone /* if none then nothing to do */ + s16i a2, a15, XT_CP_CS_ST /* save mask of CPs being stored */ + movi a13, _xt_coproc_sa_offset /* array of CP save offsets */ + l32i a15, a15, XT_CP_ASA /* a15 = base of aligned save area */ + +#if XCHAL_CP0_SA_SIZE + bbci.l a2, 0, 2f /* CP 0 not enabled */ + l32i a14, a13, 0 /* a14 = _xt_coproc_sa_offset[0] */ + add a3, a14, a15 /* a3 = save area for CP 0 */ + xchal_cp0_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP1_SA_SIZE + bbci.l a2, 1, 2f /* CP 1 not enabled */ + l32i a14, a13, 4 /* a14 = _xt_coproc_sa_offset[1] */ + add a3, a14, a15 /* a3 = save area for CP 1 */ + xchal_cp1_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP2_SA_SIZE + bbci.l a2, 2, 2f + l32i a14, a13, 8 + add a3, a14, a15 + xchal_cp2_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP3_SA_SIZE + bbci.l a2, 3, 2f + l32i a14, a13, 12 + add a3, a14, a15 + xchal_cp3_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP4_SA_SIZE + bbci.l a2, 4, 2f + l32i a14, a13, 16 + add a3, a14, a15 + xchal_cp4_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP5_SA_SIZE + bbci.l a2, 5, 2f + l32i a14, a13, 20 + add a3, a14, a15 + xchal_cp5_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP6_SA_SIZE + bbci.l a2, 6, 2f + l32i a14, a13, 24 + add a3, a14, a15 + xchal_cp6_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP7_SA_SIZE + bbci.l a2, 7, 2f + l32i a14, a13, 28 + add a3, a14, a15 + xchal_cp7_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +.Ldone: + ret +#endif + + +/******************************************************************************* +_xt_coproc_restorecs + +Restore any callee-saved coprocessor state for the incoming thread. +This function is called from coprocessor exception handling, when giving +ownership to a thread that solicited a context switch earlier. It calls a +system-specific function to get the coprocessor save area base address. + +Entry conditions: + - The incoming thread is set as the current thread. + - CPENABLE is set up correctly for all required coprocessors. + - a2 = mask of coprocessors to be restored. + +Exit conditions: + - All necessary CP callee-saved state has been restored. + - CPENABLE - unchanged. + - Registers a2-a7, a13-a15 have been trashed. + +Must be called from assembly code only, using CALL0. +*******************************************************************************/ +#if XCHAL_CP_NUM > 0 + + .global _xt_coproc_restorecs + .type _xt_coproc_restorecs,@function + .align 4 +_xt_coproc_restorecs: + + mov a14, a0 /* save return address */ + call0 XT_RTOS_CP_STATE /* get address of CP save area */ + mov a0, a14 /* restore return address */ + beqz a15, .Ldone2 /* if none then nothing to do */ + l16ui a3, a15, XT_CP_CS_ST /* a3 = which CPs have been saved */ + xor a3, a3, a2 /* clear the ones being restored */ + s32i a3, a15, XT_CP_CS_ST /* update saved CP mask */ + movi a13, _xt_coproc_sa_offset /* array of CP save offsets */ + l32i a15, a15, XT_CP_ASA /* a15 = base of aligned save area */ + +#if XCHAL_CP0_SA_SIZE + bbci.l a2, 0, 2f /* CP 0 not enabled */ + l32i a14, a13, 0 /* a14 = _xt_coproc_sa_offset[0] */ + add a3, a14, a15 /* a3 = save area for CP 0 */ + xchal_cp0_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP1_SA_SIZE + bbci.l a2, 1, 2f /* CP 1 not enabled */ + l32i a14, a13, 4 /* a14 = _xt_coproc_sa_offset[1] */ + add a3, a14, a15 /* a3 = save area for CP 1 */ + xchal_cp1_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP2_SA_SIZE + bbci.l a2, 2, 2f + l32i a14, a13, 8 + add a3, a14, a15 + xchal_cp2_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP3_SA_SIZE + bbci.l a2, 3, 2f + l32i a14, a13, 12 + add a3, a14, a15 + xchal_cp3_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP4_SA_SIZE + bbci.l a2, 4, 2f + l32i a14, a13, 16 + add a3, a14, a15 + xchal_cp4_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP5_SA_SIZE + bbci.l a2, 5, 2f + l32i a14, a13, 20 + add a3, a14, a15 + xchal_cp5_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP6_SA_SIZE + bbci.l a2, 6, 2f + l32i a14, a13, 24 + add a3, a14, a15 + xchal_cp6_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +#if XCHAL_CP7_SA_SIZE + bbci.l a2, 7, 2f + l32i a14, a13, 28 + add a3, a14, a15 + xchal_cp7_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL +2: +#endif + +.Ldone2: + ret + +#endif diff --git a/cpu/esp8266/vendor/xtensa/xtensa_context.h b/cpu/esp8266/vendor/xtensa/xtensa_context.h new file mode 100644 index 0000000000..e331d62482 --- /dev/null +++ b/cpu/esp8266/vendor/xtensa/xtensa_context.h @@ -0,0 +1,355 @@ +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + + XTENSA CONTEXT FRAMES AND MACROS FOR RTOS ASSEMBLER SOURCES + +This header contains definitions and macros for use primarily by Xtensa +RTOS assembly coded source files. It includes and uses the Xtensa hardware +abstraction layer (HAL) to deal with config specifics. It may also be +included in C source files. + +!! Supports only Xtensa Exception Architecture 2 (XEA2). XEA1 not supported. !! + +NOTE: The Xtensa architecture requires stack pointer alignment to 16 bytes. + +*******************************************************************************/ + +#ifndef XTENSA_CONTEXT_H +#define XTENSA_CONTEXT_H + +#ifdef __ASSEMBLER__ +#include +#endif + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Align a value up to nearest n-byte boundary, where n is a power of 2. */ +#define ALIGNUP(n, val) (((val) + (n)-1) & -(n)) + + +/* +------------------------------------------------------------------------------- + Macros that help define structures for both C and assembler. +------------------------------------------------------------------------------- +*/ +#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) + +#define STRUCT_BEGIN .pushsection .text; .struct 0 +#define STRUCT_FIELD(ctype,size,asname,name) asname: .space size +#define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n) +#define STRUCT_END(sname) sname##Size:; .popsection + +#else + +#define STRUCT_BEGIN typedef struct { +#define STRUCT_FIELD(ctype,size,asname,name) ctype name; +#define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n]; +#define STRUCT_END(sname) } sname; + +#endif //_ASMLANGUAGE || __ASSEMBLER__ + + +/* +------------------------------------------------------------------------------- + INTERRUPT/EXCEPTION STACK FRAME FOR A THREAD OR NESTED INTERRUPT + + A stack frame of this structure is allocated for any interrupt or exception. + It goes on the current stack. If the RTOS has a system stack for handling + interrupts, every thread stack must allow space for just one interrupt stack + frame, then nested interrupt stack frames go on the system stack. + + The frame includes basic registers (explicit) and "extra" registers introduced + by user TIE or the use of the MAC16 option in the user's Xtensa config. + The frame size is minimized by omitting regs not applicable to user's config. + + For Windowed ABI, this stack frame includes the interruptee's base save area, + another base save area to manage gcc nested functions, and a little temporary + space to help manage the spilling of the register windows. +------------------------------------------------------------------------------- +*/ + +STRUCT_BEGIN +STRUCT_FIELD (long, 4, XT_STK_EXIT, exit) /* exit point for dispatch */ +STRUCT_FIELD (long, 4, XT_STK_PC, pc) /* return PC */ +STRUCT_FIELD (long, 4, XT_STK_PS, ps) /* return PS */ +STRUCT_FIELD (long, 4, XT_STK_A0, a0) +STRUCT_FIELD (long, 4, XT_STK_A1, a1) /* stack pointer before interrupt */ +STRUCT_FIELD (long, 4, XT_STK_A2, a2) +STRUCT_FIELD (long, 4, XT_STK_A3, a3) +STRUCT_FIELD (long, 4, XT_STK_A4, a4) +STRUCT_FIELD (long, 4, XT_STK_A5, a5) +STRUCT_FIELD (long, 4, XT_STK_A6, a6) +STRUCT_FIELD (long, 4, XT_STK_A7, a7) +STRUCT_FIELD (long, 4, XT_STK_A8, a8) +STRUCT_FIELD (long, 4, XT_STK_A9, a9) +STRUCT_FIELD (long, 4, XT_STK_A10, a10) +STRUCT_FIELD (long, 4, XT_STK_A11, a11) +STRUCT_FIELD (long, 4, XT_STK_A12, a12) +STRUCT_FIELD (long, 4, XT_STK_A13, a13) +STRUCT_FIELD (long, 4, XT_STK_A14, a14) +STRUCT_FIELD (long, 4, XT_STK_A15, a15) +STRUCT_FIELD (long, 4, XT_STK_SAR, sar) +STRUCT_FIELD (long, 4, XT_STK_EXCCAUSE, exccause) +STRUCT_FIELD (long, 4, XT_STK_EXCVADDR, excvaddr) +#if XCHAL_HAVE_LOOPS +STRUCT_FIELD (long, 4, XT_STK_LBEG, lbeg) +STRUCT_FIELD (long, 4, XT_STK_LEND, lend) +STRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount) +#endif +#ifndef __XTENSA_CALL0_ABI__ +/* Temporary space for saving stuff during window spill */ +STRUCT_FIELD (long, 4, XT_STK_TMP0, tmp0) +STRUCT_FIELD (long, 4, XT_STK_TMP1, tmp1) +STRUCT_FIELD (long, 4, XT_STK_TMP2, tmp2) +#endif +#ifdef XT_USE_SWPRI +/* Storage for virtual priority mask */ +STRUCT_FIELD (long, 4, XT_STK_VPRI, vpri) +#endif +#ifdef XT_USE_OVLY +/* Storage for overlay state */ +STRUCT_FIELD (long, 4, XT_STK_OVLY, ovly) +#endif +STRUCT_END(XtExcFrame) + +#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) +#define XT_STK_NEXT1 XtExcFrameSize +#else +#define XT_STK_NEXT1 sizeof(XtExcFrame) +#endif + +/* Allocate extra storage if needed */ +#if XCHAL_EXTRA_SA_SIZE != 0 + +#if XCHAL_EXTRA_SA_ALIGN <= 16 +#define XT_STK_EXTRA ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1) +#else +/* If need more alignment than stack, add space for dynamic alignment */ +#define XT_STK_EXTRA (ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1) + XCHAL_EXTRA_SA_ALIGN) +#endif +#define XT_STK_NEXT2 (XT_STK_EXTRA + XCHAL_EXTRA_SA_SIZE) + +#else + +#define XT_STK_NEXT2 XT_STK_NEXT1 + +#endif + +/* +------------------------------------------------------------------------------- + This is the frame size. Add space for 4 registers (interruptee's base save + area) and some space for gcc nested functions if any. +------------------------------------------------------------------------------- +*/ +#define XT_STK_FRMSZ (ALIGNUP(0x10, XT_STK_NEXT2) + 0x20) + + +/* +------------------------------------------------------------------------------- + SOLICITED STACK FRAME FOR A THREAD + + A stack frame of this structure is allocated whenever a thread enters the + RTOS kernel intentionally (and synchronously) to submit to thread scheduling. + It goes on the current thread's stack. + + The solicited frame only includes registers that are required to be preserved + by the callee according to the compiler's ABI conventions, some space to save + the return address for returning to the caller, and the caller's PS register. + + For Windowed ABI, this stack frame includes the caller's base save area. + + Note on XT_SOL_EXIT field: + It is necessary to distinguish a solicited from an interrupt stack frame. + This field corresponds to XT_STK_EXIT in the interrupt stack frame and is + always at the same offset (0). It can be written with a code (usually 0) + to distinguish a solicted frame from an interrupt frame. An RTOS port may + opt to ignore this field if it has another way of distinguishing frames. +------------------------------------------------------------------------------- +*/ + +STRUCT_BEGIN +#ifdef __XTENSA_CALL0_ABI__ +STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit) +STRUCT_FIELD (long, 4, XT_SOL_PC, pc) +STRUCT_FIELD (long, 4, XT_SOL_PS, ps) +STRUCT_FIELD (long, 4, XT_SOL_NEXT, next) +STRUCT_FIELD (long, 4, XT_SOL_A12, a12) /* should be on 16-byte alignment */ +STRUCT_FIELD (long, 4, XT_SOL_A13, a13) +STRUCT_FIELD (long, 4, XT_SOL_A14, a14) +STRUCT_FIELD (long, 4, XT_SOL_A15, a15) +#else +STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit) +STRUCT_FIELD (long, 4, XT_SOL_PC, pc) +STRUCT_FIELD (long, 4, XT_SOL_PS, ps) +STRUCT_FIELD (long, 4, XT_SOL_NEXT, next) +STRUCT_FIELD (long, 4, XT_SOL_A0, a0) /* should be on 16-byte alignment */ +STRUCT_FIELD (long, 4, XT_SOL_A1, a1) +STRUCT_FIELD (long, 4, XT_SOL_A2, a2) +STRUCT_FIELD (long, 4, XT_SOL_A3, a3) +#endif +STRUCT_END(XtSolFrame) + +/* Size of solicited stack frame */ +#define XT_SOL_FRMSZ ALIGNUP(0x10, XtSolFrameSize) + + +/* +------------------------------------------------------------------------------- + CO-PROCESSOR STATE SAVE AREA FOR A THREAD + + The RTOS must provide an area per thread to save the state of co-processors + when that thread does not have control. Co-processors are context-switched + lazily (on demand) only when a new thread uses a co-processor instruction, + otherwise a thread retains ownership of the co-processor even when it loses + control of the processor. An Xtensa co-processor exception is triggered when + any co-processor instruction is executed by a thread that is not the owner, + and the context switch of that co-processor is then peformed by the handler. + Ownership represents which thread's state is currently in the co-processor. + + Co-processors may not be used by interrupt or exception handlers. If an + co-processor instruction is executed by an interrupt or exception handler, + the co-processor exception handler will trigger a kernel panic and freeze. + This restriction is introduced to reduce the overhead of saving and restoring + co-processor state (which can be quite large) and in particular remove that + overhead from interrupt handlers. + + The co-processor state save area may be in any convenient per-thread location + such as in the thread control block or above the thread stack area. It need + not be in the interrupt stack frame since interrupts don't use co-processors. + + Along with the save area for each co-processor, two bitmasks with flags per + co-processor (laid out as in the CPENABLE reg) help manage context-switching + co-processors as efficiently as possible: + + XT_CPENABLE + The contents of a non-running thread's CPENABLE register. + It represents the co-processors owned (and whose state is still needed) + by the thread. When a thread is preempted, its CPENABLE is saved here. + When a thread solicits a context-swtich, its CPENABLE is cleared - the + compiler has saved the (caller-saved) co-proc state if it needs to. + When a non-running thread loses ownership of a CP, its bit is cleared. + When a thread runs, it's XT_CPENABLE is loaded into the CPENABLE reg. + Avoids co-processor exceptions when no change of ownership is needed. + + XT_CPSTORED + A bitmask with the same layout as CPENABLE, a bit per co-processor. + Indicates whether the state of each co-processor is saved in the state + save area. When a thread enters the kernel, only the state of co-procs + still enabled in CPENABLE is saved. When the co-processor exception + handler assigns ownership of a co-processor to a thread, it restores + the saved state only if this bit is set, and clears this bit. + + XT_CP_CS_ST + A bitmask with the same layout as CPENABLE, a bit per co-processor. + Indicates whether callee-saved state is saved in the state save area. + Callee-saved state is saved by itself on a solicited context switch, + and restored when needed by the coprocessor exception handler. + Unsolicited switches will cause the entire coprocessor to be saved + when necessary. + + XT_CP_ASA + Pointer to the aligned save area. Allows it to be aligned more than + the overall save area (which might only be stack-aligned or TCB-aligned). + Especially relevant for Xtensa cores configured with a very large data + path that requires alignment greater than 16 bytes (ABI stack alignment). +------------------------------------------------------------------------------- +*/ + +#if XCHAL_CP_NUM > 0 + +/* Offsets of each coprocessor save area within the 'aligned save area': */ +#define XT_CP0_SA 0 +#define XT_CP1_SA ALIGNUP(XCHAL_CP1_SA_ALIGN, XT_CP0_SA + XCHAL_CP0_SA_SIZE) +#define XT_CP2_SA ALIGNUP(XCHAL_CP2_SA_ALIGN, XT_CP1_SA + XCHAL_CP1_SA_SIZE) +#define XT_CP3_SA ALIGNUP(XCHAL_CP3_SA_ALIGN, XT_CP2_SA + XCHAL_CP2_SA_SIZE) +#define XT_CP4_SA ALIGNUP(XCHAL_CP4_SA_ALIGN, XT_CP3_SA + XCHAL_CP3_SA_SIZE) +#define XT_CP5_SA ALIGNUP(XCHAL_CP5_SA_ALIGN, XT_CP4_SA + XCHAL_CP4_SA_SIZE) +#define XT_CP6_SA ALIGNUP(XCHAL_CP6_SA_ALIGN, XT_CP5_SA + XCHAL_CP5_SA_SIZE) +#define XT_CP7_SA ALIGNUP(XCHAL_CP7_SA_ALIGN, XT_CP6_SA + XCHAL_CP6_SA_SIZE) +#define XT_CP_SA_SIZE ALIGNUP(16, XT_CP7_SA + XCHAL_CP7_SA_SIZE) + +/* Offsets within the overall save area: */ +#define XT_CPENABLE 0 /* (2 bytes) coprocessors active for this thread */ +#define XT_CPSTORED 2 /* (2 bytes) coprocessors saved for this thread */ +#define XT_CP_CS_ST 4 /* (2 bytes) coprocessor callee-saved regs stored for this thread */ +#define XT_CP_ASA 8 /* (4 bytes) ptr to aligned save area */ +/* Overall size allows for dynamic alignment: */ +#define XT_CP_SIZE (12 + XT_CP_SA_SIZE + XCHAL_TOTAL_SA_ALIGN) +#else +#define XT_CP_SIZE 0 +#endif + + +/* +------------------------------------------------------------------------------- + MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN + + Convenient where the frame size requirements are the same for both ABIs. + ENTRY(sz), RET(sz) are for framed functions (have locals or make calls). + ENTRY0, RET0 are for frameless functions (no locals, no calls). + + where size = size of stack frame in bytes (must be >0 and aligned to 16). + For framed functions the frame is created and the return address saved at + base of frame (Call0 ABI) or as determined by hardware (Windowed ABI). + For frameless functions, there is no frame and return address remains in a0. + Note: Because CPP macros expand to a single line, macros requiring multi-line + expansions are implemented as assembler macros. +------------------------------------------------------------------------------- +*/ + +#ifdef __ASSEMBLER__ +#ifdef __XTENSA_CALL0_ABI__ + /* Call0 */ + #define ENTRY(sz) entry1 sz + .macro entry1 size=0x10 + addi sp, sp, -\size + s32i a0, sp, 0 + .endm + #define ENTRY0 + #define RET(sz) ret1 sz + .macro ret1 size=0x10 + l32i a0, sp, 0 + addi sp, sp, \size + ret + .endm + #define RET0 ret +#else + /* Windowed */ + #define ENTRY(sz) entry sp, sz + #define ENTRY0 entry sp, 0x10 + #define RET(sz) retw + #define RET0 retw +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XTENSA_CONTEXT_H */ diff --git a/cpu/esp8266/vendor/xtensa/xtensa_intr.c b/cpu/esp8266/vendor/xtensa/xtensa_intr.c new file mode 100644 index 0000000000..9ec600acda --- /dev/null +++ b/cpu/esp8266/vendor/xtensa/xtensa_intr.c @@ -0,0 +1,141 @@ +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + +/****************************************************************************** + Xtensa-specific interrupt and exception functions for RTOS ports. + Also see xtensa_intr_asm.S. +******************************************************************************/ + +#ifndef MODULE_ESP_SDK_INT_HANDLING /* not needed in SDK task handling version of RIOT */ + +#include + +#include + +#include "xtensa_api.h" + + +#if XCHAL_HAVE_EXCEPTIONS + +/* Handler table is in xtensa_intr_asm.S */ + +extern xt_exc_handler _xt_exception_table[XCHAL_EXCCAUSE_NUM]; + + +/* + Default handler for unhandled exceptions. +*/ +void xt_unhandled_exception(XtExcFrame *frame) +{ + exit(-1); +} + + +/* + This function registers a handler for the specified exception. + The function returns the address of the previous handler. + On error, it returns 0. +*/ +xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f) +{ + xt_exc_handler old; + + if( n < 0 || n >= XCHAL_EXCCAUSE_NUM ) + return 0; /* invalid exception number */ + + old = _xt_exception_table[n]; + + if (f) { + _xt_exception_table[n] = f; + } + else { + _xt_exception_table[n] = &xt_unhandled_exception; + } + + return ((old == &xt_unhandled_exception) ? 0 : old); +} + +#endif + +#if XCHAL_HAVE_INTERRUPTS + +/* Handler table is in xtensa_intr_asm.S */ + +typedef struct xt_handler_table_entry { + void * handler; + void * arg; +} xt_handler_table_entry; + +extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS]; + + +/* + Default handler for unhandled interrupts. +*/ +void xt_unhandled_interrupt(void * arg) +{ + exit(-1); +} + + +/* + This function registers a handler for the specified interrupt. The "arg" + parameter specifies the argument to be passed to the handler when it is + invoked. The function returns the address of the previous handler. + On error, it returns 0. +*/ +xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg) +{ + xt_handler_table_entry * entry; + xt_handler old; + + if( n < 0 || n >= XCHAL_NUM_INTERRUPTS ) + return 0; /* invalid interrupt number */ + if( Xthal_intlevel[n] > XCHAL_EXCM_LEVEL ) + return 0; /* priority level too high to safely handle in C */ + + #ifdef MODULE_ESP_SDK + /* for compatibility reasons with SDK, we use _xtos_interrupt_table */ + /* in reverse order */ + entry = _xt_interrupt_table + (XCHAL_NUM_INTERRUPTS - n); + #else + entry = _xt_interrupt_table + n; + #endif + old = entry->handler; + + if (f) { + entry->handler = f; + entry->arg = arg; + } + else { + entry->handler = &xt_unhandled_interrupt; + entry->arg = (void*)n; + } + + return ((old == &xt_unhandled_interrupt) ? 0 : old); +} + + +#endif /* XCHAL_HAVE_INTERRUPTS */ + +#endif /* MODULE_ESP_SDK_INT_HANDLING */ diff --git a/cpu/esp8266/vendor/xtensa/xtensa_intr_asm.S b/cpu/esp8266/vendor/xtensa/xtensa_intr_asm.S new file mode 100644 index 0000000000..ccae8f741a --- /dev/null +++ b/cpu/esp8266/vendor/xtensa/xtensa_intr_asm.S @@ -0,0 +1,187 @@ +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + +/****************************************************************************** + Xtensa interrupt handling data and assembly routines. + Also see xtensa_intr.c and xtensa_vectors.S. +******************************************************************************/ + +#ifndef MODULE_ESP_SDK_INT_HANDLING /* not needed in SDK version of RIOT */ + +#include +#include + +#include "xtensa_context.h" + +#if XCHAL_HAVE_INTERRUPTS + + .literal_position + +/* +------------------------------------------------------------------------------- + INTENABLE virtualization information. +------------------------------------------------------------------------------- +*/ + .data + .global _xt_intdata + .align 8 +_xt_intdata: + .global _xt_intenable + .type _xt_intenable,@object + .size _xt_intenable,4 + .global _xt_vpri_mask + .type _xt_vpri_mask,@object + .size _xt_vpri_mask,4 + +_xt_intenable: .word 0 /* Virtual INTENABLE */ +_xt_vpri_mask: .word 0xFFFFFFFF /* Virtual priority mask */ + + +/* +------------------------------------------------------------------------------- + Table of C-callable interrupt handlers for each interrupt. Note that not all + slots can be filled, because interrupts at level > EXCM_LEVEL will not be + dispatched to a C handler by default. +------------------------------------------------------------------------------- +*/ +/* + in SDK we use _xtos_interrupt_table_ which is provided as symbol + _xt_interrupt_table_ by ld script +*/ +#ifndef MODULE_ESP_SDK + .data + .global _xt_interrupt_table + .align 8 + +_xt_interrupt_table: + + .set i, 0 + .rept XCHAL_NUM_INTERRUPTS + .word xt_unhandled_interrupt /* handler address */ + .word i /* handler arg (default: intnum) */ + .set i, i+1 + .endr +#endif + +#endif /* XCHAL_HAVE_INTERRUPTS */ + + +#if XCHAL_HAVE_EXCEPTIONS + +/* +------------------------------------------------------------------------------- + Table of C-callable exception handlers for each exception. Note that not all + slots will be active, because some exceptions (e.g. coprocessor exceptions) + are always handled by the OS and cannot be hooked by user handlers. +------------------------------------------------------------------------------- +*/ + + .data + .global _xt_exception_table + .align 4 + +_xt_exception_table: + .rept XCHAL_EXCCAUSE_NUM + .word xt_unhandled_exception /* handler address */ + .endr + +#endif + + +/* +------------------------------------------------------------------------------- + unsigned int xt_ints_on ( unsigned int mask ) + + Enables a set of interrupts. Does not simply set INTENABLE directly, but + computes it as a function of the current virtual priority. + Can be called from interrupt handlers. +------------------------------------------------------------------------------- +*/ + + .text + .align 4 + .global xt_ints_on + .type xt_ints_on,@function + +xt_ints_on: + + ENTRY0 +#if XCHAL_HAVE_INTERRUPTS + movi a3, 0 + movi a4, _xt_intdata + xsr a3, INTENABLE /* Disables all interrupts */ + rsync + l32i a3, a4, 0 /* a3 = _xt_intenable */ + l32i a6, a4, 4 /* a6 = _xt_vpri_mask */ + or a5, a3, a2 /* a5 = _xt_intenable | mask */ + s32i a5, a4, 0 /* _xt_intenable |= mask */ + and a5, a5, a6 /* a5 = _xt_intenable & _xt_vpri_mask */ + wsr a5, INTENABLE /* Reenable interrupts */ + mov a2, a3 /* Previous mask */ +#else + movi a2, 0 /* Return zero */ +#endif + RET0 + + .size xt_ints_on, . - xt_ints_on + + +/* +------------------------------------------------------------------------------- + unsigned int xt_ints_off ( unsigned int mask ) + + Disables a set of interrupts. Does not simply set INTENABLE directly, + but computes it as a function of the current virtual priority. + Can be called from interrupt handlers. +------------------------------------------------------------------------------- +*/ + + .text + .align 4 + .global xt_ints_off + .type xt_ints_off,@function + +xt_ints_off: + + ENTRY0 +#if XCHAL_HAVE_INTERRUPTS + movi a3, 0 + movi a4, _xt_intdata + xsr a3, INTENABLE /* Disables all interrupts */ + rsync + l32i a3, a4, 0 /* a3 = _xt_intenable */ + l32i a6, a4, 4 /* a6 = _xt_vpri_mask */ + or a5, a3, a2 /* a5 = _xt_intenable | mask */ + xor a5, a5, a2 /* a5 = _xt_intenable & ~mask */ + s32i a5, a4, 0 /* _xt_intenable &= ~mask */ + and a5, a5, a6 /* a5 = _xt_intenable & _xt_vpri_mask */ + wsr a5, INTENABLE /* Reenable interrupts */ + mov a2, a3 /* Previous mask */ +#else + movi a2, 0 /* return zero */ +#endif + RET0 + + .size xt_ints_off, . - xt_ints_off + +#endif /* MODULE_ESP_SDK_INT_HANDLING */ diff --git a/cpu/esp8266/vendor/xtensa/xtensa_rtos.h b/cpu/esp8266/vendor/xtensa/xtensa_rtos.h new file mode 100644 index 0000000000..ecf0fc27c9 --- /dev/null +++ b/cpu/esp8266/vendor/xtensa/xtensa_rtos.h @@ -0,0 +1,247 @@ +/******************************************************************************* +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + + RTOS-SPECIFIC INFORMATION FOR XTENSA RTOS ASSEMBLER SOURCES + (FreeRTOS Port) + +This header is the primary glue between generic Xtensa RTOS support +sources and a specific RTOS port for Xtensa. It contains definitions +and macros for use primarily by Xtensa assembly coded source files. + +Macros in this header map callouts from generic Xtensa files to specific +RTOS functions. It may also be included in C source files. + +Xtensa RTOS ports support all RTOS-compatible configurations of the Xtensa +architecture, using the Xtensa hardware abstraction layer (HAL) to deal +with configuration specifics. + +Should be included by all Xtensa generic and RTOS port-specific sources. + +*******************************************************************************/ + +#ifndef XTENSA_RTOS_H +#define XTENSA_RTOS_H + +#ifdef __ASSEMBLER__ +#include +#else +#include +#endif + +#include +#include +#ifndef RIOT_VERSION +#include +#endif +#define XT_BOARD 1 + +/* +Include any RTOS specific definitions that are needed by this header. +*/ +#ifndef RIOT_VERSION +#include +#endif + +/* +Convert FreeRTOSConfig definitions to XTENSA definitions. +However these can still be overridden from the command line. +*/ + +#ifndef XT_SIMULATOR + #if configXT_SIMULATOR + #define XT_SIMULATOR 1 /* Simulator mode */ + #endif +#endif + +#ifndef XT_BOARD + #if configXT_BOARD + #define XT_BOARD 1 /* Board mode */ + #endif +#endif + +#ifndef XT_TIMER_INDEX + #if defined configXT_TIMER_INDEX + #define XT_TIMER_INDEX configXT_TIMER_INDEX /* Index of hardware timer to be used */ + #endif +#endif + +#ifndef XT_INTEXC_HOOKS + #if configXT_INTEXC_HOOKS + #define XT_INTEXC_HOOKS 1 /* Enables exception hooks */ + #endif +#endif + +#if (!XT_SIMULATOR) && (!XT_BOARD) + #error Either XT_SIMULATOR or XT_BOARD must be defined. +#endif + + +/* +Name of RTOS (for messages). +*/ +#define XT_RTOS_NAME RIOT-OS + +/* +Check some Xtensa configuration requirements and report error if not met. +Error messages can be customize to the RTOS port. +*/ + +#if !XCHAL_HAVE_XEA2 +#error "RIOT-OS/Xtensa requires XEA2 (exception architecture 2)." +#endif + + +/******************************************************************************* + +RTOS CALLOUT MACROS MAPPED TO RTOS PORT-SPECIFIC FUNCTIONS. + +Define callout macros used in generic Xtensa code to interact with the RTOS. +The macros are simply the function names for use in calls from assembler code. +Some of these functions may call back to generic functions in xtensa_context.h . + +*******************************************************************************/ + +/* +Inform RTOS of entry into an interrupt handler that will affect it. +Allows RTOS to manage switch to any system stack and count nesting level. +Called after minimal context has been saved, with interrupts disabled. +RTOS port can call0 _xt_context_save to save the rest of the context. +May only be called from assembly code by the 'call0' instruction. +*/ +// void XT_RTOS_INT_ENTER(void) +#define XT_RTOS_INT_ENTER _frxt_int_enter + +/* +Inform RTOS of completion of an interrupt handler, and give control to +RTOS to perform thread/task scheduling, switch back from any system stack +and restore the context, and return to the exit dispatcher saved in the +stack frame at XT_STK_EXIT. RTOS port can call0 _xt_context_restore +to save the context saved in XT_RTOS_INT_ENTER via _xt_context_save, +leaving only a minimal part of the context to be restored by the exit +dispatcher. This function does not return to the place it was called from. +May only be called from assembly code by the 'call0' instruction. +*/ +// void XT_RTOS_INT_EXIT(void) +#define XT_RTOS_INT_EXIT _frxt_int_exit + +/* +Inform RTOS of the occurrence of a tick timer interrupt. +If RTOS has no tick timer, leave XT_RTOS_TIMER_INT undefined. +May be coded in or called from C or assembly, per ABI conventions. +RTOS may optionally define XT_TICK_PER_SEC in its own way (eg. macro). +*/ +// void XT_RTOS_TIMER_INT(void) +#define XT_RTOS_TIMER_INT _frxt_timer_int +#ifndef RIOT_VERSION + #define XT_TICK_PER_SEC configTICK_RATE_HZ +#endif + +/* +Return in a15 the base address of the co-processor state save area for the +thread that triggered a co-processor exception, or 0 if no thread was running. +The state save area is structured as defined in xtensa_context.h and has size +XT_CP_SIZE. Co-processor instructions should only be used in thread code, never +in interrupt handlers or the RTOS kernel. May only be called from assembly code +and by the 'call0' instruction. A result of 0 indicates an unrecoverable error. +The implementation may use only a2-4, a15 (all other regs must be preserved). +*/ +// void* XT_RTOS_CP_STATE(void) +#define XT_RTOS_CP_STATE _frxt_task_coproc_state + + +/******************************************************************************* + +HOOKS TO DYNAMICALLY INSTALL INTERRUPT AND EXCEPTION HANDLERS PER LEVEL. + +This Xtensa RTOS port provides hooks for dynamically installing exception +and interrupt handlers to facilitate automated testing where each test +case can install its own handler for user exceptions and each interrupt +priority (level). This consists of an array of function pointers indexed +by interrupt priority, with index 0 being the user exception handler hook. +Each entry in the array is initially 0, and may be replaced by a function +pointer of type XT_INTEXC_HOOK. A handler may be uninstalled by installing 0. + +The handler for low and medium priority obeys ABI conventions so may be coded +in C. For the exception handler, the cause is the contents of the EXCCAUSE +reg, and the result is -1 if handled, else the cause (still needs handling). +For interrupt handlers, the cause is a mask of pending enabled interrupts at +that level, and the result is the same mask with the bits for the handled +interrupts cleared (those not cleared still need handling). This allows a test +case to either pre-handle or override the default handling for the exception +or interrupt level (see xtensa_vectors.S). + +High priority handlers (including NMI) must be coded in assembly, are always +called by 'call0' regardless of ABI, must preserve all registers except a0, +and must not use or modify the interrupted stack. The hook argument 'cause' +is not passed and the result is ignored, so as not to burden the caller with +saving and restoring a2 (it assumes only one interrupt per level - see the +discussion in high priority interrupts in xtensa_vectors.S). The handler +therefore should be coded to prototype 'void h(void)' even though it plugs +into an array of handlers of prototype 'unsigned h(unsigned)'. + +To enable interrupt/exception hooks, compile the RTOS with '-DXT_INTEXC_HOOKS'. + +*******************************************************************************/ + +#define XT_INTEXC_HOOK_NUM (1 + XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI) + +#ifndef __ASSEMBLER__ +typedef unsigned (*XT_INTEXC_HOOK)(unsigned cause); +extern volatile XT_INTEXC_HOOK _xt_intexc_hooks[XT_INTEXC_HOOK_NUM]; +#endif + + +/******************************************************************************* + +CONVENIENCE INCLUSIONS. + +Ensures RTOS specific files need only include this one Xtensa-generic header. +These headers are included last so they can use the RTOS definitions above. + +*******************************************************************************/ + +#include "xtensa_context.h" + +#ifdef XT_RTOS_TIMER_INT +#include "xtensa_timer.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/******************************************************************************* + +Xtensa Port Version. + +*******************************************************************************/ + +#define XTENSA_PORT_VERSION 1.5 +#define XTENSA_PORT_VERSION_STRING "1.5" + +#ifdef __cplusplus +} +#endif + +#endif /* XTENSA_RTOS_H */ diff --git a/cpu/esp8266/vendor/xtensa/xtensa_timer.h b/cpu/esp8266/vendor/xtensa/xtensa_timer.h new file mode 100644 index 0000000000..a477dc3375 --- /dev/null +++ b/cpu/esp8266/vendor/xtensa/xtensa_timer.h @@ -0,0 +1,170 @@ +/******************************************************************************* +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + + XTENSA INFORMATION FOR RTOS TICK TIMER AND CLOCK FREQUENCY + +This header contains definitions and macros for use primarily by Xtensa +RTOS assembly coded source files. It includes and uses the Xtensa hardware +abstraction layer (HAL) to deal with config specifics. It may also be +included in C source files. + +User may edit to modify timer selection and to specify clock frequency and +tick duration to match timer interrupt to the real-time tick duration. + +If the RTOS has no timer interrupt, then there is no tick timer and the +clock frequency is irrelevant, so all of these macros are left undefined +and the Xtensa core configuration need not have a timer. + +*******************************************************************************/ + +#ifndef XTENSA_TIMER_H +#define XTENSA_TIMER_H + +#ifdef __ASSEMBLER__ +#include +#endif + +#include +#include + +#ifndef RIOT_VERSION +#include "xtensa_rtos.h" /* in case this wasn't included directly */ +#include +#endif /* ifndef RIOT_VERSION */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* +Select timer to use for periodic tick, and determine its interrupt number +and priority. User may specify a timer by defining XT_TIMER_INDEX with -D, +in which case its validity is checked (it must exist in this core and must +not be on a high priority interrupt - an error will be reported in invalid). +Otherwise select the first low or medium priority interrupt timer available. +*/ +#if XCHAL_NUM_TIMERS == 0 + + #error "This Xtensa configuration is unsupported, it has no timers." + +#else + +#ifndef XT_TIMER_INDEX + #if XCHAL_TIMER3_INTERRUPT != XTHAL_TIMER_UNCONFIGURED + #if XCHAL_INT_LEVEL(XCHAL_TIMER3_INTERRUPT) <= XCHAL_EXCM_LEVEL + #undef XT_TIMER_INDEX + #define XT_TIMER_INDEX 3 + #endif + #endif + #if XCHAL_TIMER2_INTERRUPT != XTHAL_TIMER_UNCONFIGURED + #if XCHAL_INT_LEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL + #undef XT_TIMER_INDEX + #define XT_TIMER_INDEX 2 + #endif + #endif + #if XCHAL_TIMER1_INTERRUPT != XTHAL_TIMER_UNCONFIGURED + #if XCHAL_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL + #undef XT_TIMER_INDEX + #define XT_TIMER_INDEX 1 + #endif + #endif + #if XCHAL_TIMER0_INTERRUPT != XTHAL_TIMER_UNCONFIGURED + #if XCHAL_INT_LEVEL(XCHAL_TIMER0_INTERRUPT) <= XCHAL_EXCM_LEVEL + #undef XT_TIMER_INDEX + #define XT_TIMER_INDEX 0 + #endif + #endif +#endif +#ifndef XT_TIMER_INDEX + #error "There is no suitable timer in this Xtensa configuration." +#endif + +#define XT_CCOMPARE (CCOMPARE + XT_TIMER_INDEX) +#define XT_TIMER_INTNUM XCHAL_TIMER_INTERRUPT(XT_TIMER_INDEX) +#define XT_TIMER_INTPRI XCHAL_INT_LEVEL(XT_TIMER_INTNUM) +#define XT_TIMER_INTEN (1 << XT_TIMER_INTNUM) + +#if XT_TIMER_INTNUM == XTHAL_TIMER_UNCONFIGURED + #error "The timer selected by XT_TIMER_INDEX does not exist in this core." +#elif XT_TIMER_INTPRI > XCHAL_EXCM_LEVEL + #error "The timer interrupt cannot be high priority (use medium or low)." +#endif + +#endif /* XCHAL_NUM_TIMERS */ + +#ifndef RIOT_VERSION +/* +Set processor clock frequency, used to determine clock divisor for timer tick. +User should BE SURE TO ADJUST THIS for the Xtensa platform being used. +If using a supported board via the board-independent API defined in xtbsp.h, +this may be left undefined and frequency and tick divisor will be computed +and cached during run-time initialization. + +NOTE ON SIMULATOR: +Under the Xtensa instruction set simulator, the frequency can only be estimated +because it depends on the speed of the host and the version of the simulator. +Also because it runs much slower than hardware, it is not possible to achieve +real-time performance for most applications under the simulator. A frequency +too low does not allow enough time between timer interrupts, starving threads. +To obtain a more convenient but non-real-time tick duration on the simulator, +compile with xt-xcc option "-DXT_SIMULATOR". +Adjust this frequency to taste (it's not real-time anyway!). +*/ +#if defined(XT_SIMULATOR) && !defined(XT_CLOCK_FREQ) +#define XT_CLOCK_FREQ configCPU_CLOCK_HZ +#endif + +#if !defined(XT_CLOCK_FREQ) && !defined(XT_BOARD) + #error "XT_CLOCK_FREQ must be defined for the target platform." +#endif + +/* +Default number of timer "ticks" per second (default 100 for 10ms tick). +RTOS may define this in its own way (if applicable) in xtensa_rtos.h. +User may redefine this to an optimal value for the application, either by +editing this here or in xtensa_rtos.h, or compiling with xt-xcc option +"-DXT_TICK_PER_SEC=" where is a suitable number. +*/ + +#ifndef XT_TICK_PER_SEC +#define XT_TICK_PER_SEC configTICK_RATE_HZ /* 10 ms tick = 100 ticks per second */ +#endif + +/* +Derivation of clock divisor for timer tick and interrupt (one per tick). +*/ +#ifdef XT_CLOCK_FREQ +#define XT_TICK_DIVISOR (XT_CLOCK_FREQ / XT_TICK_PER_SEC) +#endif +#endif /* ifndef RIOT_VERSION */ + +#ifndef __ASSEMBLER__ +extern unsigned _xt_tick_divisor; +extern void _xt_tick_divisor_init(void); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* XTENSA_TIMER_H */ diff --git a/cpu/esp8266/vendor/xtensa/xtensa_vectors.S b/cpu/esp8266/vendor/xtensa/xtensa_vectors.S new file mode 100644 index 0000000000..e620f5facc --- /dev/null +++ b/cpu/esp8266/vendor/xtensa/xtensa_vectors.S @@ -0,0 +1,1924 @@ +/******************************************************************************* +Copyright (c) 2006-2015 Cadence Design Systems Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- + + XTENSA VECTORS AND LOW LEVEL HANDLERS FOR AN RTOS + + Xtensa low level exception and interrupt vectors and handlers for an RTOS. + + Interrupt handlers and user exception handlers support interaction with + the RTOS by calling XT_RTOS_INT_ENTER and XT_RTOS_INT_EXIT before and + after user's specific interrupt handlers. These macros are defined in + xtensa_.h to call suitable functions in a specific RTOS. + + Users can install application-specific interrupt handlers for low and + medium level interrupts, by calling xt_set_interrupt_handler(). These + handlers can be written in C, and must obey C calling convention. The + handler table is indexed by the interrupt number. Each handler may be + provided with an argument. + + Note that the system timer interrupt is handled specially, and is + dispatched to the RTOS-specific handler. This timer cannot be hooked + by application code. + + Optional hooks are also provided to install a handler per level at + run-time, made available by compiling this source file with + '-DXT_INTEXC_HOOKS' (useful for automated testing). + +!! This file is a template that usually needs to be modified to handle !! +!! application specific interrupts. Search USER_EDIT for helpful comments !! +!! on where to insert handlers and how to write them. !! + + Users can also install application-specific exception handlers in the + same way, by calling xt_set_exception_handler(). One handler slot is + provided for each exception type. Note that some exceptions are handled + by the porting layer itself, and cannot be taken over by application + code in this manner. These are the alloca, syscall, and coprocessor + exceptions. + + The exception handlers can be written in C, and must follow C calling + convention. Each handler is passed a pointer to an exception frame as + its single argument. The exception frame is created on the stack, and + holds the saved context of the thread that took the exception. If the + handler returns, the context will be restored and the instruction that + caused the exception will be retried. If the handler makes any changes + to the saved state in the exception frame, the changes will be applied + when restoring the context. + + Because Xtensa is a configurable architecture, this port supports all user + generated configurations (except restrictions stated in the release notes). + This is accomplished by conditional compilation using macros and functions + defined in the Xtensa HAL (hardware adaptation layer) for your configuration. + Only the relevant parts of this file will be included in your RTOS build. + For example, this file provides interrupt vector templates for all types and + all priority levels, but only the ones in your configuration are built. + + NOTES on the use of 'call0' for long jumps instead of 'j': + 1. This file should be assembled with the -mlongcalls option to xt-xcc. + 2. The -mlongcalls compiler option causes 'call0 dest' to be expanded to + a sequence 'l32r a0, dest' 'callx0 a0' which works regardless of the + distance from the call to the destination. The linker then relaxes + it back to 'call0 dest' if it determines that dest is within range. + This allows more flexibility in locating code without the performance + overhead of the 'l32r' literal data load in cases where the destination + is in range of 'call0'. There is an additional benefit in that 'call0' + has a longer range than 'j' due to the target being word-aligned, so + the 'l32r' sequence is less likely needed. + 3. The use of 'call0' with -mlongcalls requires that register a0 not be + live at the time of the call, which is always the case for a function + call but needs to be ensured if 'call0' is used as a jump in lieu of 'j'. + 4. This use of 'call0' is independent of the C function call ABI. + +*******************************************************************************/ + +#include "xtensa_context.h" + +#ifndef MODULE_ESP_SDK_INT_HANDLING + +#include "xtensa_rtos.h" + +/* Enable stack backtrace across exception/interrupt - see below */ +#define XT_DEBUG_BACKTRACE 1 + + +/* +-------------------------------------------------------------------------------- + Defines used to access _xtos_interrupt_table. +-------------------------------------------------------------------------------- +*/ +#define XIE_HANDLER 0 +#define XIE_ARG 4 +#define XIE_SIZE 8 + +/* +-------------------------------------------------------------------------------- + Macro extract_msb - return the input with only the highest bit set. + + Input : "ain" - Input value, clobbered. + Output : "aout" - Output value, has only one bit set, MSB of "ain". + The two arguments must be different AR registers. +-------------------------------------------------------------------------------- +*/ + + .macro extract_msb aout ain +1: + addi \aout, \ain, -1 /* aout = ain - 1 */ + and \ain, \ain, \aout /* ain = ain & aout */ + bnez \ain, 1b /* repeat until ain == 0 */ + addi \aout, \aout, 1 /* return aout + 1 */ + .endm + +/* +-------------------------------------------------------------------------------- + Macro dispatch_c_isr - dispatch interrupts to user ISRs. + This will dispatch to user handlers (if any) that are registered in the + XTOS dispatch table (_xtos_interrupt_table). These handlers would have + been registered by calling _xtos_set_interrupt_handler(). There is one + exception - the timer interrupt used by the OS will not be dispatched + to a user handler - this must be handled by the caller of this macro. + + Level triggered and software interrupts are automatically deasserted by + this code. + + ASSUMPTIONS: + -- PS.INTLEVEL is set to "level" at entry + -- PS.EXCM = 0, C calling enabled + + NOTE: For CALL0 ABI, a12-a15 have not yet been saved. + + NOTE: This macro will use registers a0 and a2-a6. The arguments are: + level -- interrupt level + mask -- interrupt bitmask for this level +-------------------------------------------------------------------------------- +*/ + + .macro dispatch_c_isr level mask + + /* Get mask of pending, enabled interrupts at this level into a2. */ + +.L_xt_user_int_&level&: + rsr a2, INTENABLE + rsr a3, INTERRUPT + movi a4, \mask + and a2, a2, a3 + and a2, a2, a4 + beqz a2, 9f /* nothing to do */ + + /* This bit of code provides a nice debug backtrace in the debugger. + It does take a few more instructions, so undef XT_DEBUG_BACKTRACE + if you want to save the cycles. + */ + #if XT_DEBUG_BACKTRACE + #ifndef __XTENSA_CALL0_ABI__ + rsr a0, EPC_1 + \level - 1 /* return address */ + movi a4, 0xC0000000 /* constant with top 2 bits set (call size) */ + or a0, a0, a4 /* set top 2 bits */ + addx2 a0, a4, a0 /* clear top bit -- simulating call4 size */ + #endif + #endif + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a4, _xt_intexc_hooks + l32i a4, a4, \level << 2 + beqz a4, 2f + #ifdef __XTENSA_CALL0_ABI__ + callx0 a4 + beqz a2, 9f + #else + mov a6, a2 + callx4 a4 + beqz a6, 9f + mov a2, a6 + #endif +2: + #endif + + /* Now look up in the dispatch table and call user ISR if any. */ + /* If multiple bits are set then MSB has highest priority. */ + + extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */ + + #ifdef XT_USE_SWPRI + /* Enable all interrupts at this level that are numerically higher + than the one we just selected, since they are treated as higher + priority. + */ + movi a3, \mask /* a3 = all interrupts at this level */ + add a2, a4, a4 /* a2 = a4 << 1 */ + addi a2, a2, -1 /* a2 = mask of 1's <= a4 bit */ + and a2, a2, a3 /* a2 = mask of all bits <= a4 at this level */ + movi a3, _xt_intdata + l32i a6, a3, 4 /* a6 = _xt_vpri_mask */ + neg a2, a2 + addi a2, a2, -1 /* a2 = mask to apply */ + and a5, a6, a2 /* mask off all bits <= a4 bit */ + s32i a5, a3, 4 /* update _xt_vpri_mask */ + rsr a3, INTENABLE + and a3, a3, a2 /* mask off all bits <= a4 bit */ + wsr a3, INTENABLE + rsil a3, \level - 1 /* lower interrupt level by 1 */ + #endif + + movi a3, XT_TIMER_INTEN /* a3 = timer interrupt bit */ + wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */ + + #ifndef RIOT_VERSION /* we use it as hardware timer in RIOT OS */ + beq a3, a4, 7f /* if timer interrupt then skip table */ + #endif + + find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */ + +#if MODULE_ESP_SDK /* _xtos_interrupt_table is in reverse order */ + movi a4, XCHAL_NUM_INTERRUPTS /* intnum = XCHAL_NUM_INTERRUPTS - intnum */ + sub a3, a4, a3 +#endif + movi a4, _xt_interrupt_table + addx8 a3, a3, a4 /* a3 = address of interrupt table entry */ + l32i a4, a3, XIE_HANDLER /* a4 = handler address */ + #ifdef __XTENSA_CALL0_ABI__ + mov a12, a6 /* save in callee-saved reg */ + l32i a2, a3, XIE_ARG /* a2 = handler arg */ + callx0 a4 /* call handler */ + mov a2, a12 + #else + mov a2, a6 /* save in windowed reg */ + l32i a6, a3, XIE_ARG /* a6 = handler arg */ + callx4 a4 /* call handler */ + #endif + + #ifdef XT_USE_SWPRI + j 8f + #else + j .L_xt_user_int_&level& /* check for more interrupts */ + #endif + +7: + + .ifeq XT_TIMER_INTPRI - \level +.L_xt_user_int_timer_&level&: + /* + Interrupt handler for the RTOS tick timer if at this level. + We'll be reading the interrupt state again after this call + so no need to preserve any registers except a6 (vpri_mask). + */ + #ifdef __XTENSA_CALL0_ABI__ + mov a12, a6 + call0 XT_RTOS_TIMER_INT + mov a2, a12 + #else + mov a2, a6 + call4 XT_RTOS_TIMER_INT + #endif + .endif + + #ifdef XT_USE_SWPRI + j 8f + #else + j .L_xt_user_int_&level& /* check for more interrupts */ + #endif + + #ifdef XT_USE_SWPRI +8: + /* Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from + virtual _xt_intenable which _could_ have changed during interrupt + processing. */ + + movi a3, _xt_intdata + l32i a4, a3, 0 /* a4 = _xt_intenable */ + s32i a2, a3, 4 /* update _xt_vpri_mask */ + and a4, a4, a2 /* a4 = masked intenable */ + wsr a4, INTENABLE /* update INTENABLE */ + #endif + +9: + /* done */ + + .endm + + +/* +-------------------------------------------------------------------------------- + Panic handler. + Should be reached by call0 (preferable) or jump only. If call0, a0 says where + from. If on simulator, display panic message and abort, else loop indefinitely. +-------------------------------------------------------------------------------- +*/ + + .text + .global _xt_panic + .type _xt_panic,@function + .align 4 + +_xt_panic: + #ifdef XT_SIMULATOR + addi a4, a0, -3 /* point to call0 */ + movi a3, _xt_panic_message + movi a2, SYS_log_msg + simcall + movi a2, SYS_gdb_abort + simcall + #else + rsil a2, XCHAL_EXCM_LEVEL /* disable all low & med ints */ +1: j 1b /* loop infinitely */ + #endif + + .section .rodata, "a" + .align 4 + +_xt_panic_message: + .string "\n*** _xt_panic() was called from 0x%08x or jumped to. ***\n" + + +/* +-------------------------------------------------------------------------------- + Hooks to dynamically install handlers for exceptions and interrupts. + Allows automated regression frameworks to install handlers per test. + Consists of an array of function pointers indexed by interrupt level, + with index 0 containing the entry for user exceptions. + Initialized with all 0s, meaning no handler is installed at each level. + See comment in xtensa_rtos.h for more details. +-------------------------------------------------------------------------------- +*/ + + #ifdef XT_INTEXC_HOOKS + .data + .global _xt_intexc_hooks + .type _xt_intexc_hooks,@object + .align 4 + +_xt_intexc_hooks: + .fill XT_INTEXC_HOOK_NUM, 4, 0 + #endif + + +/* +-------------------------------------------------------------------------------- + EXCEPTION AND LEVEL 1 INTERRUPT VECTORS AND LOW LEVEL HANDLERS + (except window exception vectors). + + Each vector goes at a predetermined location according to the Xtensa + hardware configuration, which is ensured by its placement in a special + section known to the Xtensa linker support package (LSP). It performs + the minimum necessary before jumping to the handler in the .text section. + + The corresponding handler goes in the normal .text section. It sets up + the appropriate stack frame, saves a few vector-specific registers and + calls XT_RTOS_INT_ENTER to save the rest of the interrupted context + and enter the RTOS, then sets up a C environment. It then calls the + user's interrupt handler code (which may be coded in C) and finally + calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling. + + While XT_RTOS_INT_EXIT does not return directly to the interruptee, + eventually the RTOS scheduler will want to dispatch the interrupted + task or handler. The scheduler will return to the exit point that was + saved in the interrupt stack frame at XT_STK_EXIT. +-------------------------------------------------------------------------------- +*/ + + +/* +-------------------------------------------------------------------------------- +Debug Exception. +-------------------------------------------------------------------------------- +*/ + +#if XCHAL_HAVE_DEBUG + + .begin literal_prefix .DebugExceptionVector + .section .DebugExceptionVector.text, "ax" + .global _DebugExceptionVector + .literal_position + .align 4 + +_DebugExceptionVector: + + #ifdef XT_SIMULATOR + /* + In the simulator, let the debugger (if any) handle the debug exception, + or simply stop the simulation: + */ + wsr a2, EXCSAVE+XCHAL_DEBUGLEVEL /* save a2 where sim expects it */ + movi a2, SYS_gdb_enter_sktloop + simcall /* have ISS handle debug exc. */ + #elif 0 /* change condition to 1 to use the HAL minimal debug handler */ + wsr a3, EXCSAVE+XCHAL_DEBUGLEVEL + movi a3, xthal_debugexc_defhndlr_nw /* use default debug handler */ + jx a3 + #else + wsr a0, EXCSAVE+XCHAL_DEBUGLEVEL /* save original a0 somewhere */ + call0 _xt_panic /* does not return */ + rfi XCHAL_DEBUGLEVEL /* make a0 point here not later */ + #endif + + .end literal_prefix + +#endif + +/* +-------------------------------------------------------------------------------- +Double Exception. +Double exceptions are not a normal occurrence. They indicate a bug of some kind. +-------------------------------------------------------------------------------- +*/ + +#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR + + .begin literal_prefix .DoubleExceptionVector + .section .DoubleExceptionVector.text, "ax" + .literal_position + .global _DoubleExceptionVector + .align 4 + +_DoubleExceptionVector: + + #if XCHAL_HAVE_DEBUG + break 1, 4 /* unhandled double exception */ + #endif + call0 _xt_panic /* does not return */ + rfde /* make a0 point here not later */ + + .end literal_prefix + +#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */ + +/* +-------------------------------------------------------------------------------- +Kernel Exception (including Level 1 Interrupt from kernel mode). +-------------------------------------------------------------------------------- +*/ + + .begin literal_prefix .KernelExceptionVector + .section .KernelExceptionVector.text, "ax" + .literal_position + .global _KernelExceptionVector + .align 4 + +_KernelExceptionVector: + + wsr a0, EXCSAVE_1 /* preserve a0 */ + call0 _xt_kernel_exc /* kernel exception handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .literal_position + .align 4 + +_xt_kernel_exc: + #if XCHAL_HAVE_DEBUG + break 1, 0 /* unhandled kernel exception */ + #endif + call0 _xt_panic /* does not return */ + rfe /* make a0 point here not there */ + + +/* +-------------------------------------------------------------------------------- +User Exception (including Level 1 Interrupt from user mode). +-------------------------------------------------------------------------------- +*/ + + .begin literal_prefix .UserExceptionVector + .section .UserExceptionVector.text, "ax" + .literal_position + .global _UserExceptionVector + .type _UserExceptionVector,@function + .align 4 + +_UserExceptionVector: + + wsr a0, EXCSAVE_1 /* preserve a0 */ + call0 _xt_user_exc /* user exception handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + +/* +-------------------------------------------------------------------------------- + Insert some waypoints for jumping beyond the signed 8-bit range of + conditional branch instructions, so the conditional branchces to specific + exception handlers are not taken in the mainline. Saves some cycles in the + mainline. +-------------------------------------------------------------------------------- +*/ + + .text + + #if XCHAL_HAVE_WINDOWED + .align 4 +_xt_to_alloca_exc: + call0 _xt_alloca_exc /* in window vectors section */ + /* never returns here - call0 is used as a jump (see note at top) */ + #endif + + .align 4 +_xt_to_syscall_exc: + call0 _xt_syscall_exc + /* never returns here - call0 is used as a jump (see note at top) */ + + #if XCHAL_CP_NUM > 0 + .align 4 +_xt_to_coproc_exc: + call0 _xt_coproc_exc + /* never returns here - call0 is used as a jump (see note at top) */ + #endif + + +/* +-------------------------------------------------------------------------------- + User exception handler. +-------------------------------------------------------------------------------- +*/ + + .type _xt_user_exc,@function + .align 4 + +_xt_user_exc: + + /* If level 1 interrupt then jump to the dispatcher */ + rsr a0, EXCCAUSE + beqi a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_lowint1 + + /* Handle any coprocessor exceptions. Rely on the fact that exception + numbers above EXCCAUSE_CP0_DISABLED all relate to the coprocessors. + */ + #if XCHAL_CP_NUM > 0 + bgeui a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc + #endif + + /* Handle alloca and syscall exceptions */ + #if XCHAL_HAVE_WINDOWED + beqi a0, EXCCAUSE_ALLOCA, _xt_to_alloca_exc + #endif + beqi a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc + + /* Handle all other exceptions. All can have user-defined handlers. */ + /* NOTE: we'll stay on the user stack for exception handling. */ + + /* Allocate exception frame and save minimal context. */ + mov a0, sp + addi sp, sp, -XT_STK_FRMSZ + s32i a0, sp, XT_STK_A1 + #if XCHAL_HAVE_WINDOWED + s32e a0, sp, -12 /* for debug backtrace */ + #endif + rsr a0, PS /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_1 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_1 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + #if XCHAL_HAVE_WINDOWED + s32e a0, sp, -16 /* for debug backtrace */ + #endif + s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ + s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ + call0 _xt_context_save + + /* Save exc cause and vaddr into exception frame */ + rsr a0, EXCCAUSE + s32i a0, sp, XT_STK_EXCCAUSE + rsr a0, EXCVADDR + s32i a0, sp, XT_STK_EXCVADDR + + /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM + #else + movi a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE + #endif + wsr a0, PS + + #ifdef XT_DEBUG_BACKTRACE + #ifndef __XTENSA_CALL0_ABI__ + rsr a0, EPC_1 /* return address for debug backtrace */ + movi a5, 0xC0000000 /* constant with top 2 bits set (call size) */ + rsync /* wait for WSR.PS to complete */ + or a0, a0, a5 /* set top 2 bits */ + addx2 a0, a5, a0 /* clear top bit -- thus simulating call4 size */ + #else + rsync /* wait for WSR.PS to complete */ + #endif + #endif + + rsr a2, EXCCAUSE /* recover exc cause */ + + #ifdef XT_INTEXC_HOOKS + /* + Call exception hook to pre-handle exceptions (if installed). + Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling). + */ + movi a4, _xt_intexc_hooks + l32i a4, a4, 0 /* user exception hook index 0 */ + beqz a4, 1f +.Ln_xt_user_exc_call_hook: + #ifdef __XTENSA_CALL0_ABI__ + callx0 a4 + beqi a2, -1, .L_xt_user_done + #else + mov a6, a2 + callx4 a4 + beqi a6, -1, .L_xt_user_done + mov a2, a6 + #endif +1: + #endif + + rsr a2, EXCCAUSE /* recover exc cause */ + movi a3, _xt_exception_table + addx4 a4, a2, a3 /* a4 = address of exception table entry */ + l32i a4, a4, 0 /* a4 = handler address */ + #ifdef __XTENSA_CALL0_ABI__ + mov a2, sp /* a2 = pointer to exc frame */ + callx0 a4 /* call handler */ + #else + mov a6, sp /* a6 = pointer to exc frame */ + callx4 a4 /* call handler */ + #endif + +.L_xt_user_done: + + /* Restore context and return */ + call0 _xt_context_restore + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, PS + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_1 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove exception frame */ + rsync /* ensure PS and EPC written */ + rfe /* PS.EXCM is cleared */ + +#else + + .text + +#endif /* MODULE_ESP_SDK_INT_HANDLING */ + +/* +-------------------------------------------------------------------------------- + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. +-------------------------------------------------------------------------------- +*/ + + .global _xt_user_exit + .type _xt_user_exit,@function + .align 4 +_xt_user_exit: + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, PS + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_1 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure PS and EPC written */ + rfe /* PS.EXCM is cleared */ + +#ifndef MODULE_ESP_SDK_INT_HANDLING +/* +-------------------------------------------------------------------------------- +Syscall Exception Handler (jumped to from User Exception Handler). +Syscall 0 is required to spill the register windows (no-op in Call 0 ABI). +Only syscall 0 is handled here. Other syscalls return -1 to caller in a2. +-------------------------------------------------------------------------------- +*/ + + .text + .type _xt_syscall_exc,@function + .align 4 +_xt_syscall_exc: + + #ifdef __XTENSA_CALL0_ABI__ + /* + Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI. + Use a minimal stack frame (16B) to save A2 & A3 for scratch. + PS.EXCM could be cleared here, but unlikely to improve worst-case latency. + rsr a0, PS + addi a0, a0, -PS_EXCM_MASK + wsr a0, PS + */ + addi sp, sp, -16 + s32i a2, sp, 8 + s32i a3, sp, 12 + #else /* Windowed ABI */ + /* + Save necessary context and spill the register windows. + PS.EXCM is still set and must remain set until after the spill. + Reuse context save function though it saves more than necessary. + For this reason, a full interrupt stack frame is allocated. + */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a12, sp, XT_STK_A12 /* _xt_context_save requires A12- */ + s32i a13, sp, XT_STK_A13 /* A13 to have already been saved */ + call0 _xt_context_save + #endif + + /* + Grab the interruptee's PC and skip over the 'syscall' instruction. + If it's at the end of a zero-overhead loop and it's not on the last + iteration, decrement loop counter and skip to beginning of loop. + */ + rsr a2, EPC_1 /* a2 = PC of 'syscall' */ + addi a3, a2, 3 /* ++PC */ + #if XCHAL_HAVE_LOOPS + rsr a0, LEND /* if (PC == LEND */ + bne a3, a0, 1f + rsr a0, LCOUNT /* && LCOUNT != 0) */ + beqz a0, 1f /* { */ + addi a0, a0, -1 /* --LCOUNT */ + rsr a3, LBEG /* PC = LBEG */ + wsr a0, LCOUNT /* } */ + #endif +1: wsr a3, EPC_1 /* update PC */ + + /* Restore interruptee's context and return from exception. */ + #ifdef __XTENSA_CALL0_ABI__ + l32i a2, sp, 8 + l32i a3, sp, 12 + addi sp, sp, 16 + #else + call0 _xt_context_restore + addi sp, sp, XT_STK_FRMSZ + #endif + movi a0, -1 + movnez a2, a0, a2 /* return -1 if not syscall 0 */ + rsr a0, EXCSAVE_1 + rfe + +/* +-------------------------------------------------------------------------------- +Co-Processor Exception Handler (jumped to from User Exception Handler). +These exceptions are generated by co-processor instructions, which are only +allowed in thread code (not in interrupts or kernel code). This restriction is +deliberately imposed to reduce the burden of state-save/restore in interrupts. +-------------------------------------------------------------------------------- +*/ +#if XCHAL_CP_NUM > 0 + + .section .rodata, "a" + +/* Offset to CP n save area in thread's CP save area. */ + .global _xt_coproc_sa_offset + .type _xt_coproc_sa_offset,@object + .align 16 /* minimize crossing cache boundaries */ +_xt_coproc_sa_offset: + .word XT_CP0_SA, XT_CP1_SA, XT_CP2_SA, XT_CP3_SA + .word XT_CP4_SA, XT_CP5_SA, XT_CP6_SA, XT_CP7_SA + +/* Bitmask for CP n's CPENABLE bit. */ + .type _xt_coproc_mask,@object + .align 16,,8 /* try to keep it all in one cache line */ + .set i, 0 +_xt_coproc_mask: + .rept XCHAL_CP_MAX + .long (i<<16) | (1<= 2 + + .begin literal_prefix .Level2InterruptVector + .section .Level2InterruptVector.text, "ax" + .global _Level2Vector + .type _Level2Vector,@function + .align 4 +_Level2Vector: + wsr a0, EXCSAVE_2 /* preserve a0 */ + call0 _xt_medint2 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_medint2,@function + .align 4 +_xt_medint2: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_2 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_2 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_2 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint2_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(2) | PS_UM + #else + movi a0, PS_INTLEVEL(2) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint2_exit + .type _xt_medint2_exit,@function + .align 4 +_xt_medint2_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_2 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_2 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 2 + +#endif /* Level 2 */ + +#if XCHAL_EXCM_LEVEL >= 3 + + .begin literal_prefix .Level3InterruptVector + .section .Level3InterruptVector.text, "ax" + .global _Level3Vector + .type _Level3Vector,@function + .align 4 +_Level3Vector: + wsr a0, EXCSAVE_3 /* preserve a0 */ + call0 _xt_medint3 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_medint3,@function + .align 4 +_xt_medint3: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_3 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_3 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_3 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint3_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(3) | PS_UM + #else + movi a0, PS_INTLEVEL(3) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint3_exit + .type _xt_medint3_exit,@function + .align 4 +_xt_medint3_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_3 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_3 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 3 + +#endif /* Level 3 */ + +#if XCHAL_EXCM_LEVEL >= 4 + + .begin literal_prefix .Level4InterruptVector + .section .Level4InterruptVector.text, "ax" + .global _Level4Vector + .type _Level4Vector,@function + .align 4 +_Level4Vector: + wsr a0, EXCSAVE_4 /* preserve a0 */ + call0 _xt_medint4 /* load interrupt handler */ + + .end literal_prefix + + .text + .type _xt_medint4,@function + .align 4 +_xt_medint4: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_4 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_4 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_4 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint4_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(4) | PS_UM + #else + movi a0, PS_INTLEVEL(4) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint4_exit + .type _xt_medint4_exit,@function + .align 4 +_xt_medint4_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_4 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_4 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 4 + +#endif /* Level 4 */ + +#if XCHAL_EXCM_LEVEL >= 5 + + .begin literal_prefix .Level5InterruptVector + .section .Level5InterruptVector.text, "ax" + .global _Level5Vector + .type _Level5Vector,@function + .align 4 +_Level5Vector: + wsr a0, EXCSAVE_5 /* preserve a0 */ + call0 _xt_medint5 /* load interrupt handler */ + + .end literal_prefix + + .text + .type _xt_medint5,@function + .align 4 +_xt_medint5: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_5 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_5 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_5 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint5_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(5) | PS_UM + #else + movi a0, PS_INTLEVEL(5) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint5_exit + .type _xt_medint5_exit,@function + .align 4 +_xt_medint5_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_5 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_5 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 5 + +#endif /* Level 5 */ + +#if XCHAL_EXCM_LEVEL >= 6 + + .begin literal_prefix .Level6InterruptVector + .section .Level6InterruptVector.text, "ax" + .global _Level6Vector + .type _Level6Vector,@function + .align 4 +_Level6Vector: + wsr a0, EXCSAVE_6 /* preserve a0 */ + call0 _xt_medint6 /* load interrupt handler */ + + .end literal_prefix + + .text + .type _xt_medint6,@function + .align 4 +_xt_medint6: + mov a0, sp /* sp == a1 */ + addi sp, sp, -XT_STK_FRMSZ /* allocate interrupt stack frame */ + s32i a0, sp, XT_STK_A1 /* save pre-interrupt SP */ + rsr a0, EPS_6 /* save interruptee's PS */ + s32i a0, sp, XT_STK_PS + rsr a0, EPC_6 /* save interruptee's PC */ + s32i a0, sp, XT_STK_PC + rsr a0, EXCSAVE_6 /* save interruptee's a0 */ + s32i a0, sp, XT_STK_A0 + movi a0, _xt_medint6_exit /* save exit point for dispatch */ + s32i a0, sp, XT_STK_EXIT + + /* Save rest of interrupt context and enter RTOS. */ + call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */ + + /* !! We are now on the RTOS system stack !! */ + + /* Set up PS for C, enable interrupts above this level and clear EXCM. */ + #ifdef __XTENSA_CALL0_ABI__ + movi a0, PS_INTLEVEL(6) | PS_UM + #else + movi a0, PS_INTLEVEL(6) | PS_UM | PS_WOE + #endif + wsr a0, PS + rsync + + /* OK to call C code at this point, dispatch user ISRs */ + + dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK + + /* Done handling interrupts, transfer control to OS */ + call0 XT_RTOS_INT_EXIT /* does not return directly here */ + + /* + Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT + on entry and used to return to a thread or interrupted interrupt handler. + */ + .global _xt_medint6_exit + .type _xt_medint6_exit,@function + .align 4 +_xt_medint6_exit: + /* Restore only level-specific regs (the rest were already restored) */ + l32i a0, sp, XT_STK_PS /* retrieve interruptee's PS */ + wsr a0, EPS_6 + l32i a0, sp, XT_STK_PC /* retrieve interruptee's PC */ + wsr a0, EPC_6 + l32i a0, sp, XT_STK_A0 /* retrieve interruptee's A0 */ + l32i sp, sp, XT_STK_A1 /* remove interrupt stack frame */ + rsync /* ensure EPS and EPC written */ + rfi 6 + +#endif /* Level 6 */ + + +/******************************************************************************* + +HIGH PRIORITY (LEVEL > XCHAL_EXCM_LEVEL) INTERRUPT VECTORS AND HANDLERS + +High priority interrupts are by definition those with priorities greater +than XCHAL_EXCM_LEVEL. This includes non-maskable (NMI). High priority +interrupts cannot interact with the RTOS, that is they must save all regs +they use and not call any RTOS function. + +A further restriction imposed by the Xtensa windowed architecture is that +high priority interrupts must not modify the stack area even logically +"above" the top of the interrupted stack (they need to provide their +own stack or static save area). + +Cadence Design Systems recommends high priority interrupt handlers be coded in assembly +and used for purposes requiring very short service times. + +Here are templates for high priority (level 2+) interrupt vectors. +They assume only one interrupt per level to avoid the burden of identifying +which interrupts at this level are pending and enabled. This allows for +minimum latency and avoids having to save/restore a2 in addition to a0. +If more than one interrupt per high priority level is configured, this burden +is on the handler which in any case must provide a way to save and restore +registers it uses without touching the interrupted stack. + +Each vector goes at a predetermined location according to the Xtensa +hardware configuration, which is ensured by its placement in a special +section known to the Xtensa linker support package (LSP). It performs +the minimum necessary before jumping to the handler in the .text section. + +*******************************************************************************/ + +/* +Currently only shells for high priority interrupt handlers are provided +here. However a template and example can be found in the Cadence Design Systems tools +documentation: "Microprocessor Programmer's Guide". +*/ + +#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2 + + .begin literal_prefix .Level2InterruptVector + .section .Level2InterruptVector.text, "ax" + .global _Level2Vector + .type _Level2Vector,@function + .align 4 +_Level2Vector: + wsr a0, EXCSAVE_2 /* preserve a0 */ + call0 _xt_highint2 /* load interrupt handler */ + + .end literal_prefix + + .text + .type _xt_highint2,@function + .align 4 +_xt_highint2: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 2<<2 + beqz a0, 1f +.Ln_xt_highint2_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 2 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint2_exit: + rsr a0, EXCSAVE_2 /* restore a0 */ + rfi 2 + +#endif /* Level 2 */ + +#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3 + + .begin literal_prefix .Level3InterruptVector + .section .Level3InterruptVector.text, "ax" + .global _Level3Vector + .type _Level3Vector,@function + .align 4 +_Level3Vector: + wsr a0, EXCSAVE_3 /* preserve a0 */ + call0 _xt_highint3 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_highint3,@function + .align 4 +_xt_highint3: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 3<<2 + beqz a0, 1f +.Ln_xt_highint3_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 3 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint3_exit: + rsr a0, EXCSAVE_3 /* restore a0 */ + rfi 3 + +#endif /* Level 3 */ + +#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4 + + .begin literal_prefix .Level4InterruptVector + .section .Level4InterruptVector.text, "ax" + .global _Level4Vector + .type _Level4Vector,@function + .align 4 +_Level4Vector: + wsr a0, EXCSAVE_4 /* preserve a0 */ + call0 _xt_highint4 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_highint4,@function + .align 4 +_xt_highint4: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 4<<2 + beqz a0, 1f +.Ln_xt_highint4_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 4 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint4_exit: + rsr a0, EXCSAVE_4 /* restore a0 */ + rfi 4 + +#endif /* Level 4 */ + +#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5 + + .begin literal_prefix .Level5InterruptVector + .section .Level5InterruptVector.text, "ax" + .global _Level5Vector + .type _Level5Vector,@function + .align 4 +_Level5Vector: + wsr a0, EXCSAVE_5 /* preserve a0 */ + call0 _xt_highint5 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_highint5,@function + .align 4 +_xt_highint5: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 5<<2 + beqz a0, 1f +.Ln_xt_highint5_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 5 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint5_exit: + rsr a0, EXCSAVE_5 /* restore a0 */ + rfi 5 + +#endif /* Level 5 */ + +#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6 + + .begin literal_prefix .Level6InterruptVector + .section .Level6InterruptVector.text, "ax" + .global _Level6Vector + .type _Level6Vector,@function + .align 4 +_Level6Vector: + wsr a0, EXCSAVE_6 /* preserve a0 */ + call0 _xt_highint6 /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_highint6,@function + .align 4 +_xt_highint6: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, 6<<2 + beqz a0, 1f +.Ln_xt_highint6_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY LEVEL 6 INTERRUPT HANDLER CODE HERE. + */ + + .align 4 +.L_xt_highint6_exit: + rsr a0, EXCSAVE_6 /* restore a0 */ + rfi 6 + +#endif /* Level 6 */ + +#if XCHAL_HAVE_NMI + + .begin literal_prefix .NMIExceptionVector + .section .NMIExceptionVector.text, "ax" + .literal_position + .global _NMIExceptionVector + .type _NMIExceptionVector,@function + .align 4 +_NMIExceptionVector: + wsr a0, EXCSAVE + XCHAL_NMILEVEL _ /* preserve a0 */ + call0 _xt_nmi /* load interrupt handler */ + /* never returns here - call0 is used as a jump (see note at top) */ + + .end literal_prefix + + .text + .type _xt_nmi,@function + .align 4 +_xt_nmi: + + #ifdef XT_INTEXC_HOOKS + /* Call interrupt hook if present to (pre)handle interrupts. */ + movi a0, _xt_intexc_hooks + l32i a0, a0, XCHAL_NMILEVEL<<2 + beqz a0, 1f +.Ln_xt_nmi_call_hook: + callx0 a0 /* must NOT disturb stack! */ +1: + #endif + + /* USER_EDIT: + ADD HIGH PRIORITY NON-MASKABLE INTERRUPT (NMI) HANDLER CODE HERE. + */ + + .align 4 +.L_xt_nmi_exit: + rsr a0, EXCSAVE + XCHAL_NMILEVEL /* restore a0 */ + rfi XCHAL_NMILEVEL + +#endif /* NMI */ + + +/******************************************************************************* + +WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION HANDLER + +Here is the code for each window overflow/underflow exception vector and +(interspersed) efficient code for handling the alloca exception cause. +Window exceptions are handled entirely in the vector area and are very +tight for performance. The alloca exception is also handled entirely in +the window vector area so comes at essentially no cost in code size. +Users should never need to modify them and Cadence Design Systems recommends +they do not. + +Window handlers go at predetermined vector locations according to the +Xtensa hardware configuration, which is ensured by their placement in a +special section known to the Xtensa linker support package (LSP). Since +their offsets in that section are always the same, the LSPs do not define +a section per vector. + +These things are coded for XEA2 only (XEA1 is not supported). + +Note on Underflow Handlers: +The underflow handler for returning from call[i+1] to call[i] +must preserve all the registers from call[i+1]'s window. +In particular, a0 and a1 must be preserved because the RETW instruction +will be reexecuted (and may even underflow if an intervening exception +has flushed call[i]'s registers). +Registers a2 and up may contain return values. + +*******************************************************************************/ + +#if XCHAL_HAVE_WINDOWED + + .section .WindowVectors.text, "ax" + +/* +-------------------------------------------------------------------------------- +Window Overflow Exception for Call4. + +Invoked if a call[i] referenced a register (a4-a15) +that contains data from ancestor call[j]; +call[j] had done a call4 to call[j+1]. +On entry here: + window rotated to call[j] start point; + a0-a3 are registers to be saved; + a4-a15 must be preserved; + a5 is call[j+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x0 + .global _WindowOverflow4 +_WindowOverflow4: + + s32e a0, a5, -16 /* save a0 to call[j+1]'s stack frame */ + s32e a1, a5, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a5, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a5, -4 /* save a3 to call[j+1]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* +-------------------------------------------------------------------------------- +Window Underflow Exception for Call4 + +Invoked by RETW returning from call[i+1] to call[i] +where call[i]'s registers must be reloaded (not live in ARs); +where call[i] had done a call4 to call[i+1]. +On entry here: + window rotated to call[i] start point; + a0-a3 are undefined, must be reloaded with call[i].reg[0..3]; + a4-a15 must be preserved (they are call[i+1].reg[0..11]); + a5 is call[i+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x40 + .global _WindowUnderflow4 +_WindowUnderflow4: + + l32e a0, a5, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a5, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a5, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a3, a5, -4 /* restore a3 from call[i+1]'s stack frame */ + rfwu + +/* +-------------------------------------------------------------------------------- +Handle alloca exception generated by interruptee executing 'movsp'. +This uses space between the window vectors, so is essentially "free". +All interruptee's regs are intact except a0 which is saved in EXCSAVE_1, +and PS.EXCM has been set by the exception hardware (can't be interrupted). +The fact the alloca exception was taken means the registers associated with +the base-save area have been spilled and will be restored by the underflow +handler, so those 4 registers are available for scratch. +The code is optimized to avoid unaligned branches and minimize cache misses. +-------------------------------------------------------------------------------- +*/ + + .align 4 + .global _xt_alloca_exc +_xt_alloca_exc: + + rsr a0, WINDOWBASE /* grab WINDOWBASE before rotw changes it */ + rotw -1 /* WINDOWBASE goes to a4, new a0-a3 are scratch */ + rsr a2, PS + extui a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS + xor a3, a3, a4 /* bits changed from old to current windowbase */ + rsr a4, EXCSAVE_1 /* restore original a0 (now in a4) */ + slli a3, a3, XCHAL_PS_OWB_SHIFT + xor a2, a2, a3 /* flip changed bits in old window base */ + wsr a2, PS /* update PS.OWB to new window base */ + rsync + + _bbci.l a4, 31, _WindowUnderflow4 + rotw -1 /* original a0 goes to a8 */ + _bbci.l a8, 30, _WindowUnderflow8 + rotw -1 + j _WindowUnderflow12 + +/* +-------------------------------------------------------------------------------- +Window Overflow Exception for Call8 + +Invoked if a call[i] referenced a register (a4-a15) +that contains data from ancestor call[j]; +call[j] had done a call8 to call[j+1]. +On entry here: + window rotated to call[j] start point; + a0-a7 are registers to be saved; + a8-a15 must be preserved; + a9 is call[j+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x80 + .global _WindowOverflow8 +_WindowOverflow8: + + s32e a0, a9, -16 /* save a0 to call[j+1]'s stack frame */ + l32e a0, a1, -12 /* a0 <- call[j-1]'s sp + (used to find end of call[j]'s frame) */ + s32e a1, a9, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a9, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a9, -4 /* save a3 to call[j+1]'s stack frame */ + s32e a4, a0, -32 /* save a4 to call[j]'s stack frame */ + s32e a5, a0, -28 /* save a5 to call[j]'s stack frame */ + s32e a6, a0, -24 /* save a6 to call[j]'s stack frame */ + s32e a7, a0, -20 /* save a7 to call[j]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* +-------------------------------------------------------------------------------- +Window Underflow Exception for Call8 + +Invoked by RETW returning from call[i+1] to call[i] +where call[i]'s registers must be reloaded (not live in ARs); +where call[i] had done a call8 to call[i+1]. +On entry here: + window rotated to call[i] start point; + a0-a7 are undefined, must be reloaded with call[i].reg[0..7]; + a8-a15 must be preserved (they are call[i+1].reg[0..7]); + a9 is call[i+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0xC0 + .global _WindowUnderflow8 +_WindowUnderflow8: + + l32e a0, a9, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a9, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a9, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a7, a1, -12 /* a7 <- call[i-1]'s sp + (used to find end of call[i]'s frame) */ + l32e a3, a9, -4 /* restore a3 from call[i+1]'s stack frame */ + l32e a4, a7, -32 /* restore a4 from call[i]'s stack frame */ + l32e a5, a7, -28 /* restore a5 from call[i]'s stack frame */ + l32e a6, a7, -24 /* restore a6 from call[i]'s stack frame */ + l32e a7, a7, -20 /* restore a7 from call[i]'s stack frame */ + rfwu + +/* +-------------------------------------------------------------------------------- +Window Overflow Exception for Call12 + +Invoked if a call[i] referenced a register (a4-a15) +that contains data from ancestor call[j]; +call[j] had done a call12 to call[j+1]. +On entry here: + window rotated to call[j] start point; + a0-a11 are registers to be saved; + a12-a15 must be preserved; + a13 is call[j+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x100 + .global _WindowOverflow12 +_WindowOverflow12: + + s32e a0, a13, -16 /* save a0 to call[j+1]'s stack frame */ + l32e a0, a1, -12 /* a0 <- call[j-1]'s sp + (used to find end of call[j]'s frame) */ + s32e a1, a13, -12 /* save a1 to call[j+1]'s stack frame */ + s32e a2, a13, -8 /* save a2 to call[j+1]'s stack frame */ + s32e a3, a13, -4 /* save a3 to call[j+1]'s stack frame */ + s32e a4, a0, -48 /* save a4 to end of call[j]'s stack frame */ + s32e a5, a0, -44 /* save a5 to end of call[j]'s stack frame */ + s32e a6, a0, -40 /* save a6 to end of call[j]'s stack frame */ + s32e a7, a0, -36 /* save a7 to end of call[j]'s stack frame */ + s32e a8, a0, -32 /* save a8 to end of call[j]'s stack frame */ + s32e a9, a0, -28 /* save a9 to end of call[j]'s stack frame */ + s32e a10, a0, -24 /* save a10 to end of call[j]'s stack frame */ + s32e a11, a0, -20 /* save a11 to end of call[j]'s stack frame */ + rfwo /* rotates back to call[i] position */ + +/* +-------------------------------------------------------------------------------- +Window Underflow Exception for Call12 + +Invoked by RETW returning from call[i+1] to call[i] +where call[i]'s registers must be reloaded (not live in ARs); +where call[i] had done a call12 to call[i+1]. +On entry here: + window rotated to call[i] start point; + a0-a11 are undefined, must be reloaded with call[i].reg[0..11]; + a12-a15 must be preserved (they are call[i+1].reg[0..3]); + a13 is call[i+1]'s stack pointer. +-------------------------------------------------------------------------------- +*/ + + .org 0x140 + .global _WindowUnderflow12 +_WindowUnderflow12: + + l32e a0, a13, -16 /* restore a0 from call[i+1]'s stack frame */ + l32e a1, a13, -12 /* restore a1 from call[i+1]'s stack frame */ + l32e a2, a13, -8 /* restore a2 from call[i+1]'s stack frame */ + l32e a11, a1, -12 /* a11 <- call[i-1]'s sp + (used to find end of call[i]'s frame) */ + l32e a3, a13, -4 /* restore a3 from call[i+1]'s stack frame */ + l32e a4, a11, -48 /* restore a4 from end of call[i]'s stack frame */ + l32e a5, a11, -44 /* restore a5 from end of call[i]'s stack frame */ + l32e a6, a11, -40 /* restore a6 from end of call[i]'s stack frame */ + l32e a7, a11, -36 /* restore a7 from end of call[i]'s stack frame */ + l32e a8, a11, -32 /* restore a8 from end of call[i]'s stack frame */ + l32e a9, a11, -28 /* restore a9 from end of call[i]'s stack frame */ + l32e a10, a11, -24 /* restore a10 from end of call[i]'s stack frame */ + l32e a11, a11, -20 /* restore a11 from end of call[i]'s stack frame */ + rfwu + +#endif /* XCHAL_HAVE_WINDOWED */ + +#endif /* MODULE_ESP_SDK_INT_HANDLING */ diff --git a/dist/tools/licenses/patterns/mit-espressif b/dist/tools/licenses/patterns/mit-espressif new file mode 100644 index 0000000000..ea93e1ac61 --- /dev/null +++ b/dist/tools/licenses/patterns/mit-espressif @@ -0,0 +1,16 @@ +Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, +it is free of charge, to any person obtaining a copy of this software and associated +documentation files \(the "Software"\), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + * +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software\. + * +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE\.