Merge branch master into feature/logging

* branch master: (51 commits)
  fix typos
  callback: add a void* pointer with each callback
  header: callbacks use "void *" as arguments
  header: format and fix typos
  add wifi api comments
  add wifi api comments
  components/spi_flash: call SPIUnlock only once
  components/spi_flash: improve comments and readability
  esp32 cpu_start: Include rom/uart.h, remove inline ROM function declarations
  bootloader: Add bootloader Kconfig
  Fix bug where nesting vTaskEnterCritical calls would not re-enable interrupts after vTaskExitCritical sections.
  installed gitlab key in global before_script, don't need to overwrite in template before_script
  ci: Use github repo for wifi libraries on master branch, gitlab repo otherwise
  components/esp32,spi_flash: update some comments
  components/esp32: remove dependency of WIFI_ENABLED on FREERTOS_UNICORE
  esp32/lib: Bump WiFi revision
  update ci: build ssc with idf submodule wifi lib
  components/esp32: add inter-processor call API and implement spi_flash through it
  add MACRO to get flash pad number from efuse value
  add comments to register read/write operations
  ...
This commit is contained in:
Ivan Grokhotkov 2016-09-14 12:19:43 +08:00
commit 2fc60ba938
71 changed files with 3836 additions and 3198 deletions

View File

@ -4,11 +4,25 @@ stages:
- deploy
before_script:
# add gitlab ssh key
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo -n $GITLAB_KEY >> ~/.ssh/id_rsa_base64
- base64 --decode --ignore-garbage ~/.ssh/id_rsa_base64 > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- echo -e "Host gitlab.espressif.cn\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
# if testing master branch, use github wifi libs.
# if testing other branches, use gitlab wifi libs (as maybe changes aren't merged to master yet)
- test "${CI_BUILD_REF_NAME}" = "master" || sed -i "s%https://github.com/espressif/esp32-wifi-lib%ssh://git@gitlab.espressif.cn:27227/idf/esp32-wifi-lib%" .gitmodules
# fetch all submodules
- git submodule update --init --recursive
build_template_app:
stage: build
image: espressif/esp32-ci-env
tags:
- build
variables:
SDK_PATH: "$CI_PROJECT_DIR"
@ -18,12 +32,47 @@ build_template_app:
script:
- git clone https://github.com/espressif/esp-idf-template.git
- cd esp-idf-template
# Try to use the same branch name for esp-idf-template that we're
# using on esp-idf. If it doesn't exist then just stick to the default
# branch
- git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..."
- make defconfig
- make all
.build_gitlab: &build_template
stage: build
tags:
- build
image: espressif/esp32-ci-env
variables:
SDK_PATH: "$CI_PROJECT_DIR"
IDF_PATH: "$CI_PROJECT_DIR"
GIT_STRATEGY: clone
build_ssc:
<<: *build_template
artifacts:
paths:
- ./SSC/build/*.bin
- ./SSC/build/*.elf
- ./SSC/build/*.map
- ./SSC/build/bootloader/*.bin
expire_in: 6 mos
script:
- git clone ssh://git@gitlab.espressif.cn:27227/yinling/SSC.git
- cd SSC
- make defconfig
- chmod +x gen_misc_ng.sh
- ./gen_misc_ng.sh
test_nvs_on_host:
stage: test
image: espressif/esp32-ci-env
tags:
- nvs_host_test
script:
- cd components/nvs_flash/test
- make test
@ -31,15 +80,58 @@ test_nvs_on_host:
test_build_system:
stage: test
image: espressif/esp32-ci-env
tags:
- build_test
variables:
IDF_PATH: "$CI_PROJECT_DIR"
script:
- ./make/test_build_system.sh
# template for test jobs
.test_template: &test_template
stage: test
when: on_success
only:
- master
variables:
# need user to set SDK_NAME and CONFIG_FILE (may need to set BIN_PATH and APP_NAME later) in before_script
SCRIPT_PATH: /home/gitlab-runner/auto_test_script
BIN_PATH: ${CI_PROJECT_DIR}/SSC/build/
APP_NAME: ssc
LOG_PATH: $CI_PROJECT_DIR/$CI_BUILD_REF
artifacts:
when: always
paths:
- $LOG_PATH
expire_in: 6 mos
script:
- cd $SCRIPT_PATH
- python CIRunner.py -l $LOG_PATH -c $SDK_NAME/$CONFIG_FILE bin_path $APP_NAME $BIN_PATH
sanity_test:
<<: *test_template
tags:
- ESP32
- SSC_T1_1
- SSC_T2_1
- SSC_T1_WAN
before_script:
- SDK_NAME=ESP32_IDF
- CONFIG_FILE=sanity_test.yml
push_master_to_github:
stage: deploy
only:
- master
tags:
- deploy
when: on_success
image: espressif/esp32-ci-env
variables:

3
.gitmodules vendored
View File

@ -1,3 +1,6 @@
[submodule "components/esp32/lib"]
path = components/esp32/lib
url = https://github.com/espressif/esp32-wifi-lib.git
[submodule "components/esptool_py/esptool"]
path = components/esptool_py/esptool
url = https://github.com/themadinventor/esptool.git

View File

@ -1,265 +0,0 @@
The build structure of the Espressif IoT Development Framework explained.
An ESP-IDF project can be seen as an almagation of a number of components.
For example, for a webserver that shows the current humidity, we would
have:
- The ESP32 base libraries (libc, rom bindings etc)
- The WiFi drivers
- A TCP/IP stack
- The FreeRTOS operating system
- A webserver
- A driver for an humidity sensor
- Main code tying it all together
ESP-IDF makes these components explicit and configurable. To do that, when a project
is compiled, the build environment will look up all the components in the
ESP-IDF directories, the project directories and optionally custom other component
directories. It then allows the user to configure compile-time options using
a friendly text-based menu system to customize the ESP-IDF as well as other components
to the requirements of the project. After the components are customized, the
build process will compile everything into an output file, which can then be uploaded
into a board in a way that can also be defined by components.
A project in this sense is defined as a directory under which all the files required
to build it live, excluding the ESP-IDF files and the toolchain. A simple project
tree looks like this:
- myProject/ - build/
- components/ - component1/ - Makefile
- Kconfig
- src1.c
- component2/ - Makefile
- Kconfig
- src1.c
- main/ - src1.c
- src2.c
- Makefile
As we can see, a project consists of a components/ subdirectory containing its
components as well as one or more directories containing the project-specific
sources; by default a single directory called 'main' is assumed. The project
directory will also have a Makefile where the projects name as well as optionally
other options are defined. After compilation, the project directory will contain
a 'build'-directory containing all of the objects, libraries and other generated
files as well as the final binary.
Components also have a Makefile containing various definititions influencing
the build process of the component as well as the project it's used in, as
well as a Kconfig file defining the compile-time options that are settable
by means of the menu system.
Project makefile variables that can be set by the programmer:
PROJECT_NAME: Mandatory. Name for the project
BUILD_DIR_BASE: Set the directory where all objects/libraries/binaries end up in.
Defaults to $(PROJECT_PATH)/build
COMPONENT_DIRS: Search path for components. Defaults to the component/ directories
in the ESP-IDF path and the project path.
COMPONENTS: A list of component names. Defaults to all the component found in the
COMPONENT_DIRS directory
EXTRA_COMPONENT_DIRS: Defaults to unset. Use this to add directories to the default
COMPONENT_DIRS.
SRCDIRS: Directories under the project dir containing project-specific sources.
Defaults to 'main'. These are treated as 'lite' components: they do not have
include directories that are passed to the compilation pass of all components and
they do not have a Kconfig option.
Component makefile variables that can be set by the programmer:
COMPONENT_ADD_INCLUDEDIRS: Relative path to include directories to be added to
the entire project
COMPONENT_PRIV_INCLUDEDIRS: Relative path to include directories that are only used
when compiling this specific component
COMPONENT_DEPENDS: Names of any components that need to be compiled before this component.
COMPONENT_ADD_LDFLAGS: Ld flags to add for this project. Defaults to -l$(COMPONENT_NAME).
Add libraries etc in the current directory as $(abspath libwhatever.a)
COMPONENT_EXTRA_INCLUDES: Any extra include paths. These will be prefixed with '-I' and
passed to the compiler; please put absolute paths here.
COMPONENT_SRCDIRS: Relative directories to look in for sources. Defaults to '.', the current
directory (the root of the component) only. Use this to specify any subdirectories. Note
that specifying this overwrites the default action of compiling everything in the
components root dir; to keep this behaviour please also add '.' as a directory in this
list.
COMPONENT_OBJS: Object files to compile. Defaults to the .o variants of all .c and .S files
that are found in COMPONENT_SRCDIRS.
COMPONENT_EXTRA_CLEAN: Files that are generated using rules in the components Makefile
that also need to be cleaned
COMPONENT_BUILDRECIPE: Recipe to build the component. Optional. Defaults to building all
COMPONENT_OBJS and linking them into lib(componentname).a
COMPONENT_CLEANRECIPE: Recipe to clean the component. Optional. Defaults to removing
all built objects and libraries.
COMPONENT_BUILD_DIR: Equals the cwd of the component build, which is the build dir
of the component (where all the .o etc files should be created).
These variables are already set early on in the Makefile and the values in it will
be usable in component or project Makefiles:
CC, LD, AR, OBJCOPY: Xtensa gcc tools
HOSTCC, HOSTLD etc: Host gcc tools
LDFLAGS, CFLAGS: Set to usable values as defined in ESP-IDF Makefile
PROJECT_NAME: Name of the project, as set in project makefile
PROJECT_PATH: Path to the root of the project folder
COMPONENTS: Name of the components to be included
CONFIG_*: Values set by 'make menuconfig' also have corresponding Makefile variables.
For components, there also are these defines:
COMPONENT_PATH: Absolute path to the root of the source tree of the component we're
compiling
COMPONENT_LIBRARY: The full path to the static library the components compilation pass
is supposed to generate
How this works:
The Make process is always invoked from the project directory by the
user; invoking it anywhere else gives an error. This is what happens if
we build a binary:
The Makefile first determines how it was included. It determines it was
included as a project file in this case and will continue to figure out
various paths as well as the components available to it. It will also
collect the ldflags and includes that the components specify they need.
It does this by running a dummy Make on the components with a target that
will output these values.
The Makefile will then create targets to build the lib*.a libraries of
all components and make the elf target depend on this. The targets
invoke Make on the makefiles of the components in a subshell: this way
the components have full freedom to do whatever is necessary to build
the library without influencing other components. By default, the
component includes the utility makefile $(IDF_PATH)/make/component.mk.
This provides default targets and configurations that will work
out-of-the-box for most projects.
For components that have parts that need to be run when building of the
project is done, you can create a file called Makefile.projbuild in the
component root directory. This file will be included in the main
Makefile. For the menu, there's an equivalent: if you want to include
options not in the 'components' submenu, create a Kconfig.projbuild and
it will be included in the main menu of menuconfig. Take good care when
(re)defining stuff here: because it's included with all the other
.projbuild files, it's possible to overwrite variables or re-declare
targets defined in the ESP-IDF makefile/Kconfig and other .projbuild files
WRITING COMPONENT MAKEFILES
A component consists of a directory which doubles as the name for the
component: a component named 'httpd' lives in a directory called 'httpd'
Because components usually live under the project directory (although
they can also reside in an other folder), the path to this may be
something like /home/myuser/projects/myprojects/components/httpd .
One of the things that most components will have is a Makefile,
containing instructions on how to build the component. Because the
build environment tries to set reasonable defaults that will work most
of the time, a component Makefile can be pretty small. At the absolute
minimum, it will just include the ESP-IDF component makefile, which adds
component functionality:
----8<----
include $(IDF_PATH)/make/component.mk
---->8----
This will take all the .c and .S files in the component root and compile
them into object files, finally linking them into a library.
Subdirectories are ignored; if your project has sources in subdirectories
instead of in the root of the component, you can tell that to the build
system by setting COMPONENT_SRCDIRS:
----8<----
COMPONENT_SRCDIRS := src1 src2
include $(IDF_PATH)/make/component.mk
---->8----
This will compile all source files in the src1/ and src2/ subdirectories
instead.
The standard component.mk logic adds all .S and .c files in the source
directories as sources to be compiled unconditionally. It is possible
to circumvent that logic and hardcode the objects to be compiled by
manually setting the COMPONENT_OBJS variable to the name of the
objects that need to be generated:
----8<----
COMPONENT_OBJS := file1.o file2.o thing/filea.o thing/fileb.o anotherthing/main.o
include $(IDF_PATH)/make/component.mk
---->8----
This can also be used in order to conditionally compile some files
dependent on the options selected in the Makefile:
Kconfig:
----8<----
config FOO_ENABLE_BAR
bool "Enable the BAR feature."
help
This enables the BAR feature of the FOO component.
---->8----
Makefile:
----8<----
COMPONENT_OBJS := foo_a.o foo_b.o $(if $(CONFIG_FOO_ENABLE_BAR),foo_bar.o foo_bar_interface.o)
include $(IDF_PATH)/make/component.mk
---->8----
Some components will have a situation where a source file isn't supplied
with the component itself but has to be generated from another file. Say
our component has a header file that consists of the converted binary
data of a BMP file, converted using a hypothetical tool called bmp2h. The
header file is then included in as C source file called graphics_lib.c.
----8<----
COMPONENT_EXTRA_CLEAN := logo.h
graphics_lib.o: logo.h
logo.h: $(COMPONENT_PATH)/logo.bmp
bmp2h -i $^ -o $@
include $(IDF_PATH)/make/component.mk
---->8----
In this example, graphics_lib.o and logo.h will be generated in the
current directory (the build directory) while logo.bmp comes with the
component and resides under the component path. Because logo.h is a
generated file, it needs to be cleaned when make clean is called which
why it is added to the COMPONENT_EXTRA_CLEAN variable.
This will work just fine, but there's one last cosmetic improvement that
can be done. The make system tries to make the make process somewhat
easier on the eyes by hiding the commands (unless you run make with the
V=1 switch) and this does not do that yet. Here's an improved version
that will output in the same style as the rest of the make process:
----8<----
COMPONENT_EXTRA_CLEAN := test_tjpgd_logo.h
graphics_lib.o: logo.h
logo.h: $(COMPONENT_PATH)/logo.bmp
$(summary) BMP2H $@
$(Q) bmp2h -i $^ -o $@
include $(IDF_PATH)/make/component.mk
---->8----
Obviously, there are cases where all these recipes are insufficient for a
certain component, for example when the component is basically a wrapper
around another third-party component not originally intended to be
compiled under this build system. In that case, it's possible to forego
the build system entirely by setting COMPONENT_OWNBUILDTARGET and
possibly COMPONENT_OWNCLEANTARGET and defining your own build- and clean
target. The build target can do anything as long as it creates
$(COMPONENT_LIBRARY) for the main file to link into the project binary,
and even that is not necessary: if the COMPONENT_ADD_LDFLAGS variable
is set, the component can instruct the linker to do anything else as well.

View File

@ -49,3 +49,11 @@ The simplest way to use the partition table is to `make menuconfig` and choose o
In both cases the factory app is flashed at offset 0x10000. If you `make partition_table` then it will print a summary of the partition table.
For more details about partition tables and how to create custom variations, view the `docs/partition_tables.rst` file.
# Resources
* The [docs directory of the esp-idf repository](https://github.com/espressif/esp-idf/tree/master/docs) contains esp-idf documentation.
* The [esp32.com forum](http://esp32.com/) is a place to ask questions and find community resources.
* [Check the Issues section on github](https://github.com/espressif/esp-idf/issues) if you find a bug or have a feature request. Please check existing Issues before opening a new one.

17
add_path.sh Normal file
View File

@ -0,0 +1,17 @@
# This shell snippet appends useful esp-idf tools to your PATH environment
# variable. This means you can run esp-idf tools without needing to give the
# full path.
#
# Use this script like this:
#
# . ${IDF_PATH}/add_path.sh
#
if [ -z ${IDF_PATH} ]; then
echo "IDF_PATH must be set before including this script."
else
IDF_ADD_PATHS_EXTRAS="${IDF_PATH}/components/esptool_py/esptool:${IDF_PATH}/components/partition_table/"
export PATH="${PATH}:${IDF_ADD_PATHS_EXTRAS}"
echo "Added to PATH: ${IDF_ADD_PATHS_EXTRAS}"
fi

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,33 @@
menu "Bootloader config"
choice BOOTLOADER_LOG_LEVEL
bool "Bootloader log verbosity"
default BOOTLOADER_LOG_LEVEL_NOTICE
help
Specify how much output to see in the bootloader logs.
Note that if MTDO is HIGH on reset, all early boot output
(including bootloader logs) are suppressed.
config BOOTLOADER_LOG_LEVEL_NONE
bool "No output"
config BOOTLOADER_LOG_LEVEL_ERROR
bool "Error"
config BOOTLOADER_LOG_LEVEL_WARN
bool "Warning"
config BOOTLOADER_LOG_LEVEL_INFO
bool "Info"
config BOOTLOADER_LOG_LEVEL_NOTICE
bool "Notice"
config BOOTLOADER_LOG_LEVEL_DEBUG
bool "Debug"
endchoice
config BOOTLOADER_LOG_COLORS
bool "Use ANSI terminal colors in bootloader log output"
default "y"
help
Enable ANSI terminal color codes in bootloader output.
In order to view these, your terminal program must support ANSI color codes.
endmenu

View File

@ -8,6 +8,7 @@
# basically runs Make in the src/ directory but it needs to zero some variables
# the ESP-IDF project.mk makefile exports first, to not let them interfere.
#
ifeq ("$(IS_BOOTLOADER_BUILD)","")
BOOTLOADER_COMPONENT_PATH := $(COMPONENT_PATH)
BOOTLOADER_BUILD_DIR=$(BUILD_DIR_BASE)/bootloader
@ -47,3 +48,5 @@ $(COMPONENT_PATH)/src/sdkconfig: $(PROJECT_PATH)/sdkconfig
# bootloader-flash calls flash in the bootloader dummy project
bootloader-flash: $(BOOTLOADER_BIN)
$(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src flash MAKEFLAGS= V=$(V)
endif

View File

@ -4,7 +4,12 @@
#
PROJECT_NAME := bootloader
COMPONENTS := esptool_py
COMPONENTS := esptool_py bootloader
# The bootloader pseudo-component is also included in this build, for its Kconfig.projbuild to be included.
#
# IS_BOOTLOADER_BUILD tells the component Makefile.projbuild to be a no-op
IS_BOOTLOADER_BUILD := 1
#We cannot include the esp32 component directly but we need its includes. This is fixed by
#adding it in the main/Makefile directory.

View File

@ -19,39 +19,64 @@ extern "C"
{
#endif
#include "sdkconfig.h"
#define BOOT_LOG_LEVEL_NONE (0)
#define BOOT_LOG_LEVEL_ERROR (1)
#define BOOT_LOG_LEVEL_WARN (2)
#define BOOT_LOG_LEVEL_INFO (3)
#define BOOT_LOG_LEVEL_NOTICE (4)
#define BOOT_LOG_LEVEL_DEBUG (5)
#define Black 0;30
#define Red 0;31
#define Green 0;32
#define Brown 0;33
#define Blue 0;34
#define Purple 0;35
#define Cyan 0;36
#define Black "30"
#define Red "31"
#define Green "32"
#define Brown "33"
#define Blue "34"
#define Purple "35"
#define Cyan "36"
// TODO: move BOOT_LOG_LEVEL into menuconfig
//#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_ERROR
#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_NOTICE
#if CONFIG_BOOTLOADER_LOG_COLORS
#define LOG_COLOR(COLOR) "\033[0;"COLOR"m"
#define LOG_BOLD(COLOR) "\033[1;"COLOR"m"
#define LOG_RESET_COLOR "\033[0m"
#else
#define LOG_COLOR(...)
#define LOG_BOLD(...)
#define LOG_RESET_COLOR ""
#endif
// BOOT_LOG_LEVEL defined by make menuconfig
#if CONFIG_BOOTLOADER_LOG_LEVEL_NONE
#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_NONE
#elif CONFIG_BOOTLOADER_LOG_LEVEL_ERROR
#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_ERROR
#elif CONFIG_BOOTLOADER_LOG_LEVEL_WARN
#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_WARN
#elif CONFIG_BOOTLOADER_LOG_LEVEL_INFO
#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO
#elif CONFIG_BOOTLOADER_LOG_LEVEL_NOTICE
#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_NOTICE
#elif CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG
#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_DEBUG
#else
#error "No bootloader log level set in menuconfig!"
#endif
//printf("\033[0;36m[NOTICE][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#define log_notice(format, ...) \
do{\
if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_NOTICE){\
ets_printf("\033[0;36m" format "\r\n", ##__VA_ARGS__);\
ets_printf("\033[0m"); \
ets_printf(LOG_COLOR(Cyan) format "\r\n", ##__VA_ARGS__); \
ets_printf(LOG_RESET_COLOR); \
}\
}while(0)
#define log_info(format, ...) \
do{\
if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_INFO){\
ets_printf("\033[1;36m" format "\r\n", ##__VA_ARGS__);\
ets_printf("\033[0m"); \
ets_printf(LOG_BOLD(Cyan) format "\r\n", ##__VA_ARGS__); \
ets_printf(LOG_RESET_COLOR); \
}\
}while(0)
@ -59,8 +84,8 @@ extern "C"
#define log_error(format, ...) \
do{\
if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_ERROR){\
ets_printf("\033[0;31m[ERROR][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);\
ets_printf("\033[0m"); \
ets_printf(LOG_COLOR(Red) "[ERROR][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
ets_printf(LOG_RESET_COLOR); \
}\
}while(0)
@ -68,8 +93,8 @@ extern "C"
#define log_warn(format, ...) \
do{\
if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_WARN){\
ets_printf("\033[1;33m[WARN][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);\
ets_printf("\033[0m"); \
ets_printf(LOG_BOLD(Brown) "[WARN][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
ets_printf(LOG_RESET_COLOR); \
}\
}while(0)
@ -77,8 +102,8 @@ extern "C"
#define log_debug(format, ...) \
do{\
if(BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_DEBUG){\
ets_printf("\033[1;32m[DEBUG][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
ets_printf("\033[0m"); \
ets_printf(LOG_BOLD(Green) "[DEBUG][%s][%s][%d]\n" format "\r\n", __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
ets_printf(LOG_RESET_COLOR); \
}\
}while(0)
@ -86,4 +111,4 @@ extern "C"
}
#endif
#endif /* __BOOT_LOGGING_H__ */
#endif /* __BOOT_LOGGING_H__ */

View File

@ -276,8 +276,6 @@ void bootloader_main()
{
//Run start routine.
/*ESP32 2ND bootload start here*/
log_info( "\n" );
log_info( "**************************************" );
log_info( "* hello espressif ESP32! *" );
@ -294,7 +292,7 @@ void bootloader_main()
log_notice( "compile time %s\n", __TIME__ );
/* close watch dog here */
REG_CLR_BIT( RTC_WDTCONFIG0, RTC_CNTL_WDT_FLASHBOOT_MOD_EN );
REG_CLR_BIT( WDTCONFIG0, TIMERS_WDT_FLASHBOOT_MOD_EN );
REG_CLR_BIT( WDTCONFIG0(0), TIMERS_WDT_FLASHBOOT_MOD_EN );
SPIUnlock();
/*register first sector in drom0 page 0 */
boot_cache_redirect( 0, 0x5000 );

View File

@ -1,7 +1,7 @@
#
# Main Makefile. This is basically the same as a component makefile.
#
# This Makefile should, at the very least, just include $(IDF_PATH)/make/component.mk. By default,
# This Makefile should, at the very least, just include $(IDF_PATH)/make/component_common.mk. By default,
# this will take the sources in the src/ directory, compile them and link them into
# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
# please read the esp-idf build system document if you need to do this.
@ -10,4 +10,4 @@
COMPONENT_ADD_LDFLAGS := -L $(abspath .) -lmain -T esp32.bootloader.ld -T $(IDF_PATH)/components/esp32/ld/esp32.rom.ld
COMPONENT_EXTRA_INCLUDES := $(IDF_PATH)/components/esp32/include
include $(IDF_PATH)/make/component.mk
include $(IDF_PATH)/make/component_common.mk

View File

@ -7,7 +7,6 @@ config WIFI_ENABLED
This compiles in the low-level WiFi stack.
Temporarily, this option requires that FreeRTOS runs in single core mode.
depends on FREERTOS_UNICORE
config WIFI_AUTO_STARTUP
bool "Start WiFi with system startup"

View File

@ -1,7 +1,7 @@
#
# Component Makefile
#
# This Makefile should, at the very least, just include $(IDF_PATH)/make/component.mk. By default,
# This Makefile should, at the very least, just include $(IDF_PATH)/make/component_common.mk. By default,
# this will take the sources in this directory, compile them and link them into
# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
# please read the esp-idf build system document if you need to do this.
@ -33,18 +33,13 @@ COMPONENT_ADD_LDFLAGS := -lesp32 \
-L $(abspath ld) \
$(LINKER_SCRIPTS)
include $(IDF_PATH)/make/component.mk
include $(IDF_PATH)/make/component_common.mk
ALL_LIB_FILES := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS))
# The binary libraries are in a git submodule, so this target will
# be invoked if any modules are missing (probably because
# git submodule update --init needs to be run).
$(ALL_LIB_FILES):
$(Q) [ -d ${IDF_PATH}/.git ] || ( @echo "ERROR: Missing libraries in esp32 component. esp-idf must be cloned from git to work."; exit 1 )
$(Q) [ -x $(which git) ] || ( @echo "ERROR: Missing libraries in esp32 component. Need to run 'git submodule update --init' in esp-idf root directory."; exit 1 )
@echo "Warning: Missing libraries in components/esp32/lib/ submodule. Going to try running 'git submodule update --init' in esp-idf root directory..."
cd ${IDF_PATH} && git submodule update --init
# automatically trigger a git submodule update
# if any libraries are missing
$(eval $(call SubmoduleRequiredForFiles,$(ALL_LIB_FILES)))
# this is a hack to make sure the app is re-linked if the binary
# libraries change or are updated. If they change, the main esp32

View File

@ -18,6 +18,7 @@
#include "esp_err.h"
#include "rom/ets_sys.h"
#include "rom/uart.h"
#include "soc/dport_reg.h"
#include "soc/io_mux_reg.h"
@ -36,6 +37,8 @@
#include "esp_spi_flash.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_spi_flash.h"
#include "esp_ipc.h"
static void IRAM_ATTR user_start_cpu0(void);
static void IRAM_ATTR call_user_start_cpu1();
@ -59,11 +62,6 @@ We arrive here after the bootloader finished loading the program from flash. The
flash cache is down and the app CPU is in reset. We do have a stack, so we can do the initialization in C.
*/
void Uart_Init(int no);
void uartAttach();
void ets_set_appcpu_boot_addr(uint32_t ent);
int ets_getAppEntry();
static bool app_cpu_started = false;
void IRAM_ATTR call_user_start_cpu0() {
@ -180,53 +178,55 @@ void IRAM_ATTR call_user_start_cpu1() {
user_start_cpu1();
}
extern volatile int port_xSchedulerRunning;
extern int xPortStartScheduler();
extern volatile int port_xSchedulerRunning[2];
void user_start_cpu1(void) {
//Wait for the freertos initialization is finished on CPU0
while (port_xSchedulerRunning == 0) ;
ets_printf("Core0 started initializing FreeRTOS. Jumping to scheduler.\n");
//Okay, start the scheduler!
void IRAM_ATTR user_start_cpu1(void) {
// Wait for FreeRTOS initialization to finish on PRO CPU
while (port_xSchedulerRunning[0] == 0) {
;
}
ets_printf("Starting scheduler on APP CPU.\n");
xPortStartScheduler();
}
extern void (*__init_array_start)(void);
extern void (*__init_array_end)(void);
extern esp_err_t app_main();
static void do_global_ctors(void) {
void (**p)(void);
for(p = &__init_array_start; p != &__init_array_end; ++p)
(*p)();
}
extern esp_err_t app_main(void *ctx);
void user_start_cpu0(void) {
ets_setup_syscalls();
do_global_ctors();
esp_ipc_init();
spi_flash_init();
#if CONFIG_WIFI_ENABLED
ets_printf("nvs_flash_init\n");
esp_err_t ret = nvs_flash_init(5, 3);
if (ret != ESP_OK) {
ets_printf("nvs_flash_init fail, ret=%d\n", ret);
printf("nvs_flash_init failed, ret=%d\n", ret);
}
system_init();
esp_event_init(NULL);
esp_event_init(NULL, NULL);
tcpip_adapter_init();
#endif
#if CONFIG_WIFI_ENABLED && CONFIG_WIFI_AUTO_STARTUP
#include "esp_wifi.h"
esp_wifi_startup(app_main);
esp_wifi_startup(app_main, NULL);
#else
app_main();
app_main(NULL);
#endif
ets_printf("Starting scheduler on PRO CPU.\n");
vTaskStartScheduler();
}

View File

@ -11,6 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
@ -29,10 +30,13 @@
#define ESP32_WORKAROUND 1
#if CONFIG_WIFI_ENABLED
static bool event_init_flag = false;
static xQueueHandle g_event_handler = NULL;
static system_event_cb_t g_event_handler_cb;
#define WIFI_DEBUG(...)
static system_event_cb_t g_event_handler_cb;
static void *g_event_ctx;
#define WIFI_DEBUG(...)
#define WIFI_API_CALL_CHECK(info, api_call, ret) \
do{\
esp_err_t __err = (api_call);\
@ -43,6 +47,7 @@ do{\
} while(0)
typedef esp_err_t (*system_event_handle_fn_t)(system_event_t *e);
typedef struct {
system_event_id_t event_id;
system_event_handle_fn_t event_handle;
@ -55,7 +60,7 @@ static esp_err_t system_event_sta_start_handle_default(system_event_t *event);
static esp_err_t system_event_sta_stop_handle_default(system_event_t *event);
static esp_err_t system_event_sta_connected_handle_default(system_event_t *event);
static esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event);
static esp_err_t system_event_sta_gotip_default(system_event_t *event);
static esp_err_t system_event_sta_got_ip_default(system_event_t *event);
static system_event_handle_t g_system_event_handle_table[] = {
{SYSTEM_EVENT_WIFI_READY, NULL},
@ -65,7 +70,7 @@ static system_event_handle_t g_system_event_handle_table[] = {
{SYSTEM_EVENT_STA_CONNECTED, system_event_sta_connected_handle_default},
{SYSTEM_EVENT_STA_DISCONNECTED, system_event_sta_disconnected_handle_default},
{SYSTEM_EVENT_STA_AUTHMODE_CHANGE, NULL},
{SYSTEM_EVENT_STA_GOTIP, system_event_sta_gotip_default},
{SYSTEM_EVENT_STA_GOT_IP, system_event_sta_got_ip_default},
{SYSTEM_EVENT_AP_START, system_event_ap_start_handle_default},
{SYSTEM_EVENT_AP_STOP, system_event_ap_stop_handle_default},
{SYSTEM_EVENT_AP_STACONNECTED, NULL},
@ -74,15 +79,15 @@ static system_event_handle_t g_system_event_handle_table[] = {
{SYSTEM_EVENT_MAX, NULL},
};
static esp_err_t system_event_sta_gotip_default(system_event_t *event)
static esp_err_t system_event_sta_got_ip_default(system_event_t *event)
{
extern esp_err_t esp_wifi_set_sta_ip(void);
WIFI_API_CALL_CHECK("esp_wifi_set_sta_ip", esp_wifi_set_sta_ip(), ESP_OK);
printf("ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR "\n",
IP2STR(&event->event_info.got_ip.ip_info.ip),
IP2STR(&event->event_info.got_ip.ip_info.netmask),
IP2STR(&event->event_info.got_ip.ip_info.gw));
IP2STR(&event->event_info.got_ip.ip_info.ip),
IP2STR(&event->event_info.got_ip.ip_info.netmask),
IP2STR(&event->event_info.got_ip.ip_info.gw));
return ESP_OK;
}
@ -132,7 +137,7 @@ esp_err_t system_event_sta_stop_handle_default(system_event_t *event)
esp_err_t system_event_sta_connected_handle_default(system_event_t *event)
{
tcpip_adapter_dhcp_status_t status;
WIFI_API_CALL_CHECK("esp_wifi_reg_rxcb", esp_wifi_reg_rxcb(WIFI_IF_STA, (wifi_rxcb_t)tcpip_adapter_sta_input), ESP_OK);
tcpip_adapter_up(TCPIP_ADAPTER_IF_STA);
@ -150,7 +155,7 @@ esp_err_t system_event_sta_connected_handle_default(system_event_t *event)
system_event_t evt;
//notify event
evt.event_id = SYSTEM_EVENT_STA_GOTIP;
evt.event_id = SYSTEM_EVENT_STA_GOT_IP;
memcpy(&evt.event_info.got_ip.ip_info, &sta_ip, sizeof(tcpip_adapter_ip_info_t));
esp_event_send(&evt);
@ -172,7 +177,7 @@ esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event)
static esp_err_t esp_wifi_post_event_to_user(system_event_t *event)
{
if (g_event_handler_cb) {
return (*g_event_handler_cb)(event);
return (*g_event_handler_cb)(g_event_ctx, event);
}
return ESP_OK;
@ -187,102 +192,88 @@ static esp_err_t esp_system_event_debug(system_event_t *event)
WIFI_DEBUG("received event: ");
switch (event->event_id) {
case SYSTEM_EVENT_WIFI_READY:
{
WIFI_DEBUG("SYSTEM_EVENT_WIFI_READY\n");
break;
}
case SYSTEM_EVENT_SCAN_DONE:
{
system_event_sta_scan_done_t *scan_done;
scan_done = &event->event_info.scan_done;
WIFI_DEBUG("SYSTEM_EVENT_SCAN_DONE\nstatus:%d, number:%d\n", scan_done->status, scan_done->number);
break;
}
case SYSTEM_EVENT_STA_START:
{
WIFI_DEBUG("SYSTEM_EVENT_STA_START\n");
break;
}
case SYSTEM_EVENT_STA_STOP:
{
WIFI_DEBUG("SYSTEM_EVENT_STA_STOP\n");
break;
}
case SYSTEM_EVENT_STA_CONNECTED:
{
system_event_sta_connected_t *connected;
connected = &event->event_info.connected;
WIFI_DEBUG("SYSTEM_EVENT_STA_CONNECTED\nssid:%s, ssid_len:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x, channel:%d, authmode:%d\n", \
connected->ssid, connected->ssid_len, connected->bssid[0], connected->bssid[0], connected->bssid[1], \
connected->bssid[3], connected->bssid[4], connected->bssid[5], connected->channel, connected->authmode);
break;
}
case SYSTEM_EVENT_STA_DISCONNECTED:
{
system_event_sta_disconnected_t *disconnected;
disconnected = &event->event_info.disconnected;
WIFI_DEBUG("SYSTEM_EVENT_STA_DISCONNECTED\nssid:%s, ssid_len:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x, reason:%d\n", \
disconnected->ssid, disconnected->ssid_len, disconnected->bssid[0], disconnected->bssid[0], disconnected->bssid[1], \
disconnected->bssid[3], disconnected->bssid[4], disconnected->bssid[5], disconnected->reason);
break;
}
case SYSTEM_EVENT_STA_AUTHMODE_CHANGE:
{
system_event_sta_authmode_change_t *auth_change;
auth_change = &event->event_info.auth_change;
WIFI_DEBUG("SYSTEM_EVENT_STA_AUTHMODE_CHNAGE\nold_mode:%d, new_mode:%d\n", auth_change->old_mode, auth_change->new_mode);
break;
}
case SYSTEM_EVENT_STA_GOTIP:
{
system_event_sta_got_ip_t *got_ip;
got_ip = &event->event_info.got_ip;
WIFI_DEBUG("SYSTEM_EVENT_STA_GOTIP\n");
break;
}
case SYSTEM_EVENT_AP_START:
{
WIFI_DEBUG("SYSTEM_EVENT_AP_START\n");
break;
}
case SYSTEM_EVENT_AP_STOP:
{
WIFI_DEBUG("SYSTEM_EVENT_AP_STOP\n");
break;
}
case SYSTEM_EVENT_AP_STACONNECTED:
{
system_event_ap_staconnected_t *staconnected;
staconnected = &event->event_info.sta_connected;
WIFI_DEBUG("SYSTEM_EVENT_AP_STACONNECTED\nmac:%02x:%02x:%02x:%02x:%02x:%02x, aid:%d\n", \
staconnected->mac[0], staconnected->mac[0], staconnected->mac[1], \
staconnected->mac[3], staconnected->mac[4], staconnected->mac[5], staconnected->aid);
break;
}
case SYSTEM_EVENT_AP_STADISCONNECTED:
{
system_event_ap_stadisconnected_t *stadisconnected;
stadisconnected = &event->event_info.sta_disconnected;
WIFI_DEBUG("SYSTEM_EVENT_AP_STADISCONNECTED\nmac:%02x:%02x:%02x:%02x:%02x:%02x, aid:%d\n", \
stadisconnected->mac[0], stadisconnected->mac[0], stadisconnected->mac[1], \
stadisconnected->mac[3], stadisconnected->mac[4], stadisconnected->mac[5], stadisconnected->aid);
break;
}
case SYSTEM_EVENT_AP_PROBEREQRECVED:
{
system_event_ap_probe_req_rx_t *ap_probereqrecved;
ap_probereqrecved = &event->event_info.ap_probereqrecved;
WIFI_DEBUG("SYSTEM_EVENT_AP_PROBEREQRECVED\nrssi:%d, mac:%02x:%02x:%02x:%02x:%02x:%02x\n", \
ap_probereqrecved->rssi, ap_probereqrecved->mac[0], ap_probereqrecved->mac[0], ap_probereqrecved->mac[1], \
ap_probereqrecved->mac[3], ap_probereqrecved->mac[4], ap_probereqrecved->mac[5]);
break;
}
default:
{
printf("Error: no such kind of event!\n");
break;
}
case SYSTEM_EVENT_WIFI_READY: {
WIFI_DEBUG("SYSTEM_EVENT_WIFI_READY\n");
break;
}
case SYSTEM_EVENT_SCAN_DONE: {
system_event_sta_scan_done_t *scan_done;
scan_done = &event->event_info.scan_done;
WIFI_DEBUG("SYSTEM_EVENT_SCAN_DONE\nstatus:%d, number:%d\n", scan_done->status, scan_done->number);
break;
}
case SYSTEM_EVENT_STA_START: {
WIFI_DEBUG("SYSTEM_EVENT_STA_START\n");
break;
}
case SYSTEM_EVENT_STA_STOP: {
WIFI_DEBUG("SYSTEM_EVENT_STA_STOP\n");
break;
}
case SYSTEM_EVENT_STA_CONNECTED: {
system_event_sta_connected_t *connected;
connected = &event->event_info.connected;
WIFI_DEBUG("SYSTEM_EVENT_STA_CONNECTED\nssid:%s, ssid_len:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x, channel:%d, authmode:%d\n", \
connected->ssid, connected->ssid_len, connected->bssid[0], connected->bssid[0], connected->bssid[1], \
connected->bssid[3], connected->bssid[4], connected->bssid[5], connected->channel, connected->authmode);
break;
}
case SYSTEM_EVENT_STA_DISCONNECTED: {
system_event_sta_disconnected_t *disconnected;
disconnected = &event->event_info.disconnected;
WIFI_DEBUG("SYSTEM_EVENT_STA_DISCONNECTED\nssid:%s, ssid_len:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x, reason:%d\n", \
disconnected->ssid, disconnected->ssid_len, disconnected->bssid[0], disconnected->bssid[0], disconnected->bssid[1], \
disconnected->bssid[3], disconnected->bssid[4], disconnected->bssid[5], disconnected->reason);
break;
}
case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: {
system_event_sta_authmode_change_t *auth_change;
auth_change = &event->event_info.auth_change;
WIFI_DEBUG("SYSTEM_EVENT_STA_AUTHMODE_CHNAGE\nold_mode:%d, new_mode:%d\n", auth_change->old_mode, auth_change->new_mode);
break;
}
case SYSTEM_EVENT_STA_GOT_IP: {
system_event_sta_got_ip_t *got_ip;
got_ip = &event->event_info.got_ip;
WIFI_DEBUG("SYSTEM_EVENT_STA_GOTIP\n");
break;
}
case SYSTEM_EVENT_AP_START: {
WIFI_DEBUG("SYSTEM_EVENT_AP_START\n");
break;
}
case SYSTEM_EVENT_AP_STOP: {
WIFI_DEBUG("SYSTEM_EVENT_AP_STOP\n");
break;
}
case SYSTEM_EVENT_AP_STACONNECTED: {
system_event_ap_staconnected_t *staconnected;
staconnected = &event->event_info.sta_connected;
WIFI_DEBUG("SYSTEM_EVENT_AP_STACONNECTED\nmac:%02x:%02x:%02x:%02x:%02x:%02x, aid:%d\n", \
staconnected->mac[0], staconnected->mac[0], staconnected->mac[1], \
staconnected->mac[3], staconnected->mac[4], staconnected->mac[5], staconnected->aid);
break;
}
case SYSTEM_EVENT_AP_STADISCONNECTED: {
system_event_ap_stadisconnected_t *stadisconnected;
stadisconnected = &event->event_info.sta_disconnected;
WIFI_DEBUG("SYSTEM_EVENT_AP_STADISCONNECTED\nmac:%02x:%02x:%02x:%02x:%02x:%02x, aid:%d\n", \
stadisconnected->mac[0], stadisconnected->mac[0], stadisconnected->mac[1], \
stadisconnected->mac[3], stadisconnected->mac[4], stadisconnected->mac[5], stadisconnected->aid);
break;
}
case SYSTEM_EVENT_AP_PROBEREQRECVED: {
system_event_ap_probe_req_rx_t *ap_probereqrecved;
ap_probereqrecved = &event->event_info.ap_probereqrecved;
WIFI_DEBUG("SYSTEM_EVENT_AP_PROBEREQRECVED\nrssi:%d, mac:%02x:%02x:%02x:%02x:%02x:%02x\n", \
ap_probereqrecved->rssi, ap_probereqrecved->mac[0], ap_probereqrecved->mac[0], ap_probereqrecved->mac[1], \
ap_probereqrecved->mac[3], ap_probereqrecved->mac[4], ap_probereqrecved->mac[5]);
break;
}
default: {
printf("Error: no such kind of event!\n");
break;
}
}
return ESP_OK;
@ -296,8 +287,8 @@ static esp_err_t esp_system_event_handler(system_event_t *event)
}
esp_system_event_debug(event);
if ((event->event_id < SYSTEM_EVENT_MAX) && (event->event_id == g_system_event_handle_table[event->event_id].event_id)){
if (g_system_event_handle_table[event->event_id].event_handle){
if ((event->event_id < SYSTEM_EVENT_MAX) && (event->event_id == g_system_event_handle_table[event->event_id].event_id)) {
if (g_system_event_handle_table[event->event_id].event_handle) {
WIFI_DEBUG("enter default callback\n");
g_system_event_handle_table[event->event_id].event_handle(event);
WIFI_DEBUG("exit default callback\n");
@ -317,42 +308,57 @@ static void esp_system_event_task(void *pvParameters)
while (1) {
if (xQueueReceive(g_event_handler, &evt, portMAX_DELAY) == pdPASS) {
ret = esp_system_event_handler(&evt);
if (ret == ESP_FAIL)
if (ret == ESP_FAIL) {
printf("esp wifi post event to user fail!\n");
}
}
}
}
system_event_cb_t esp_event_set_cb(system_event_cb_t cb)
system_event_cb_t esp_event_set_cb(system_event_cb_t cb, void *ctx)
{
system_event_cb_t old_cb = g_event_handler_cb;
g_event_handler_cb = cb;
g_event_ctx = ctx;
return old_cb;
}
esp_err_t esp_event_send(system_event_t *event)
{
portBASE_TYPE ret;
ret = xQueueSendToBack((xQueueHandle)g_event_handler, event, 0);
if (pdPASS != ret){
if (event) printf("e=%d f\n", event->event_id);
else printf("e null\n");
if (pdPASS != ret) {
if (event) {
printf("e=%d f\n", event->event_id);
} else {
printf("e null\n");
}
return ESP_FAIL;
}
return ESP_OK;
}
void* esp_event_get_handler(void)
void *esp_event_get_handler(void)
{
return (void*)g_event_handler;
return (void *)g_event_handler;
}
esp_err_t esp_event_init(system_event_cb_t cb)
esp_err_t esp_event_init(system_event_cb_t cb, void *ctx)
{
g_event_handler_cb = (system_event_cb_t)cb;
if (event_init_flag) {
return ESP_FAIL;
}
g_event_handler_cb = cb;
g_event_ctx = ctx;
g_event_handler = xQueueCreate(CONFIG_WIFI_ENENT_QUEUE_SIZE, sizeof(system_event_t));
xTaskCreatePinnedToCore(esp_system_event_task, "eventTask", CONFIG_WIFI_EVENT_TASK_STACK_SIZE, NULL, 5, NULL, 0); // TODO: rearrange task priority
return ESP_OK;
}

View File

@ -27,7 +27,10 @@ typedef int32_t esp_err_t;
#define ESP_OK 0
#define ESP_FAIL -1
#define ESP_ERR_NO_MEM 0x101
#define ESP_ERR_NO_MEM 0x101
#define ESP_ERR_INVALID_ARG 0x102
#define ESP_ERR_INVALID_STATE 0x103
#ifdef __cplusplus
}

84
components/esp32/include/esp_event.h Executable file → Normal file
View File

@ -28,24 +28,24 @@ extern "C" {
#endif
typedef enum {
SYSTEM_EVENT_WIFI_READY = 0, /**< ESP32 wifi ready */
SYSTEM_EVENT_WIFI_READY = 0, /**< ESP32 WiFi ready */
SYSTEM_EVENT_SCAN_DONE, /**< ESP32 finish scanning AP */
SYSTEM_EVENT_STA_START, /**< ESP32 station start */
SYSTEM_EVENT_STA_STOP, /**< ESP32 station start */
SYSTEM_EVENT_STA_STOP, /**< ESP32 station stop */
SYSTEM_EVENT_STA_CONNECTED, /**< ESP32 station connected to AP */
SYSTEM_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected to AP */
SYSTEM_EVENT_STA_DISCONNECTED, /**< ESP32 station disconnected from AP */
SYSTEM_EVENT_STA_AUTHMODE_CHANGE, /**< the auth mode of AP connected by ESP32 station changed */
SYSTEM_EVENT_STA_GOTIP, /**< ESP32 station received IP address */
SYSTEM_EVENT_AP_START, /**< ESP32 softap start */
SYSTEM_EVENT_AP_STOP, /**< ESP32 softap start */
SYSTEM_EVENT_STA_GOT_IP, /**< ESP32 station got IP from connected AP */
SYSTEM_EVENT_AP_START, /**< ESP32 soft-AP start */
SYSTEM_EVENT_AP_STOP, /**< ESP32 soft-AP stop */
SYSTEM_EVENT_AP_STACONNECTED, /**< a station connected to ESP32 soft-AP */
SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected to ESP32 soft-AP */
SYSTEM_EVENT_AP_STADISCONNECTED, /**< a station disconnected from ESP32 soft-AP */
SYSTEM_EVENT_AP_PROBEREQRECVED, /**< Receive probe request packet in soft-AP interface */
SYSTEM_EVENT_MAX
} system_event_id_t;
typedef struct {
uint32_t status; /**< status of scanning APs*/
uint32_t status; /**< status of scanning APs */
uint8_t number;
uint8_t scan_id;
} system_event_sta_scan_done_t;
@ -94,10 +94,10 @@ typedef union {
system_event_sta_disconnected_t disconnected; /**< ESP32 station disconnected to AP */
system_event_sta_scan_done_t scan_done; /**< ESP32 station scan (APs) done */
system_event_sta_authmode_change_t auth_change; /**< the auth mode of AP ESP32 station connected to changed */
system_event_sta_got_ip_t got_ip;
system_event_sta_got_ip_t got_ip; /**< ESP32 station got IP */
system_event_ap_staconnected_t sta_connected; /**< a station connected to ESP32 soft-AP */
system_event_ap_stadisconnected_t sta_disconnected; /**< a station disconnected to ESP32 soft-AP */
system_event_ap_probe_req_rx_t ap_probereqrecved; /**< ESP32 softAP receive probe request packet */
system_event_ap_probe_req_rx_t ap_probereqrecved; /**< ESP32 soft-AP receive probe request packet */
} system_event_info_t;
typedef struct {
@ -105,11 +105,65 @@ typedef struct {
system_event_info_t event_info; /**< event information */
} system_event_t;
typedef esp_err_t (*system_event_cb_t)(system_event_t *event);
system_event_cb_t esp_event_set_cb(system_event_cb_t cb);
esp_err_t esp_event_send(system_event_t * event);
void* esp_event_get_handler(void);
esp_err_t esp_event_init(system_event_cb_t cb);
/**
* @brief Application specified event callback function
*
* @param void *ctx : reserved for user
* @param system_event_t *event : event type defined in this file
*
* @return ESP_OK : succeed
* @return others : fail
*/
typedef esp_err_t (*system_event_cb_t)(void *ctx, system_event_t *event);
/**
* @brief Set application specified event callback function
*
* @attention 1. If cb is NULL, means application don't need to handle
* If cb is not NULL, it will be call when an event is received, after the default event callback is completed
*
* @param system_event_cb_t cb : callback
* @param void *ctx : reserved for user
*
* @return system_event_cb_t : old callback
*/
system_event_cb_t esp_event_set_cb(system_event_cb_t cb, void *ctx);
/**
* @brief Send a event to event task
*
* @attention 1. Other task/modules, such as the TCPIP module, can call this API to send an event to event task
*
* @param system_event_t * event : event
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_event_send(system_event_t *event);
/**
* @brief Get the event handler
*
* @attention : currently this API returns event queue handler, by this event queue,
* users can notice when WiFi has done something like scanning done, connected to AP or disconnected from AP.
*
* @param null
*
* @return void * : event queue pointer
*/
void *esp_event_get_handler(void);
/**
* @brief Init the event module
* Create the event handler and task
*
* @param system_event_cb_t cb : application specified event callback, it can be modified by call esp_event_set_cb
* @param void *ctx : reserved for user
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_event_init(system_event_cb_t cb, void *ctx);
#ifdef __cplusplus
}

View File

@ -61,8 +61,8 @@ extern "C" {
#define ESP_GPIO_INTR_ATTACH(func, arg) \
xt_set_interrupt_handler(ETS_GPIO_INUM, (func), (void *)(arg))
#define ESP_UART_INTR_ATTACH(func, arg) \
xt_set_interrupt_handler(ETS_UART_INUM, (func), (void *)(arg))
#define ESP_UART0_INTR_ATTACH(func, arg) \
xt_set_interrupt_handler(ETS_UART0_INUM, (func), (void *)(arg))
#define ESP_WDT_INTR_ATTACH(func, arg) \
xt_set_interrupt_handler(ETS_WDT_INUM, (func), (void *)(arg))
@ -142,11 +142,11 @@ extern "C" {
#define ESP_BB_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_BB_INUM)
#define ESP_UART_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_UART_INUM)
#define ESP_UART0_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_UART0_INUM)
#define ESP_UART_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_UART_INUM)
#define ESP_UART0_INTR_DISABLE() \
ESP_INTR_DISABLE(ETS_UART0_INUM)
#define ESP_LEDC_INTR_ENABLE() \
ESP_INTR_ENABLE(ETS_LEDC_INUM)

View File

@ -0,0 +1,88 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __ESP_IPC_H__
#define __ESP_IPC_H__
#include <esp_err.h>
typedef void (*esp_ipc_func_t)(void* arg);
/**
* @brief Inter-processor call APIs
*
* FreeRTOS provides several APIs which can be used to communicate between
* different tasks, including tasks running on different CPUs.
* This module provides additional APIs to run some code on the other CPU.
*
* These APIs can only be used when FreeRTOS scheduler is running.
*/
/**
* @brief Initialize inter-processor call module.
*
* This function start two tasks, one on each CPU. These tasks are started
* with high priority. These tasks are normally inactive, waiting until one of
* the esp_ipc_call_* functions to be used. One of these tasks will be
* woken up to execute the callback provided to esp_ipc_call_nonblocking or
* esp_ipc_call_blocking.
*/
void esp_ipc_init();
/**
* @brief Execute function on the given CPU
*
* This will wake a high-priority task on CPU indicated by cpu_id argument,
* and run func(arg) in the context of that task.
* This function returns as soon as the high-priority task is woken up.
* If another IPC call is already being executed, this function will also wait
* for it to complete.
*
* In single-core mode, returns ESP_ERR_INVALID_ARG for cpu_id 1.
*
* @param cpu_id CPU where function should be executed (0 or 1)
* @param func pointer to a function which should be executed
* @param arg arbitrary argument to be passed into function
*
* @return ESP_ERR_INVALID_ARG if cpu_id is invalid
* ESP_ERR_INVALID_STATE if FreeRTOS scheduler is not running
* ESP_OK otherwise
*/
esp_err_t esp_ipc_call(uint32_t cpu_id, esp_ipc_func_t func, void* arg);
/**
* @brief Execute function on the given CPU and wait for it to finish
*
* This will wake a high-priority task on CPU indicated by cpu_id argument,
* and run func(arg) in the context of that task.
* This function waits for func to return.
*
* In single-core mode, returns ESP_ERR_INVALID_ARG for cpu_id 1.
*
* @param cpu_id CPU where function should be executed (0 or 1)
* @param func pointer to a function which should be executed
* @param arg arbitrary argument to be passed into function
*
* @return ESP_ERR_INVALID_ARG if cpu_id is invalid
* ESP_ERR_INVALID_STATE if FreeRTOS scheduler is not running
* ESP_OK otherwise
*/
esp_err_t esp_ipc_call_blocking(uint32_t cpu_id, esp_ipc_func_t func, void* arg);
#endif /* __ESP_IPC_H__ */

494
components/esp32/include/esp_wifi.h Executable file → Normal file
View File

@ -12,6 +12,48 @@
// See the License for the specific language governing permissions and
// limitations under the License.
/* Notes about WiFi Programming
*
* The esp32 WiFi programming model can be depicted as following picture:
*
*
* default handler user handler
* ------------- --------------- ---------------
* | | event | | callback or | |
* | tcpip | ---------> | event | ----------> | application |
* | stack | | task | event | task |
* |-----------| |-------------| |-------------|
* /|\ |
* | |
* event | |
* | |
* | |
* --------------- |
* | | |
* | WiFi Driver |/__________________|
* | |\ API call
* | |
* |-------------|
*
* The WiFi driver can be consider as black box, it knows nothing about the high layer code, such as
* TCPIP stack, application task, event task etc, all it can do is to receive API call from high layer
* or post event queue to a specified Queue, which is initialized by API esp_wifi_init().
*
* The event task is a daemon task, which receives events from WiFi driver or from other subsystem, such
* as TCPIP stack, event task will call the default callback function on receiving the event. For example,
* on receiving event SYSTEM_EVENT_STA_CONNECTED, it will call tcpip_adapter_start() to start the DHCP
* client in it's default handler.
*
* Application can register it's own event callback function by API esp_event_init, then the application callback
* function will be called after the default callback. Also, if application doesn't want to execute the callback
* in the event task, what it needs to do is to post the related event to application task in the application callback function.
*
* The application task (code) generally mixes all these thing together, it calls APIs to init the system/WiFi and
* handle the events when necessary.
*
*/
#ifndef __ESP_WIFI_H__
#define __ESP_WIFI_H__
@ -40,10 +82,10 @@ typedef enum {
} wifi_interface_t;
typedef enum {
WIFI_COUNTRY_CN = 0,
WIFI_COUNTRY_JP,
WIFI_COUNTRY_US,
WIFI_COUNTRY_EU,
WIFI_COUNTRY_CN = 0, /**< country China, channel range [1, 14] */
WIFI_COUNTRY_JP, /**< country Japan, channel range [1, 14] */
WIFI_COUNTRY_US, /**< country USA, channel range [1, 11] */
WIFI_COUNTRY_EU, /**< country Europe, channel range [1, 13] */
WIFI_COUNTRY_MAX
} wifi_country_t;
@ -89,54 +131,205 @@ enum {
};
typedef enum {
WIFI_SECOND_CHAN_NONE = 0,
WIFI_SECOND_CHAN_ABOVE,
WIFI_SECOND_CHAN_BELOW,
WIFI_SECOND_CHAN_NONE = 0, /**< the channel width is HT20 */
WIFI_SECOND_CHAN_ABOVE, /**< the channel width is HT40 and the second channel is above the primary channel */
WIFI_SECOND_CHAN_BELOW, /**< the channel width is HT40 and the second channel is below the primary channel */
} wifi_second_chan_t;
typedef esp_err_t (* wifi_startup_cb_t)(void);
/**
* @brief startup WiFi driver and register application specific callback function
*
* @attention 1. This API should be called in application startup code to init WiFi driver
* @attention 2. The callback function is used to provide application specific WiFi configuration,
* such as, set the WiFi mode, register the event callback, set AP SSID etc before
* WiFi is startup
* @attention 3. Avoid to create application task in the callback, otherwise you may get wrong behavior
* @attention 4. If the callback return is not ESP_OK, the startup will fail!
* @attention 5. Before this API can be called, system_init()/esp_event_init()/tcpip_adapter_init() should
* be called firstly
*
* @param wifi_startup_cb_t cb : application specific callback function
* @param void *ctx : reserved for user
*
* @return ESP_OK : succeed
* @return others : fail
*/
typedef esp_err_t (* wifi_startup_cb_t)(void *ctx);
void esp_wifi_startup(wifi_startup_cb_t cb);
esp_err_t esp_wifi_startup(wifi_startup_cb_t cb, void *ctx);
typedef struct {
void *event_q;
void *event_q; /**< WiFi event q handler, it's a freeRTOS queue */
uint8_t rx_ba_win; /**< TBC */
uint8_t tx_ba_win; /**< TBC */
uint8_t rx_buf_cnt; /**< TBC */
uint8_t tx_buf_cnt; /**< TBC */
} wifi_init_config_t;
/**
* @brief Init WiFi
* Alloc resource for WiFi driver, such as WiFi control structure, RX/TX buffer,
* WiFi NVS structure etc, this WiFi also start WiFi task
*
* @attention 1. This API must be called before all other WiFi API can be called
* @attention 2. Generally we should init event_q in *config, WiFi driver will post the event
* to this queue when event happens, such as, when station connects to WiFi, WiFi driver
* will post station connected event to this queue. If the queue is not initialized, WiFi
* will not post any events
* @attention 3. For other parameters, currently it's not ready, just ignore it.
*
* @param wifi_init_config_t *config : provide WiFi init configuration
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_init(wifi_init_config_t *config);
/**
* @brief Deinit WiFi
* Free all resource allocated in esp_wifi_init and stop WiFi task
*
* @attention 1. This API should be called if you want to remove WiFi driver from the system
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_deinit(void);
/**
* @brief Set the WiFi operating mode
*
* Set the WiFi operating mode as station, soft-AP or station+soft-AP,
* The default mode is soft-AP mode.
*
* @param wifi_mode_t mode : WiFi operating modes:
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_set_mode(wifi_mode_t mode);
/**
* @brief Get current operating mode of WiFi
*
* @param wifi_mode_t *mode : store current WiFi mode
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_get_mode(wifi_mode_t *mode);
/**
* @brief Start WiFi according to current configuration
* If mode is WIFI_MODE_STA, it create station control block and start station
* If mode is WIFI_MODE_AP, it create soft-AP control block and start soft-AP
* If mode is WIFI_MODE_APSTA, it create soft-AP and station control block and start soft-AP and station
*
* @param null
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_start(void);
/**
* @brief Stop WiFi
If mode is WIFI_MODE_STA, it stop station and free station control block
* If mode is WIFI_MODE_AP, it stop soft-AP and free soft-AP control block
* If mode is WIFI_MODE_APSTA, it stop station/soft-AP and free station/soft-AP control block
*
* @param null
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_stop(void);
/**
* @brief Connect the ESP32 WiFi station to the AP.
*
* @attention 1. This API only impact WIFI_MODE_STA or WIFI_MODE_APSTA mode
* @attention 2. If the ESP32 is connected to an AP, call esp_wifi_disconnect to disconnect.
*
* @param null
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_connect(void);
/**
* @brief Disconnect the ESP32 WiFi station from the AP.
*
* @param null
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_disconnect(void);
/**
* @brief Currently this API is just an stub API
*
* @param null
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_clear_fast_connect(void);
/**
* @brief Kick the all station or associated id equals to aid
*
* @param uint16_t aid : when aid is 0, kick all stations, otherwise kick station whose associated id is aid
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_kick_station(uint16_t aid);
typedef struct {
char *ssid; /**< SSID of AP */
uint8_t *bssid; /**< MAC address of AP */
uint8_t channel; /**< channel, scan the specific channel */
bool show_hidden; /**< enable to scan AP whose SSID is hidden */
bool show_hidden; /**< enable to scan AP whose SSID is hidden */
} wifi_scan_config_t;
/**
* @brief Scan all available APs.
*
* @attention If this API is called, the found APs are stored in WiFi driver dynamic allocated memory and the
* will be freed in esp_wifi_get_ap_list, so generally, call esp_wifi_get_ap_list to cause
* the memory to be freed once the scan is done
*
* @param struct scan_config *config : configuration of scanning
* @param bool block : if block is true, this API will block the caller until the scan is done, otherwise
* it will return immediately
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_scan_start(wifi_scan_config_t *conf, bool block);
/**
* @brief Stop the scan in process
*
* @param null
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_scan_stop(void);
/**
* @brief Get number of APs found in last scan
*
* @param uint16_t *number : store number of APIs found in last scan
*
* @attention This API can only be called when the scan is completed, otherwise it may get wrong value
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_get_ap_num(uint16_t *number);
typedef struct {
@ -144,58 +337,226 @@ typedef struct {
uint8_t ssid[32]; /**< SSID of AP */
uint8_t primary; /**< channel of AP */
wifi_second_chan_t second; /**< second channel of AP */
signed char rssi; /**< signal strength of AP */
int8_t rssi; /**< signal strength of AP */
wifi_auth_mode_t authmode; /**< authmode of AP */
}wifi_ap_list_t;
} wifi_ap_list_t;
/**
* @brief Get AP list found in last scan
*
* @param uint16_t *number : as input param, it stores max AP number ap_list can hold, as output param, it store
the actual AP number this API returns
* @param wifi_ap_list_t *ap_list : a list to hold the found APs
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_get_ap_list(uint16_t *number, wifi_ap_list_t *ap_list);
typedef enum {
WIFI_PS_NONE,
WIFI_PS_MODEM,
WIFI_PS_LIGHT,
WIFI_PS_MAC,
WIFI_PS_NONE, /**< No power save */
WIFI_PS_MODEM, /**< Modem power save */
WIFI_PS_LIGHT, /**< Light power save */
WIFI_PS_MAC, /**< MAC power save */
} wifi_ps_type_t;
/**
* @brief Set current power save type
*
* @param wifi_ps_type_t type : power save type
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_set_ps(wifi_ps_type_t type);
/**
* @brief Get current power save type
*
* @param wifi_ps_type_t *type : store current power save type
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_get_ps(wifi_ps_type_t *type);
#define WIFI_PROTOCOL_11B 1
#define WIFI_PROTOCOL_11G 2
#define WIFI_PROTOCOL_11N 4
esp_err_t esp_wifi_set_protocol(wifi_interface_t ifx, uint8_t protocol);
/**
* @brief Set protocol type of specified interface
* The default protocol is (WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)
*
* @attention Currently we only support 802.11b or 802.11bg or 802.11bgn mode
*
* @param wifi_interface_t ifx : interfaces
* @param uint8_t protocol : WiFi protocol bitmap
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_set_protocol(wifi_interface_t ifx, uint8_t protocol_bitmap);
esp_err_t esp_wifi_get_protocol(wifi_interface_t ifx, uint8_t *protocol);
/**
* @brief Get the current protocol bitmap of specified ifx
*
* @param wifi_interface_t ifx : interfaces
* @param uint8_t protocol : store current WiFi protocol bitmap of interface ifx
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_get_protocol(wifi_interface_t ifx, uint8_t *protocol_bitmap);
typedef enum {
WIFI_BW_HT20 = 0,
WIFI_BW_HT40,
WIFI_BW_HT20 = 0, /* Bandwidth is HT20 */
WIFI_BW_HT40, /* Bandwidth is HT40 */
} wifi_bandwidth_t;
/**
* @brief Set the bandwidth of ESP32 specified interface
*
* @attention 1. API return false if try to configure a interface that is not enable
* @attention 2. WIFI_BW_HT40 is supported only when the interface support 11N
*
* @param wifi_interface_t ifx : interface to be configured
* @param wifi_bandwidth_t bw : bandwidth
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_set_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t bw);
/**
* @brief Get the bandwidth of ESP32 specified interface
*
* @attention 1. API return false if try to get a interface that is not enable
*
* @param wifi_interface_t ifx : interface to be configured
* @param wifi_bandwidth_t *bw : store bandwidth of interface ifx
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_get_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t *bw);
/**
* @brief Set primary/second channel of ESP32
*
* @attention 1. This is a special API for sniffer
*
* @param uint8_t primary : for HT20, primary is the channel number, for HT40, primary is the primary channel
* @param wifi_second_chan_t second : for HT20, second is ignored, for HT40, second is the second channel
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_set_channel(uint8_t primary, wifi_second_chan_t second);
/**
* @brief Get the primary/second channel of ESP32
*
* @attention 1. API return false if try to get a interface that is not enable
*
* @param uint8_t *primary : store current primary channel
* @param wifi_second_chan_t *second : store current second channel
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_get_channel(uint8_t *primary, wifi_second_chan_t *second);
/**
* @brief Set country code
* The default value is WIFI_COUNTRY_CN
*
* @param wifi_country_t country : country type
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_set_country(wifi_country_t country);
/**
* @brief Get country code
*
* @param wifi_country_t country : store current country
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_get_country(wifi_country_t *country);
/**
* @brief Set MAC address of the ESP32 WiFi station or the soft-AP interface.
*
* @attention 1. This API can only be called when the interface is disabled
* @attention 2. ESP32 soft-AP and station have different MAC addresses, do not set them to be the same.
* - The bit0 of the first byte of ESP32 MAC address can not be 1. For example, the MAC address
* can set to be "1a:XX:XX:XX:XX:XX", but can not be "15:XX:XX:XX:XX:XX".
*
* @param wifi_interface_t ifx : interface
* @param uint8 mac[6]: the MAC address.
*
* @return true : succeed
* @return false : fail
*/
esp_err_t esp_wifi_set_mac(wifi_interface_t ifx, uint8_t mac[6]);
/**
* @brief Get mac of specified interface
*
* @param uint8_t mac[6] : store mac of this interface ifx
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_get_mac(wifi_interface_t ifx, uint8_t mac[6]);
/**
* @brief The RX callback function in the promiscuous mode.
*
* Each time a packet is received, the callback function will be called.
*
* @param void *buf : the data received
* @param uint16_t len : data length
*
* @return ESP_OK : succeed
* @return others : fail
*/
typedef void (* wifi_promiscuous_cb_t)(void *buf, uint16_t len);
/**
* @brief Register the RX callback function in the promiscuous mode.
*
* Each time a packet is received, the registered callback function will be called.
*
* @param wifi_promiscuous_cb_t cb : callback
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb_t cb);
/**
* @brief Enable the promiscuous mode.
*
* @param uint8 promiscuous : 0 - disable / 1 - enable
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_set_promiscuous(uint8_t enable);
/**
* @brief Get the promiscuous mode.
*
* @param uint8 *enable : store the current status of promiscuous mode
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_get_promiscuous(uint8_t *enable);
typedef struct {
@ -206,7 +567,7 @@ typedef struct {
wifi_auth_mode_t authmode; /**< Auth mode of ESP32 soft-AP. Do not support AUTH_WEP in soft-AP mode */
uint8_t ssid_hidden; /**< Broadcast SSID or not, default 0, broadcast the SSID */
uint8_t max_connection; /**< Max number of stations allowed to connect in, default 4, max 4 */
uint16_t beacon_interval; /**< Beacon interval, 100 ~ 60000 ms, default 100 */
uint16_t beacon_interval; /**< Beacon interval, 100 ~ 60000 ms, default 100 ms */
} wifi_ap_config_t;
typedef struct {
@ -217,12 +578,35 @@ typedef struct {
} wifi_sta_config_t;
typedef union {
wifi_ap_config_t ap;
wifi_sta_config_t sta;
wifi_ap_config_t ap; /**< configuration of AP */
wifi_sta_config_t sta; /**< configuration of STA */
} wifi_config_t;
/**
* @brief Set the configuration of the ESP32 STA or AP
*
* @attention 1. This API can be called only when specified interface is enabled, otherwise, API fail
* @attention 2. For station configuration, bssid_set needs to be 0; and it needs to be 1 only when users need to check the MAC address of the AP.
* @attention 3. ESP32 is limited to only one channel, so when in the soft-AP+station mode, the soft-AP will adjust its channel automatically to be the same as
* the channel of the ESP32 station.
*
* @param wifi_interface_t ifx : interface
* @param wifi_config_t *conf : station or soft-AP configuration
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_set_config(wifi_interface_t ifx, wifi_config_t *conf);
/**
* @brief Get configuration of specified interface
*
* @param wifi_interface_t ifx : interface
* @param wifi_config_t *conf : station or soft-AP configuration
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_get_config(wifi_interface_t ifx, wifi_config_t *conf);
struct station_info {
@ -230,23 +614,79 @@ struct station_info {
uint8_t bssid[6];
};
/**
* @brief Get STAs associated with soft-AP
*
* @attention SSC only API
*
* @param struct station_info **station : station list
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_get_station_list(struct station_info **station);
esp_err_t esp_wifi_free_station_list(void);
typedef enum {
WIFI_STORAGE_RAM,
WIFI_STORAGE_FLASH,
WIFI_STORAGE_FLASH, /**< all configuration will strore in both memory and flash */
WIFI_STORAGE_RAM, /**< all configuration will only store in the memory */
} wifi_storage_t;
/**
* @brief Set the WiFi API configuration storage type
*
* @attention 1. The default value is WIFI_STORAGE_FLASH
*
* @param wifi_storage_t storage : storage type
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_set_storage(wifi_storage_t storage);
typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void* eb);
/**
* @brief The WiFi RX callback function
*
* Each time the WiFi need to forward the packets to high layer, the callback function will be called
*
*/
typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void *eb);
/**
* @brief Set the WiFi RX callback
*
* @attention 1. Currently we support only one RX callback for each interface
*
* @param wifi_interface_t ifx : interface
* @param wifi_rxcb_t fn : WiFi RX callback
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_reg_rxcb(wifi_interface_t ifx, wifi_rxcb_t fn);
/**
* @brief Set auto connect
* The default value is true
*
* @attention 1.
*
* @param bool en : true - enable auto connect / false - disable auto connect
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_set_auto_connect(bool en);
/**
* @brief Get the auto connect flag
*
* @param bool *en : store current auto connect configuration
*
* @return ESP_OK : succeed
* @return others : fail
*/
esp_err_t esp_wifi_get_auto_connect(bool *en);
#ifdef __cplusplus

View File

@ -11,6 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ROM_AES_H_
#define _ROM_AES_H_
@ -21,6 +22,7 @@
extern "C" {
#endif
//TODO, add comment for aes apis
enum AES_BITS {
AES128,
AES192,
@ -32,8 +34,8 @@ void ets_aes_enable(void);
void ets_aes_disable(void);
void ets_aes_set_endian(bool key_word_swap, bool key_byte_swap,
bool in_word_swap, bool in_byte_swap,
bool out_word_swap, bool out_byte_swap);
bool in_word_swap, bool in_byte_swap,
bool out_word_swap, bool out_byte_swap);
bool ets_aes_setkey_enc(const uint8_t *key, enum AES_BITS bits);

View File

@ -11,6 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ROM_BIGINT_H_
#define _ROM_BIGINT_H_
@ -21,6 +22,7 @@
extern "C" {
#endif
//TODO: add comment here
void ets_bigint_enable(void);
void ets_bigint_disable(void);

View File

@ -11,6 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ROM_CACHE_H_
#define _ROM_CACHE_H_
@ -18,50 +19,126 @@
extern "C" {
#endif
//===========================================
// function : cache_init
// description: initialise cache mmu, mark all entries as invalid.
// conditions:
// Call Cache_Read_Disable() before calling this function.
// inputs:
// cpu_no is CPU number,0(PRO CPU) or 1(APP CPU),
// output: NONE
//===========================================
/** \defgroup uart_apis, uart configuration and communication related apis
* @brief uart apis
*/
/** @addtogroup uart_apis
* @{
*/
/**
* @brief Initialise cache mmu, mark all entries as invalid.
* Please do not call this function in your SDK application.
*
* @param int cpu_no : 0 for PRO cpu, 1 for APP cpu.
*
* @return None
*/
void mmu_init(int cpu_no);
//===========================================
// function : cache_flash_mmu_set
// description: Configure MMU to cache a flash region.
// conditions:
// Call this function to configure the flash cache before enabling it.
// Check return value to verify MMU was set correctly.
// inputs:
// cpu_no is CPU number,0(PRO CPU) or 1(APP CPU),
// pid is process identifier. Range 0~7
// vaddr is "virtual" address in CPU address space. Can be IRam0, IRam1, IRom0 and DRom0 memory address.
// Should be aligned by psize
// paddr is "physical" address in flash controller's address space.
// ie for 16M flash the range is 0x000000~0xFFFFFF. Should be aligned by psize
// psize is page size of flash, in kilobytes. Can be 64, 32, 16.
// num is number of pages to be set, valid range 0 ~ (flash size)/(page size)
// output: error status
// 0 : mmu set success
// 1 : vaddr or paddr is not aligned
// 2 : pid error
// 3 : psize error
// 4 : mmu table to be written is out of range
// 5 : vaddr is out of range
//===========================================
/**
* @brief Set Flash-Cache mmu mapping.
* Please do not call this function in your SDK application.
*
* @param int cpu_no : CPU number, 0 for PRO cpu, 1 for APP cpu.
*
* @param int pod : process identifier. Range 0~7.
*
* @param unsigned int vaddr : virtual address in CPU address space.
* Can be IRam0, IRam1, IRom0 and DRom0 memory address.
* Should be aligned by psize.
*
* @param unsigned int paddr : physical address in Flash.
* Should be aligned by psize.
*
* @param int psize : page size of flash, in kilobytes. Should be 64 here.
*
* @param int num : pages to be set.
*
* @return unsigned int: error status
* 0 : mmu set success
* 1 : vaddr or paddr is not aligned
* 2 : pid error
* 3 : psize error
* 4 : mmu table to be written is out of range
* 5 : vaddr is out of range
*/
unsigned int cache_flash_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num);
unsigned int cache_sram_mmu_set(int cpu_no, int pid,unsigned int vaddr, unsigned int paddr, int psize, int num);
/**
* @brief Set Ext-SRAM-Cache mmu mapping.
* Please do not call this function in your SDK application.
*
* @param int cpu_no : CPU number, 0 for PRO cpu, 1 for APP cpu.
*
* @param int pod : process identifier. Range 0~7.
*
* @param unsigned int vaddr : virtual address in CPU address space.
* Can be IRam0, IRam1, IRom0 and DRom0 memory address.
* Should be aligned by psize.
*
* @param unsigned int paddr : physical address in Ext-SRAM.
* Should be aligned by psize.
*
* @param int psize : page size of flash, in kilobytes. Should be 32 here.
*
* @param int num : pages to be set.
*
* @return unsigned int: error status
* 0 : mmu set success
* 1 : vaddr or paddr is not aligned
* 2 : pid error
* 3 : psize error
* 4 : mmu table to be written is out of range
* 5 : vaddr is out of range
*/
unsigned int cache_sram_mmu_set(int cpu_no, int pid, unsigned int vaddr, unsigned int paddr, int psize, int num);
/**
* @brief Initialise cache access for the cpu.
* Please do not call this function in your SDK application.
*
* @param int cpu_no : 0 for PRO cpu, 1 for APP cpu.
*
* @return None
*/
void Cache_Read_Init(int cpu_no);
/**
* @brief Flush the cache value for the cpu.
* Please do not call this function in your SDK application.
*
* @param int cpu_no : 0 for PRO cpu, 1 for APP cpu.
*
* @return None
*/
void Cache_Flush(int cpu_no);
/**
* @brief Disable Cache access for the cpu.
* Please do not call this function in your SDK application.
*
* @param int cpu_no : 0 for PRO cpu, 1 for APP cpu.
*
* @return None
*/
void Cache_Read_Disable(int cpu_no);
/**
* @brief Enable Cache access for the cpu.
* Please do not call this function in your SDK application.
*
* @param int cpu_no : 0 for PRO cpu, 1 for APP cpu.
*
* @return None
*/
void Cache_Read_Enable(int cpu_no);
/**
* @}
*/
#ifdef __cplusplus
}
#endif

View File

@ -11,20 +11,113 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ROM_CRC_H
#define ROM_CRC_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup uart_apis, uart configuration and communication related apis
* @brief uart apis
*/
/** @addtogroup uart_apis
* @{
*/
/* Standard CRC8/16/32 algorithms. */
uint32_t crc32_le(uint32_t crc, uint8_t const * buf, uint32_t len);
uint32_t crc32_be(uint32_t crc, uint8_t const * buf, uint32_t len);
uint16_t crc16_le(uint16_t crc, uint8_t const * buf, uint32_t len);
uint16_t crc16_be(uint16_t crc, uint8_t const * buf, uint32_t len);
uint8_t crc8_le(uint8_t crc, uint8_t const * buf, uint32_t len);
uint8_t crc8_be(uint8_t crc, uint8_t const * buf, uint32_t len);
// CRC-8 x8+x2+x1+1 0x07
// CRC16-CCITT x16+x12+x5+1 1021 ISO HDLC, ITU X.25, V.34/V.41/V.42, PPP-FCS
// CRC32:
//G(x) = x32 +x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x1 + 1
//If your buf is not continuous, you can use the first result to be the second parameter.
/**
* @brief Crc32 value that is in little endian.
*
* @param uint32_t crc : init crc value, use 0 at the first use.
*
* @param uint8_t const *buf : buffer to start calculate crc.
*
* @param uint32_t len : buffer length in byte.
*
* @return None
*/
uint32_t crc32_le(uint32_t crc, uint8_t const *buf, uint32_t len);
/**
* @brief Crc32 value that is in big endian.
*
* @param uint32_t crc : init crc value, use 0 at the first use.
*
* @param uint8_t const *buf : buffer to start calculate crc.
*
* @param uint32_t len : buffer length in byte.
*
* @return None
*/
uint32_t crc32_be(uint32_t crc, uint8_t const *buf, uint32_t len);
/**
* @brief Crc16 value that is in little endian.
*
* @param uint16_t crc : init crc value, use 0 at the first use.
*
* @param uint8_t const *buf : buffer to start calculate crc.
*
* @param uint32_t len : buffer length in byte.
*
* @return None
*/
uint16_t crc16_le(uint16_t crc, uint8_t const *buf, uint32_t len);
/**
* @brief Crc16 value that is in big endian.
*
* @param uint16_t crc : init crc value, use 0 at the first use.
*
* @param uint8_t const *buf : buffer to start calculate crc.
*
* @param uint32_t len : buffer length in byte.
*
* @return None
*/
uint16_t crc16_be(uint16_t crc, uint8_t const *buf, uint32_t len);
/**
* @brief Crc8 value that is in little endian.
*
* @param uint8_t crc : init crc value, use 0 at the first use.
*
* @param uint8_t const *buf : buffer to start calculate crc.
*
* @param uint32_t len : buffer length in byte.
*
* @return None
*/
uint8_t crc8_le(uint8_t crc, uint8_t const *buf, uint32_t len);
/**
* @brief Crc8 value that is in big endian.
*
* @param uint32_t crc : init crc value, use 0 at the first use.
*
* @param uint8_t const *buf : buffer to start calculate crc.
*
* @param uint32_t len : buffer length in byte.
*
* @return None
*/
uint8_t crc8_be(uint8_t crc, uint8_t const *buf, uint32_t len);
/**
* @}
*/
#ifdef __cplusplus
}

View File

@ -11,17 +11,100 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ROM_EFUSE_H_
#define _ROM_EFUSE_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup efuse_APIs efuse APIs
* @brief ESP32 efuse read/write APIs
* @attention
*
*/
/** @addtogroup efuse_APIs
* @{
*/
/**
* @brief Do a efuse read operation, to update the efuse value to efuse read registers.
*
* @param null
*
* @return null
*/
void ets_efuse_read_op(void);
/**
* @brief Do a efuse write operation, to update efuse write registers to efuse, then you need call ets_efuse_read_op again.
*
* @param null
*
* @return null
*/
void ets_efuse_program_op(void);
/**
* @brief Read 8M Analog Clock value(8 bit) in efuse, the analog clock will not change with temperature.
* It can be used to test the external xtal frequency, do not touch this efuse field.
*
* @param null
*
* @return u32: 1 for 100KHZ, range is 0 to 255.
*/
uint32_t ets_efuse_get_8M_clock(void);
/**
* @brief Read spi pad configuration, show gpio number of flash pad, includes 5 pads.
*
* @param null
*
* @return uint32_t: 0, invalid, flash pad decided by strapping
* else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd
*/
uint32_t ets_efuse_get_spiconfig(void);
#define EFUSE_SPICONFIG_RET_SPICLK_MASK 0x3f
#define EFUSE_SPICONFIG_RET_SPICLK_SHIFT 0
#define EFUSE_SPICONFIG_RET_SPICLK(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPICLK_SHIFT) & EFUSE_SPICONFIG_RET_SPICLK_MASK)
#define EFUSE_SPICONFIG_RET_SPIQ_MASK 0x3f
#define EFUSE_SPICONFIG_RET_SPIQ_SHIFT 6
#define EFUSE_SPICONFIG_RET_SPIQ(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPIQ_SHIFT) & EFUSE_SPICONFIG_RET_SPIQ_MASK)
#define EFUSE_SPICONFIG_RET_SPID_MASK 0x3f
#define EFUSE_SPICONFIG_RET_SPID_SHIFT 12
#define EFUSE_SPICONFIG_RET_SPID(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPID_SHIFT) & EFUSE_SPICONFIG_RET_SPID_MASK)
#define EFUSE_SPICONFIG_RET_SPICS0_MASK 0x3f
#define EFUSE_SPICONFIG_RET_SPICS0_SHIFT 18
#define EFUSE_SPICONFIG_RET_SPICS0(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPICS0_SHIFT) & EFUSE_SPICONFIG_RET_SPICS0_MASK)
#define EFUSE_SPICONFIG_RET_SPIHD_MASK 0x3f
#define EFUSE_SPICONFIG_RET_SPIHD_SHIFT 24
#define EFUSE_SPICONFIG_RET_SPIHD(ret) (((ret) >> EFUSE_SPICONFIG_RET_SPIHD_SHIFT) & EFUSE_SPICONFIG_RET_SPIHD_MASK)
/**
* @brief A crc8 algorithm used in efuse check.
*
* @param unsigned char const *p : Pointer to original data.
*
* @param unsigned int len : Data length in byte.
*
* @return unsigned char: Crc value.
*/
unsigned char esp_crc8(unsigned char const *p, unsigned int len);
/**
* @}
*/
#ifdef __cplusplus
}
#endif

View File

@ -24,82 +24,242 @@
extern "C" {
#endif
#define ETS_DEBUG
#define ETS_SERIAL_ENABLED() (1)
/** \defgroup ets_sys_apis, ets system related apis
* @brief ets system apis
*/
/** @addtogroup ets_sys_apis
* @{
*/
/************************************************************************
* NOTE
* Many functions in this header files can't be run in FreeRTOS.
* Please see the comment of the Functions.
* There are also some functions that doesn't work on FreeRTOS
* without listed in the header, such as:
* xtos functions start with "_xtos_" in ld file.
*
***********************************************************************
*/
/** \defgroup ets_apis, Espressif Task Scheduler related apis
* @brief ets apis
*/
/** @addtogroup ets_apis
* @{
*/
typedef enum {
ETS_OK = 0,
ETS_FAILED = 1
ETS_OK = 0, /**< return successful in ets*/
ETS_FAILED = 1 /**< return failed in ets*/
} ETS_STATUS;
typedef uint32_t ETSSignal;
typedef uint32_t ETSParam;
typedef struct ETSEventTag ETSEvent;
typedef struct ETSEventTag ETSEvent; /**< Event transmit/receive in ets*/
struct ETSEventTag {
ETSSignal sig;
ETSParam par;
ETSSignal sig; /**< Event signal, in same task, different Event with different signal*/
ETSParam par; /**< Event parameter, sometimes without usage, then will be set as 0*/
};
typedef void (*ETSTask)(ETSEvent *e);
enum ETS_User_Priorities {
/* task priorities... */
TICK_TASK_A_PRIO = 2,
KBD_TASK_PRIO = 5,
MAX_ETS_USER_PRIO = 16,
/* ISR priorities... */
MAX_ETS_USER_ISR_PRIO = 0xFF - 16
};
/* ETS interrupt entry and exit */
/* actually we don't need the following 2 macros any more since we won't exit
* isr until it is finised, more over, we don't do nest interrupt
*/
typedef void (*ETSTask)(ETSEvent *e); /**< Type of the Task processer*/
typedef void (* ets_idle_cb_t)(void *arg); /**< Type of the system idle callback*/
/**
* @brief Start the Espressif Task Scheduler, which is an infinit loop. Please do not add code after it.
*
* @param none
*
* @return none
*/
void ets_run(void);
/**
* @brief Set the Idle callback, when Tasks are processed, will call the callback before CPU goto sleep.
*
* @param ets_idle_cb_t func : The callback function.
*
* @param void *arg : Argument of the callback.
*
* @return None
*/
void ets_set_idle_cb(ets_idle_cb_t func, void *arg);
/**
* @brief Init a task with processer, priority, queue to receive Event, queue length.
*
* @param ETSTask task : The task processer.
*
* @param uint8_t prio : Task priority, 0-31, bigger num with high priority, one priority with one task.
*
* @param ETSEvent *queue : Queue belongs to the task, task always receives Events, Queue is circular used.
*
* @param uint8_t qlen : Queue length.
*
* @return None
*/
void ets_task(ETSTask task, uint8_t prio, ETSEvent *queue, uint8_t qlen);
ETS_STATUS ets_post(uint8_t prio, ETSSignal sig, ETSParam par);
/**
* @brief Post an event to an Task.
*
* @param uint8_t prio : Priority of the Task.
*
* @param ETSSignal sig : Event signal.
*
* @param ETSParam par : Event parameter
*
* @return ETS_OK : post successful
* @return ETS_FAILED : post failed
*/
ETS_STATUS ets_post(uint8_t prio, ETSSignal sig, ETSParam par);
/*
* now things become complicated, print could be directed to uart and/or SDIO
*/
/**
* @}
*/
/** \defgroup ets_boot_apis, Boot routing related apis
* @brief ets boot apis
*/
/** @addtogroup ets_apis
* @{
*/
extern const char *const exc_cause_table[40]; ///**< excption cause that defined by the core.*/
/**
* @brief Set Pro cpu Entry code, code can be called in PRO CPU when booting is not completed.
* When Pro CPU booting is completed, Pro CPU will call the Entry code if not NULL.
*
* @param uint32_t start : the PRO Entry code address value in uint32_t
*
* @return None
*/
void ets_set_user_start(uint32_t start);
/**
* @brief Set Pro cpu Startup code, code can be called when booting is not completed, or in Entry code.
* When Entry code completed, CPU will call the Startup code if not NULL, else call ets_run.
*
* @param uint32_t callback : the Startup code address value in uint32_t
*
* @return None : post successful
*/
void ets_set_startup_callback(uint32_t callback);
/**
* @brief Set App cpu Entry code, code can be called in PRO CPU.
* When APP booting is completed, APP CPU will call the Entry code if not NULL.
*
* @param uint32_t start : the APP Entry code address value in uint32_t, stored in register APPCPU_CTRL_REG_D.
*
* @return None
*/
void ets_set_appcpu_boot_addr(uint32_t start);
/**
* @brief unpack the image in flash to iram and dram, no using cache.
*
* @param uint32_t pos : Flash physical address.
*
* @param uint32_t *entry_addr: the pointer of an variable that can store Entry code address.
*
* @param bool jump : Jump into the code in the function or not.
*
* @param bool config : Config the flash when unpacking the image, config should be done only once.
*
* @return ETS_OK : unpack successful
* @return ETS_FAILED : unpack failed
*/
ETS_STATUS ets_unpack_flash_code_legacy(uint32_t pos, uint32_t *entry_addr, bool jump, bool config);
/**
* @brief unpack the image in flash to iram and dram, using cache, maybe decrypting.
*
* @param uint32_t pos : Flash physical address.
*
* @param uint32_t *entry_addr: the pointer of an variable that can store Entry code address.
*
* @param bool jump : Jump into the code in the function or not.
*
* @param bool sb_need_check : Do security boot check or not.
*
* @param bool config : Config the flash when unpacking the image, config should be done only once.
*
* @return ETS_OK : unpack successful
* @return ETS_FAILED : unpack failed
*/
ETS_STATUS ets_unpack_flash_code(uint32_t pos, uint32_t *entry_addr, bool jump, bool sb_need_check, bool config);
/**
* @}
*/
/** \defgroup ets_printf_apis, ets_printf related apis used in ets
* @brief ets printf apis
*/
/** @addtogroup ets_printf_apis
* @{
*/
/**
* @brief Printf the strings to uart or other devices, similar with printf, simple than printf.
* Can not print float point data format, or longlong data format.
* So we maybe only use this in ROM.
*
* @param const char *fmt : See printf.
*
* @param ... : See printf.
*
* @return int : the length printed to the output device.
*/
int ets_printf(const char *fmt, ...);
/* by default it's UART, just install_uart_printf, set putc1 to NULL to disable */
/**
* @brief Output a char to uart, which uart to output(which is in uart module in ROM) is not in scope of the function.
* Can not print float point data format, or longlong data format
*
* @param char c : char to output.
*
* @return None
*/
void ets_write_char_uart(char c);
/**
* @brief Ets_printf have two output functions putc1 and putc2, both of which will be called if need ouput.
* To install putc1, which is defaulted installed as ets_write_char_uart in none silent boot mode, as NULL in silent mode.
*
* @param void (*)(char) p: Output function to install.
*
* @return None
*/
void ets_install_putc1(void (*p)(char c));
void ets_install_uart_printf(void);
/* no need to install, call directly */
int ets_uart_printf(const char *fmt, ...);
/* usually we don't need to call this, unless we want to disable SDIO print */
/**
* @brief Ets_printf have two output functions putc1 and putc2, both of which will be called if need ouput.
* To install putc2, which is defaulted installed as NULL.
*
* @param void (*)(char) p: Output function to install.
*
* @return None
*/
void ets_install_putc2(void (*p)(char c));
/* @prepare_buf: allocate buffer for printf internal writting
* @putc: just set to NULL, let printf write to to buffer, unless if you want more fancy stuff
* @post_printf: will be called every time printf finish write buffer
*
* main idea of external printf is re-directing content to an external buffer.
* e.g. sip module allocates an event buffer in prepare_buf() and send the event to host in post_printf()
* moreover, you can check printf_buf_remain_len in post_printf(), send the event to host till buf is
* about to full.
*
* TBD: Another approach is sending printf parameter to host and let host to decode, which could save some bytes.
*/
void ets_install_external_printf(void (*prepare_buf)(char ** bufptr, uint16_t *buflen, uint32_t *cookie),
void (*putc)(char c),
void (*post_printf)(uint32_t cookie));
uint16_t est_get_printf_buf_remain_len(void);
void est_reset_printf_buf_len(void);
/* external (SDIO) printf only, still need to install*/
int ets_external_printf(const char *fmt, ...);
/**
* @brief Install putc1 as ets_write_char_uart.
* In silent boot mode(to void interfere the UART attached MCU), we can call this function, after booting ok.
*
* @param None
*
* @return None
*/
void ets_install_uart_printf(void);
#define ETS_PRINTF(...) ets_printf(...)
@ -110,82 +270,251 @@ int ets_external_printf(const char *fmt, ...);
} \
} while (0);
/* memory and string support */
int8_t ets_char2xdigit(char ch);
uint8_t * ets_str2macaddr(uint8_t *macaddr, char *str);
void ets_getc(char *c);
void ets_putc(char c);
/**
* @}
*/
/* timer related */
typedef uint32_t ETSHandle;
typedef void ETSTimerFunc(void *timer_arg);
/** \defgroup ets_timer_apis, ets_timer related apis used in ets
* @brief ets timer apis
*/
/** @addtogroup ets_timer_apis
* @{
*/
typedef void ETSTimerFunc(void *timer_arg);/**< timer handler*/
typedef struct _ETSTIMER_ {
struct _ETSTIMER_ *timer_next;
uint32_t timer_expire;
uint32_t timer_period;
ETSTimerFunc *timer_func;
void *timer_arg;
struct _ETSTIMER_ *timer_next; /**< timer linker*/
uint32_t timer_expire; /**< abstruct time when timer expire*/
uint32_t timer_period; /**< timer period, 0 means timer is not periodic repeated*/
ETSTimerFunc *timer_func; /**< timer handler*/
void *timer_arg; /**< timer handler argument*/
} ETSTimer;
/**
* @brief Init ets timer, this timer range is 640 us to 429496 ms
* In FreeRTOS, please call FreeRTOS apis, never call this api.
*
* @param None
*
* @return None
*/
void ets_timer_init(void);
/**
* @brief Arm an ets timer, this timer range is 640 us to 429496 ms.
* In FreeRTOS, please call FreeRTOS apis, never call this api.
*
* @param ETSTimer *timer : Timer struct pointer.
*
* @param uint32_t tmout : Timer value in ms, range is 1 to 429496.
*
* @param bool repeat : Timer is periodic repeated.
*
* @return None
*/
void ets_timer_arm(ETSTimer *timer, uint32_t tmout, bool repeat);
/**
* @brief Arm an ets timer, this timer range is 640 us to 429496 ms.
* In FreeRTOS, please call FreeRTOS apis, never call this api.
*
* @param ETSTimer *timer : Timer struct pointer.
*
* @param uint32_t tmout : Timer value in us, range is 1 to 429496729.
*
* @param bool repeat : Timer is periodic repeated.
*
* @return None
*/
void ets_timer_arm_us(ETSTimer *ptimer, uint32_t us, bool repeat);
/**
* @brief Disarm an ets timer.
* In FreeRTOS, please call FreeRTOS apis, never call this api.
*
* @param ETSTimer *timer : Timer struct pointer.
*
* @return None
*/
void ets_timer_disarm(ETSTimer *timer);
void ets_timer_done(ETSTimer *ptimer);
/**
* @brief Set timer callback and argument.
* In FreeRTOS, please call FreeRTOS apis, never call this api.
*
* @param ETSTimer *timer : Timer struct pointer.
*
* @param ETSTimerFunc *pfunction : Timer callback.
*
* @param void *parg : Timer callback argument.
*
* @return None
*/
void ets_timer_setfn(ETSTimer *ptimer, ETSTimerFunc *pfunction, void *parg);
/* watchdog related */
typedef enum {
WDT_NONE = -1,
WDT_DISABLED = 0,
WDT_CONTROL_RESET = 1,
WDT_CONTROL_INTR = 2, /* usually we use this mode? */
WDT_CONTROL_EXTERNAL_FEED = 3,
WDT_TESET_OVERFLOW = 4, // intend to make watchdog overflow to test
} WDT_MODE;
/**
* @brief Unset timer callback and argument to NULL.
* In FreeRTOS, please call FreeRTOS apis, never call this api.
*
* @param ETSTimer *timer : Timer struct pointer.
*
* @return None
*/
void ets_timer_done(ETSTimer *ptimer);
typedef enum{
WDT_INTERVAL_THREE_SEC = 3,
WDT_INTERVAL_SIX_SEC = 6,
WDT_INTERVAL_TWELVE_SEC = 12,
} WDT_INTERVAL_TIME;
/**
* @brief CPU do while loop for some time.
* In FreeRTOS task, please call FreeRTOS apis.
*
* @param uint32_t us : Delay time in us.
*
* @return None
*/
void ets_delay_us(uint32_t us);
void ets_wdt_init(void);
WDT_MODE ets_wdt_get_mode(void);
void ets_wdt_enable(WDT_MODE mode, WDT_INTERVAL_TIME feed_interval,
WDT_INTERVAL_TIME expire_interval);
WDT_MODE ets_wdt_disable(void);
void ets_wdt_restore(WDT_MODE old_mode);
/**
* @brief Set the real CPU ticks per us to the ets, so that ets_delay_us will be accurate.
* Call this function when CPU frequency is changed.
*
* @param uint32_t ticks_per_us : CPU ticks per us.
*
* @return None
*/
void ets_update_cpu_frequency(uint32_t ticks_per_us);
/* interrupt related */
typedef void (* ets_isr_t)(void *);
/**
* @brief Get the real CPU ticks per us to the ets.
* This function do not return real CPU ticks per us, just the record in ets. It can be used to check with the real CPU frequency.
*
* @param None
*
* @return uint32_t : CPU ticks per us record in ets.
*/
uint32_t ets_get_cpu_frequency(void);
#define ETS_WMAC_SOURCE 0
#define ETS_SLC_SOURCE 1
#define ETS_UART_SOURCE 13
#define ETS_UART1_SOURCE 14
#define ETS_FRC_TIMER2_SOURCE 43
/**
* @brief Get xtal_freq/analog_8M*256 value calibrated in rtc module.
*
* @param None
*
* @return uint32_t : xtal_freq/analog_8M*256.
*/
uint32_t ets_get_xtal_scale(void);
#define ETS_WMAC_INUM 0
#define ETS_SLC_INUM 1
#define ETS_SPI_INUM 2
#define ETS_HSIP_INUM 2
#define ETS_I2S_INUM 2
#define ETS_RTC_INUM 3
#define ETS_FRC_TIMER1_INUM 9 /* use edge*/
#define ETS_FRC_TIMER2_INUM 10 /* use edge*/
#define ETS_WDT_INUM 8 /* use edge*/
#define ETS_GPIO_INUM 4
#define ETS_UART_INUM 5
#define ETS_UART1_INUM 5
#define ETS_MAX_INUM 6
/**
* @brief Get xtal_freq value, If value not stored in RTC_STORE5, than store.
*
* @param None
*
* @return uint32_t : if rtc store the value (RTC_STORE5 high 16 bits and low 16 bits with same value), read from rtc register.
* clock = (REG_READ(RTC_STORE5) & 0xffff) << 12;
* else if analog_8M in efuse
* clock = ets_get_xtal_scale() * 15625 * ets_efuse_get_8M_clock() / 40;
* else clock = 26M.
*/
uint32_t ets_get_detected_xtal_freq(void);
/**
* @}
*/
/** \defgroup ets_intr_apis, ets interrupt configure related apis
* @brief ets intr apis
*/
/** @addtogroup ets_intr_apis
* @{
*/
typedef void (* ets_isr_t)(void *);/**< interrupt handler type*/
/**
* @brief Attach a interrupt handler to a CPU interrupt number.
* This function equals to _xtos_set_interrupt_handler_arg(i, func, arg).
* In FreeRTOS, please call FreeRTOS apis, never call this api.
*
* @param int i : CPU interrupt number.
*
* @param ets_isr_t func : Interrupt handler.
*
* @param void *arg : argument of the handler.
*
* @return None
*/
void ets_isr_attach(int i, ets_isr_t func, void *arg);
/**
* @brief Mask the interrupts which show in mask bits.
* This function equals to _xtos_ints_off(mask).
* In FreeRTOS, please call FreeRTOS apis, never call this api.
*
* @param uint32_t mask : BIT(i) means mask CPU interrupt number i.
*
* @return None
*/
void ets_isr_mask(uint32_t mask);
/**
* @brief Unmask the interrupts which show in mask bits.
* This function equals to _xtos_ints_on(mask).
* In FreeRTOS, please call FreeRTOS apis, never call this api.
*
* @param uint32_t mask : BIT(i) means mask CPU interrupt number i.
*
* @return None
*/
void ets_isr_unmask(uint32_t unmask);
/**
* @brief Lock the interrupt to level 2.
* This function direct set the CPU registers.
* In FreeRTOS, please call FreeRTOS apis, never call this api.
*
* @param None
*
* @return None
*/
void ets_intr_lock(void);
/**
* @brief Unlock the interrupt to level 0.
* This function direct set the CPU registers.
* In FreeRTOS, please call FreeRTOS apis, never call this api.
*
* @param None
*
* @return None
*/
void ets_intr_unlock(void);
/**
* @brief Unlock the interrupt to level 0, and CPU will go into power save mode(wait interrupt).
* This function direct set the CPU registers.
* In FreeRTOS, please call FreeRTOS apis, never call this api.
*
* @param None
*
* @return None
*/
void ets_waiti0(void);
/**
* @brief Attach an CPU interrupt to a hardware source.
* We have 4 steps to use an interrupt:
* 1.Attach hardware interrupt source to CPU. intr_matrix_set(0, ETS_WIFI_MAC_INTR_SOURCE, ETS_WMAC_INUM);
* 2.Set interrupt handler. xt_set_interrupt_handler(ETS_WMAC_INUM, func, NULL);
* 3.Enable interrupt for CPU. xt_ints_on(1 << ETS_WMAC_INUM);
* 4.Enable interrupt in the module.
*
* @param int cpu_no : The CPU which the interrupt number belongs.
*
* @param uint32_t model_num : The interrupt hardware source number, please see the interrupt hardware source table.
*
* @param uint32_t intr_num : The interrupt number CPU, please see the interrupt cpu using table.
*
* @return None
*/
void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num);
#define _ETSTR(v) # v
@ -194,126 +523,80 @@ void intr_matrix_set(int cpu_no, uint32_t model_num, uint32_t intr_num);
: "=a" (__tmp) : : "memory" ); \
})
#ifdef CONFIG_NONE_OS
#define ETS_INTR_LOCK() \
ets_intr_lock()
ets_intr_lock()
#define ETS_INTR_UNLOCK() \
ets_intr_unlock()
#define ETS_CCOMPARE_INTR_ATTACH(func, arg) \
ets_isr_attach(ETS_CCOMPARE_INUM, (func), (void *)(arg))
#define ETS_PWM_INTR_ATTACH(func, arg) \
ets_isr_attach(ETS_PWM_INUM, (func), (void *)(arg))
#define ETS_WMAC_INTR_ATTACH(func, arg) \
ets_isr_attach(ETS_WMAC_INUM, (func), (void *)(arg))
#define ETS_FRC_TIMER1_INTR_ATTACH(func, arg) \
ets_isr_attach(ETS_FRC_TIMER1_INUM, (func), (void *)(arg))
#define ETS_FRC_TIMER2_INTR_ATTACH(func, arg) \
ets_isr_attach(ETS_FRC_TIMER2_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_WDT_INTR_ATTACH(func, arg) \
ets_isr_attach(ETS_WDT_INUM, (func), (void *)(arg))
#define ETS_RTC_INTR_ATTACH(func, arg) \
ets_isr_attach(ETS_RTC_INUM, (func), (void *)(arg))
#define ETS_SLC_INTR_ATTACH(func, arg) \
ets_isr_attach(ETS_SLC_INUM, (func), (void *)(arg))
ets_intr_unlock()
#define ETS_ISR_ATTACH \
ets_isr_attach
#define ETS_INTR_ENABLE(inum) \
xt_ints_on((1<<inum))
ets_isr_unmask((1<<inum))
#define ETS_INTR_DISABLE(inum) \
xt_ints_off((1<<inum))
ets_isr_mask((1<<inum))
#define ETS_CCOMPARE_INTR_ENBALE() \
ETS_INTR_ENABLE(ETS_CCOMPARE_INUM)
#define ETS_WMAC_INTR_ATTACH(func, arg) \
ETS_ISR_ATTACH(ETS_WMAC_INUM, (func), (void *)(arg))
#define ETS_CCOMPARE_INTR_DISBALE() \
ETS_INTR_DISABLE(ETS_CCOMPARE_INUM)
#define ETS_TG0_T0_INTR_ATTACH(func, arg) \
ETS_ISR_ATTACH(ETS_TG0_T0_INUM, (func), (void *)(arg))
#define ETS_PWM_INTR_ENABLE() \
ETS_INTR_ENABLE(ETS_PWM_INUM)
#define ETS_GPIO_INTR_ATTACH(func, arg) \
ETS_ISR_ATTACH(ETS_GPIO_INUM, (func), (void *)(arg))
#define ETS_PWM_INTR_DISABLE() \
ETS_INTR_DISABLE(ETS_PWM_INUM)
#define ETS_UART0_INTR_ATTACH(func, arg) \
ETS_ISR_ATTACH(ETS_UART0_INUM, (func), (void *)(arg))
#define ETS_WDT_INTR_ATTACH(func, arg) \
ETS_ISR_ATTACH(ETS_WDT_INUM, (func), (void *)(arg))
#define ETS_SLC_INTR_ATTACH(func, arg) \
ETS_ISR_ATTACH(ETS_SLC_INUM, (func), (void *)(arg))
#define ETS_BB_INTR_ENABLE() \
ETS_INTR_ENABLE(ETS_BB_INUM)
ETS_INTR_ENABLE(ETS_BB_INUM)
#define ETS_BB_INTR_DISABLE() \
ETS_INTR_DISABLE(ETS_BB_INUM)
ETS_INTR_DISABLE(ETS_BB_INUM)
#define ETS_UART_INTR_ENABLE() \
ETS_INTR_ENABLE(ETS_UART_INUM)
#define ETS_UART0_INTR_ENABLE() \
ETS_INTR_ENABLE(ETS_UART0_INUM)
#define ETS_UART_INTR_DISABLE() \
ETS_INTR_DISABLE(ETS_UART_INUM)
#define ETS_UART0_INTR_DISABLE() \
ETS_INTR_DISABLE(ETS_UART0_INUM)
#define ETS_GPIO_INTR_ENABLE() \
ETS_INTR_ENABLE(ETS_GPIO_INUM)
ETS_INTR_ENABLE(ETS_GPIO_INUM)
#define ETS_GPIO_INTR_DISABLE() \
ETS_INTR_DISABLE(ETS_GPIO_INUM)
ETS_INTR_DISABLE(ETS_GPIO_INUM)
#define ETS_WDT_INTR_ENABLE() \
ETS_INTR_ENABLE(ETS_WDT_INUM)
ETS_INTR_ENABLE(ETS_WDT_INUM)
#define ETS_WDT_INTR_DISABLE() \
ETS_INTR_DISABLE(ETS_WDT_INUM)
ETS_INTR_DISABLE(ETS_WDT_INUM)
#define ETS_FRC1_INTR_ENABLE() \
ETS_INTR_ENABLE(ETS_FRC_TIMER1_INUM)
#define ETS_TG0_T0_INTR_ENABLE() \
ETS_INTR_ENABLE(ETS_TG0_T0_INUM)
#define ETS_FRC1_INTR_DISABLE() \
ETS_INTR_DISABLE(ETS_FRC_TIMER1_INUM)
#define ETS_FRC2_INTR_ENABLE() \
ETS_INTR_ENABLE(ETS_FRC_TIMER2_INUM)
#define ETS_FRC2_INTR_DISABLE() \
ETS_INTR_DISABLE(ETS_FRC_TIMER2_INUM)
#define ETS_RTC_INTR_ENABLE() \
ETS_INTR_ENABLE(ETS_RTC_INUM)
#define ETS_RTC_INTR_DISABLE() \
ETS_INTR_DISABLE(ETS_RTC_INUM)
#define ETS_TG0_T0_INTR_DISABLE() \
ETS_INTR_DISABLE(ETS_TG0_T0_INUM)
#define ETS_SLC_INTR_ENABLE() \
ETS_INTR_ENABLE(ETS_SLC_INUM)
ETS_INTR_ENABLE(ETS_SLC_INUM)
#define ETS_SLC_INTR_DISABLE() \
ETS_INTR_DISABLE(ETS_SLC_INUM)
void ets_delay_us(uint32_t us);
void ets_update_cpu_frequency(uint32_t ticks_per_us);
uint32_t ets_get_xtal_scale();
uint32_t ets_get_detected_xtal_freq();
#if 0
#define isdigit(c) ((c >= '0') && (c <= '9'))
#define isxdigit(c) (((c >= '0') && (c <= '9')) || \
((c >= 'a') && (c <= 'f')) || \
((c >= 'A') && (c <= 'F')) )
#define isblank(c) ((c == ' ') || (c == '\t'))
#define isupper(c) ((c >= 'A') && (c <= 'Z'))
ETS_INTR_DISABLE(ETS_SLC_INUM)
#endif
/**
* @}
*/
#ifndef MAC2STR
#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
@ -322,6 +605,10 @@ uint32_t ets_get_detected_xtal_freq();
#define ETS_MEM_BAR() asm volatile ( "" : : : "memory" )
/**
* @}
*/
#ifdef __cplusplus
}
#endif

View File

@ -25,6 +25,14 @@
extern "C" {
#endif
/** \defgroup gpio_apis, uart configuration and communication related apis
* @brief gpio apis
*/
/** @addtogroup gpio_apis
* @{
*/
#define GPIO_REG_READ(reg) READ_PERI_REG(reg)
#define GPIO_REG_WRITE(reg, val) WRITE_PERI_REG(reg, val)
#define GPIO_PIN_COUNT 40
@ -37,17 +45,14 @@ extern "C" {
#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_ANYEGDE = 3,
GPIO_PIN_INTR_LOLEVEL = 4,
GPIO_PIN_INTR_HILEVEL = 5
}GPIO_INT_TYPE;
#define GREEN_LED_ON() GPIO_OUTPUT_SET(GPIO_ID_PIN(1) , 0)
#define GREEN_LED_OFF() GPIO_OUTPUT_SET(GPIO_ID_PIN(1) , 1)
typedef enum {
GPIO_PIN_INTR_DISABLE = 0,
GPIO_PIN_INTR_POSEDGE = 1,
GPIO_PIN_INTR_NEGEDGE = 2,
GPIO_PIN_INTR_ANYEGDE = 3,
GPIO_PIN_INTR_LOLEVEL = 4,
GPIO_PIN_INTR_HILEVEL = 5
} GPIO_INT_TYPE;
#define GPIO_OUTPUT_SET(gpio_no, bit_value) \
((gpio_no < 32) ? gpio_output_set(bit_value<<gpio_no, (bit_value ? 0 : 1)<<gpio_no, 1<<gpio_no,0) : \
@ -58,82 +63,235 @@ typedef enum{
/* GPIO interrupt handler, registered through gpio_intr_handler_register */
typedef void (* gpio_intr_handler_fn_t)(uint32_t intr_mask, bool high, void *arg);
/**
* @brief Initialize GPIO. This includes reading the GPIO Configuration DataSet
* to initialize "output enables" and pin configurations for each gpio pin.
* Please do not call this function in SDK.
*
* @param None
*
* @return None
*/
void gpio_init(void);
/*
* 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.
*/
void gpio_init(void) ROMFN_ATTR;
/**
* @brief Change GPIO(0-31) pin output by setting, clearing, or disabling pins, GPIO0<->BIT(0).
* There is no particular ordering guaranteed; so if the order of writes is significant,
* calling code should divide a single call into multiple calls.
*
* @param uint32_t set_mask : the gpios that need high level.
*
* @param uint32_t clear_mask : the gpios that need low level.
*
* @param uint32_t enable_mask : the gpios that need be changed.
*
* @param uint32_t disable_mask : the gpios that need diable output.
*
* @return None
*/
void gpio_output_set(uint32_t set_mask, uint32_t clear_mask, uint32_t enable_mask, uint32_t disable_mask);
/*
* 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_t set_mask,
uint32_t clear_mask,
uint32_t enable_mask,
uint32_t disable_mask) ROMFN_ATTR;
void gpio_output_set_high(uint32_t set_mask,
uint32_t clear_mask,
uint32_t enable_mask,
uint32_t disable_mask) ROMFN_ATTR;
/*
* Sample the value of GPIO input pins and returns a bitmask.
*/
uint32_t gpio_input_get(void) ROMFN_ATTR;
uint32_t gpio_input_get_high(void) ROMFN_ATTR;
/**
* @brief Change GPIO(32-39) pin output by setting, clearing, or disabling pins, GPIO32<->BIT(0).
* There is no particular ordering guaranteed; so if the order of writes is significant,
* calling code should divide a single call into multiple calls.
*
* @param uint32_t set_mask : the gpios that need high level.
*
* @param uint32_t clear_mask : the gpios that need low level.
*
* @param uint32_t enable_mask : the gpios that need be changed.
*
* @param uint32_t disable_mask : the gpios that need diable output.
*
* @return None
*/
void gpio_output_set_high(uint32_t set_mask, uint32_t clear_mask, uint32_t enable_mask, uint32_t disable_mask);
/*
* 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_t reg_id, uint32_t value) ROMFN_ATTR;
/**
* @brief Sample the value of GPIO input pins(0-31) and returns a bitmask.
*
* @param None
*
* @return uint32_t : bitmask for GPIO input pins, BIT(0) for GPIO0.
*/
uint32_t gpio_input_get(void);
/* Get the current value of the specified GPIO register. */
uint32_t gpio_register_get(uint32_t reg_id) ROMFN_ATTR;
/**
* @brief Sample the value of GPIO input pins(32-39) and returns a bitmask.
*
* @param None
*
* @return uint32_t : bitmask for GPIO input pins, BIT(0) for GPIO32.
*/
uint32_t gpio_input_get_high(void);
/*
* 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) ROMFN_ATTR;
/**
* @brief 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.
* Please do not call this function in SDK.
*
* @param gpio_intr_handler_fn_t fn : gpio application-specific interrupt handler
*
* @param void *arg : gpio application-specific interrupt handler argument.
*
* @return None
*/
void gpio_intr_handler_register(gpio_intr_handler_fn_t fn, void *arg);
/* Determine which GPIO interrupts are pending. */
uint32_t gpio_intr_pending(void) ROMFN_ATTR;
uint32_t gpio_intr_pending_high(void) ROMFN_ATTR;
/**
* @brief Get gpio interrupts which happens but not processed.
* Please do not call this function in SDK.
*
* @param None
*
* @return uint32_t : bitmask for GPIO pending interrupts, BIT(0) for GPIO0.
*/
uint32_t gpio_intr_pending(void);
/*
* Acknowledge GPIO interrupts.
* Intended to be called from the gpio_intr_handler_fn.
*/
void gpio_intr_ack(uint32_t ack_mask) ROMFN_ATTR;
void gpio_intr_ack_high(uint32_t ack_mask) ROMFN_ATTR;
/**
* @brief Get gpio interrupts which happens but not processed.
* Please do not call this function in SDK.
*
* @param None
*
* @return uint32_t : bitmask for GPIO pending interrupts, BIT(0) for GPIO32.
*/
uint32_t gpio_intr_pending_high(void);
void gpio_pin_wakeup_enable(uint32_t i, GPIO_INT_TYPE intr_state) ROMFN_ATTR;
/**
* @brief Ack gpio interrupts to process pending interrupts.
* Please do not call this function in SDK.
*
* @param uint32_t ack_mask: bitmask for GPIO ack interrupts, BIT(0) for GPIO0.
*
* @return None
*/
void gpio_intr_ack(uint32_t ack_mask);
void gpio_pin_wakeup_disable() ROMFN_ATTR;
/**
* @brief Ack gpio interrupts to process pending interrupts.
* Please do not call this function in SDK.
*
* @param uint32_t ack_mask: bitmask for GPIO ack interrupts, BIT(0) for GPIO32.
*
* @return None
*/
void gpio_intr_ack_high(uint32_t ack_mask);
//extern void gpio_module_install(struct gpio_api *api);
/**
* @brief Set GPIO to wakeup the ESP32.
* Please do not call this function in SDK.
*
* @param uint32_t i: gpio number.
*
* @param GPIO_INT_TYPE intr_state : only GPIO_PIN_INTR_LOLEVEL\GPIO_PIN_INTR_HILEVEL can be used
*
* @return None
*/
void gpio_pin_wakeup_enable(uint32_t i, GPIO_INT_TYPE intr_state);
void gpio_matrix_in(uint32_t gpio, uint32_t signal_idx, bool inv) ROMFN_ATTR;
/**
* @brief disable GPIOs to wakeup the ESP32.
* Please do not call this function in SDK.
*
* @param None
*
* @return None
*/
void gpio_pin_wakeup_disable(void);
void gpio_matrix_out(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) ROMFN_ATTR;
/**
* @brief set gpio input to a signal, one gpio can input to several signals.
*
* @param uint32_t gpio : gpio number, 0~0x27
* gpio == 0x30, input 0 to signal
* gpio == 0x34, ???
* gpio == 0x38, input 1 to signal
*
* @param uint32_t signal_idx : signal index.
*
* @param bool inv : the signal is inv or not
*
* @return None
*/
void gpio_matrix_in(uint32_t gpio, uint32_t signal_idx, bool inv);
/**
* @brief set signal output to gpio, one signal can output to several gpios.
*
* @param uint32_t gpio : gpio number, 0~0x27
*
* @param uint32_t signal_idx : signal index.
* signal_idx == 0x100, cancel output put to the gpio
*
* @param bool out_inv : the signal output is inv or not
*
* @param bool oen_inv : the signal output enable is inv or not
*
* @return None
*/
void gpio_matrix_out(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv);
/**
* @brief Select pad as a gpio function from IOMUX.
*
* @param uint32_t gpio_num : gpio number, 0~0x27
*
* @return None
*/
void gpio_pad_select_gpio(uint8_t gpio_num);
/**
* @brief Set pad driver capability.
*
* @param uint32_t gpio_num : gpio number, 0~0x27
*
* @param uint8_t drv : 0-3
*
* @return None
*/
void gpio_pad_set_drv(uint8_t gpio_num, uint8_t drv);
/**
* @brief Pull up the pad from gpio number.
*
* @param uint32_t gpio_num : gpio number, 0~0x27
*
* @return None
*/
void gpio_pad_pullup(uint8_t gpio_num);
/**
* @brief Pull down the pad from gpio number.
*
* @param uint32_t gpio_num : gpio number, 0~0x27
*
* @return None
*/
void gpio_pad_pulldown(uint8_t gpio_num);
/**
* @brief Unhold the pad from gpio number.
*
* @param uint32_t gpio_num : gpio number, 0~0x27
*
* @return None
*/
void gpio_pad_unhold(uint8_t gpio_num);
/**
* @brief Hold the pad from gpio number.
*
* @param uint32_t gpio_num : gpio number, 0~0x27
*
* @return None
*/
void gpio_pad_hold(uint8_t gpio_num);
/**
* @}
*/
#ifdef __cplusplus
}

View File

@ -26,30 +26,68 @@
extern "C" {
#endif
/** \defgroup rtc_apis, rtc registers and memory related apis
* @brief rtc apis
*/
/** @addtogroup rtc_apis
* @{
*/
/**************************************************************************************
* Note: *
* Some Rtc memory and registers are used, in ROM or in internal library. *
* Please do not use reserved or used rtc memory or registers. *
* *
*************************************************************************************
* RTC Memory & Store Register usage
*************************************************************************************
* rtc memory addr type size usage
* 0x3ff61000(0x50000000) Slow SIZE_CP Co-Processor code/Reset Entry
* 0x3ff61000+SIZE_CP Slow 6144-SIZE_CP
* 0x3ff62800 Slow 2048 Reserved
*
* 0x3ff80000(0x400c0000) Fast 8192 deep sleep entry code
*
*************************************************************************************
* Rtc store registers usage
* RTC_STORE0
* RTC_STORE1
* RTC_STORE2
* RTC_STORE3
* RTC_STORE4 Reserved
* RTC_STORE5 External Xtal Frequency
* RTC_STORE6 FAST_RTC_MEMORY_ENTRY
* RTC_STORE7 FAST_RTC_MEMORY_CRC
*************************************************************************************
*/
#define RTC_ENTRY_ADDR RTC_STORE6
#define RTC_MEMORY_CRC RTC_STORE7
typedef enum {
AWAKE = 0, //CPU ON
AWAKE = 0, //<CPU ON
LIGHT_SLEEP = BIT0, //CPU waiti, PLL ON. We don't need explicitly set this mode.
DEEP_SLEEP = BIT1 //CPU OFF, PLL OFF, only specific timer could wake up
} SLEEP_MODE;
typedef enum {
NO_MEAN = 0,
POWERON_RESET = 1, //1 Vbat power on reset, RTC reset
// EXT_SYS_RESET = 2, //4 External System reset, RTC reset
SW_RESET = 3, //6 Software warm reset
OWDT_RESET = 4, //5 Watch dog reset
DEEPSLEEP_RESET = 5, //2 Deep sleep timer reach reset.
SDIO_RESET = 6, //3 Deep sleep Pbint power on reset [boot]
TG0WDT_SYS_RESET = 7,
TG1WDT_SYS_RESET = 8,
RTCWDT_SYS_RESET = 9,
INTRUSION_RESET = 10,
TGWDT_CPU_RESET = 11,
SW_CPU_RESET = 12,
RTCWDT_CPU_RESET = 13,
EXT_CPU_RESET = 14,
RTCWDT_BROWN_OUT_RESET = 15,
RTCWDT_RTC_RESET = 16
POWERON_RESET = 1, /**<1, Vbat power on reset*/
SW_RESET = 3, /**<3, Software reset digital core*/
OWDT_RESET = 4, /**<4, Legacy watch dog reset digital core*/
DEEPSLEEP_RESET = 5, /**<3, Deep Sleep reset digital core*/
SDIO_RESET = 6, /**<6, Reset by SLC module, reset digital core*/
TG0WDT_SYS_RESET = 7, /**<7, Timer Group0 Watch dog reset digital core*/
TG1WDT_SYS_RESET = 8, /**<8, Timer Group1 Watch dog reset digital core*/
RTCWDT_SYS_RESET = 9, /**<9, RTC Watch dog Reset digital core*/
INTRUSION_RESET = 10, /**<10, Instrusion tested to reset CPU*/
TGWDT_CPU_RESET = 11, /**<11, Time Group reset CPU*/
SW_CPU_RESET = 12, /**<12, Software reset CPU*/
RTCWDT_CPU_RESET = 13, /**<13, RTC Watch dog Reset CPU*/
EXT_CPU_RESET = 14, /**<14, for APP CPU, reseted by PRO CPU*/
RTCWDT_BROWN_OUT_RESET = 15, /**<15, Reset when the vdd voltage is not stable*/
RTCWDT_RTC_RESET = 16 /**<16, RTC Watch dog reset digital core and rtc module*/
} RESET_REASON;
typedef enum {
@ -98,67 +136,67 @@ typedef enum {
SDIO_IDLE_INT_EN = SDIO_IDLE_INT,
RTC_WDT_INT_EN = RTC_WDT_INT,
RTC_TIME_VALID_INT_EN = RTC_TIME_VALID_INT
}RTC_INT_EN;
// Alive memory is a special memory block which could restore data during system
// deep sleep. power management and wlan profile data may need put into this
// memory area.
// Should create a dram segment in link script.
#define ALIVE_MEMORY_ADDR
#define ALIVE_MEMORY_SIZE (1024 * 2)
void rtc_hw_init(void);
} RTC_INT_EN;
/**
* @brief Get the reset reason for CPU.
*
* @param int cpu_no : CPU no.
*
* @return RESET_REASON
*/
RESET_REASON rtc_get_reset_reason(int cpu_no);
/**
* @brief Get the wakeup cause for CPU.
*
* @param int cpu_no : CPU no.
*
* @return WAKEUP_REASON
*/
WAKEUP_REASON rtc_get_wakeup_cause(void);
/**
* @brief Get CRC for Fast RTC Memory.
*
* @param uint32_t start_addr : 0 - 0x7ff for Fast RTC Memory.
*
* @param uint32_t crc_len : 0 - 0x7ff, 0 for 1 byte, 0x7ff for 0x800 byte.
*
* @return uint32_t : CRC32 result
*/
uint32_t calc_rtc_memory_crc(uint32_t start_addr, uint32_t crc_len);
/**
* @brief Set CRC of Fast RTC memory 0-0x7ff into RTC STORE7.
*
* @param None
*
* @return None
*/
void set_rtc_memory_crc(void);
/**
* @brief Software Reset digital core.
*
* @param None
*
* @return None
*/
void software_reset(void);
/**
* @brief Software Reset digital core.
*
* @param int cpu_no : The CPU to reset, 0 for PRO CPU, 1 for APP CPU.
*
* @return None
*/
void software_reset_cpu(int cpu_no);
void rtc_select_apb_bridge(bool sel);
void rtc_set_sleep_mode(SLEEP_MODE mode, uint32_t sleep_sec, uint32_t wakeup_mode);
uint8_t ets_rtc_recovery(void);
#define MAX_DEEPSLEEP_DURATION (0xffffffff / RTC_CLK_FREQ)
#define SECOND_TO_RTC_TICK(second) ((second)*RTC_CLK_FREQ) //32KHz
#define CALIB_VALUE_TO_RTC_TICK(microsecond, clk_mkz, n_rtc,nclk) ((microsecond)*(clk_mkz)*(n_rtc)/(nclk)) //32KHz
#define RTC_TICK_TO_SECOND(tick) ((tick)/RTC_CLK_FREQ )
#define GET_CURRENT_TICK() (READ_PERI_REG(RTC_TIME))
#define SET_WAKEUP_TICK(tick) (WRITE_PERI_REG(RTC_TIMER0, tick))
//#define GET_WAKEUP_CAUSE() GET_PERI_REG_BITS2(RTC_STATE1, RTC_CNTL_WAKEUP_CAUSE, RTC_CNTL_WAKEUP_CAUSE_S)
#define DISABLE_RTC_INT(int_type) CLEAR_PERI_REG_MASK(RTC_INT_ENA, int_type)
#define ENABLE_RTC_INT(int_type) SET_PERI_REG_MASK(RTC_INT_ENA, int_type)
#define CLR_RTC_INT(int_type) SET_PERI_REG_MASK(RTC_INT_CLR, int_type)
#define GET_RTC_INT_CAUSE() GET_PERI_REG_BITS(RTC_INT_RAW, RTC_INT_RAW_MSB,RTC_INT_RAW_LSB)
void rtc_register_deepsleep_timer(ETSTimer *timer, uint32_t tmout);
void rtc_disable_deepsleep_timer(void);
void rtc_enter_sleep(void);
void ets_rtc_int_register(void);
void dtm_set_intr_mask(uint32_t mask);
uint32_t dtm_get_intr_mask(void);
void dtm_set_params(uint32_t sleep_mode, uint32_t sleep_tm_ms, uint32_t wakeup_tm_ms, uint32_t sleep_times, uint32_t rxbcn_len);
void save_rxbcn_mactime(uint32_t rxbcn_mactime);
void save_tsf_us(uint32_t tsf_us);
typedef void (* ets_idle_cb_t)(void *arg);
typedef uint32_t (* ETS_GET_MACTIME)(void);
typedef void (* ETS_WAKEUP_INIT)(void);
void dtm_params_init(ETS_GET_MACTIME get_mactime, ETS_WAKEUP_INIT wakeup_init);
void ets_set_idle_cb(ets_idle_cb_t func, void *arg);
void ets_enter_sleep(void);
void rtc_intr_handler(void *);
#define ETS_SLEEP_START(pfunc, parg) ets_set_idle_cb((pfunc), (parg));
#define ETS_SLEEP_END() ets_set_idle_cb(NULL, NULL);
/**
* @}
*/
#ifdef __cplusplus
}

View File

@ -11,6 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ROM_SECURE_BOOT_H_
#define _ROM_SECURE_BOOT_H_
@ -34,6 +35,10 @@ void ets_secure_boot_rd_iv(uint32_t *buf);
void ets_secure_boot_rd_abstract(uint32_t *buf);
bool ets_secure_boot_check_start(uint8_t abs_index, uint32_t iv_addr);
int ets_secure_boot_check_finish(uint32_t *abstract);
#ifdef __cplusplus
}
#endif

View File

@ -11,6 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ROM_SPI_FLASH_H_
#define _ROM_SPI_FLASH_H_
@ -25,6 +26,45 @@
extern "C" {
#endif
/** \defgroup spi_flash_apis, spi flash operation related apis
* @brief spi_flash apis
*/
/** @addtogroup spi_flash_apis
* @{
*/
/*************************************************************
* Note
*************************************************************
* 1. ESP32 chip have 4 SPI slave/master, however, SPI0 is
* used as an SPI master to access Flash and ext-SRAM by
* Cache module. It will support Decryto read for Flash,
* read/write for ext-SRAM. And SPI1 is also used as an
* SPI master for Flash read/write and ext-SRAM read/write.
* It will support Encrypto write for Flash.
* 2. As an SPI master, SPI support Highest clock to 80M,
* however, Flash with 80M Clock should be configured
* for different Flash chips. If you want to use 80M
* clock We should use the SPI that is certified by
* Espressif. However, the certification is not started
* at the time, so please use 40M clock at the moment.
* 3. SPI Flash can use 2 lines or 4 lines mode. If you
* use 2 lines mode, you can save two pad SPIHD and
* SPIWP for gpio. ESP32 support configured SPI pad for
* Flash, the configuration is stored in efuse and flash.
* However, the configurations of pads should be certified
* by Espressif. If you use this function, please use 40M
* clock at the moment.
* 4. ESP32 support to use Common SPI command to configure
* Flash to QIO mode, if you failed to configure with fix
* command. With Common SPI Command, ESP32 can also provide
* a way to use same Common SPI command groups on different
* Flash chips.
* 5. This functions are not protected by packeting, Please use the
*************************************************************
*/
#define PERIPHS_SPI_FLASH_CMD SPI_CMD(1)
#define PERIPHS_SPI_FLASH_ADDR SPI_ADDR(1)
#define PERIPHS_SPI_FLASH_CTRL SPI_CTRL(1)
@ -92,7 +132,7 @@ typedef enum {
SPI_FLASH_RESULT_TIMEOUT
} SpiFlashOpResult;
typedef struct{
typedef struct {
uint32_t deviceId;
uint32_t chip_size; // chip size in bytes
uint32_t block_size;
@ -110,33 +150,362 @@ typedef struct {
uint16_t data;
} SpiCommonCmd;
void SelectSpiQIO(uint8_t wp_gpio_num, uint32_t ishspi) ROMFN_ATTR;
void SetSpiDrvs(uint8_t wp_gpio_num, uint32_t ishspi, uint8_t* drvs) ROMFN_ATTR;
void SelectSpiFunction(uint32_t ishspi) ROMFN_ATTR;
SpiFlashOpResult SPIEraseChip(void) ROMFN_ATTR;
SpiFlashOpResult SPIEraseBlock(uint32_t block_num) ROMFN_ATTR;
SpiFlashOpResult SPIEraseSector(uint32_t sector_num) ROMFN_ATTR;
SpiFlashOpResult SPIWrite(uint32_t dest_addr, const uint32_t* src, int32_t len) ROMFN_ATTR;
void SPI_Write_Encrypt_Enable() ROMFN_ATTR;
SpiFlashOpResult SPI_Prepare_Encrypt_Data(uint32_t flash_addr, uint32_t* data) ROMFN_ATTR;
void SPI_Write_Encrypt_Disable() ROMFN_ATTR;
SpiFlashOpResult SPI_Encrypt_Write(uint32_t flash_addr, uint32_t* data, uint32_t len) ROMFN_ATTR;
SpiFlashOpResult SPIRead(uint32_t src_addr, uint32_t* dest, int32_t len) ROMFN_ATTR;
SpiFlashOpResult SPIReadModeCnfig(SpiFlashRdMode mode, bool legacy) ROMFN_ATTR;
SpiFlashOpResult SPIMasterReadModeCnfig(SpiFlashRdMode mode) ROMFN_ATTR;
SpiFlashOpResult SPIClkConfig(uint8_t freqdiv, uint8_t spi) ROMFN_ATTR;
uint16_t SPI_Common_Command(SpiCommonCmd * cmd) ROMFN_ATTR;
SpiFlashOpResult SPIUnlock() ROMFN_ATTR;
SpiFlashOpResult SPIEraseArea(uint32_t start_addr, uint32_t area_len) ROMFN_ATTR;
SpiFlashOpResult SPILock() ROMFN_ATTR;
SpiFlashOpResult SPIParamCfg(uint32_t deviceId, uint32_t chip_size, uint32_t block_size, uint32_t sector_size, uint32_t page_size, uint32_t status_mask) ROMFN_ATTR;
SpiFlashOpResult SPI_user_command_read(uint32_t * status, uint8_t cmd) ROMFN_ATTR;
void spi_cache_sram_init() ROMFN_ATTR;
/**
* @brief Fix the bug in SPI hardware communication with Flash/Ext-SRAM in High Speed.
* Please do not call this function in SDK.
*
* @param uint8_t spi: 0 for SPI0(Cache Access), 1 for SPI1(Flash read/write).
*
* @param uint8_t freqdiv: Pll is 80M, 4 for 20M, 3 for 26.7M, 2 for 40M, 1 for 80M.
*
* @return None
*/
void spi_dummy_len_fix(uint8_t spi, uint8_t freqdiv);
//ETS_STATUS ets_unpack_flash_code(uint32_t pos, uint32_t *entry_addr, bool jump, bool sb_need_check, bool config) ROMFN_ATTR;
//ETS_STATUS ets_unpack_flash_code_legacy(uint32_t pos, uint32_t *entry_addr, bool jump, bool config) ROMFN_ATTR;
/**
* @brief Select SPI Flash to QIO mode when WP pad is read from Flash.
* Please do not call this function in SDK.
*
* @param uint8_t wp_gpio_num: WP gpio number.
*
* @param uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping
* else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd
*
* @return None
*/
void SelectSpiQIO(uint8_t wp_gpio_num, uint32_t ishspi);
void spi_flash_attach(uint32_t ishspi, bool legacy) ROMFN_ATTR;
/**
* @brief Set SPI Flash pad drivers.
* Please do not call this function in SDK.
*
* @param uint8_t wp_gpio_num: WP gpio number.
*
* @param uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping
* else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd
*
* @param uint8_t *drvs: drvs[0]-bit[3:0] for cpiclk, bit[7:4] for spiq, drvs[1]-bit[3:0] for spid, drvs[1]-bit[7:4] for spid
* drvs[2]-bit[3:0] for spihd, drvs[2]-bit[7:4] for spiwp.
* Values usually read from falsh by rom code, function usually callde by rom code.
* if value with bit(3) set, the value is valid, bit[2:0] is the real value.
*
* @return None
*/
void SetSpiDrvs(uint8_t wp_gpio_num, uint32_t ishspi, uint8_t *drvs);
/**
* @brief Select SPI Flash function for pads.
* Please do not call this function in SDK.
*
* @param uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping
* else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd
*
* @return None
*/
void SelectSpiFunction(uint32_t ishspi);
/**
* @brief SPI Flash init, clock divisor is 4, use 1 line Slow read mode.
* Please do not call this function in SDK.
*
* @param uint32_t ishspi: 0 for spi, 1 for hspi, flash pad decided by strapping
* else, bit[5:0] spiclk, bit[11:6] spiq, bit[17:12] spid, bit[23:18] spics0, bit[29:24] spihd
*
* @param uint8_t legacy: In legacy mode, more SPI command is used in line.
*
* @return None
*/
void spi_flash_attach(uint32_t ishspi, bool legacy);
/**
* @brief SPI Read Flash status register. We use CMD 0x05.
* Please do not call this function in SDK.
*
* @param SpiFlashChip *spi : The information for Flash, which is exported from ld file.
*
* @param uint32_t *status : The pointer to which to return the Flash status value.
*
* @return SPI_FLASH_RESULT_OK : read OK.
* SPI_FLASH_RESULT_ERR : read error.
* SPI_FLASH_RESULT_TIMEOUT : read timeout.
*/
SpiFlashOpResult SPI_read_status(SpiFlashChip *spi, uint32_t *status);
/**
* @brief SPI Read Flash status register high 16 bit. We use CMD 0x35.
* Please do not call this function in SDK.
*
* @param SpiFlashChip *spi : The information for Flash, which is exported from ld file.
*
* @param uint32_t *status : The pointer to which to return the Flash status value.
*
* @return SPI_FLASH_RESULT_OK : read OK.
* SPI_FLASH_RESULT_ERR : read error.
* SPI_FLASH_RESULT_TIMEOUT : read timeout.
*/
SpiFlashOpResult SPI_read_status_high(SpiFlashChip *spi, uint32_t *status);
/**
* @brief Write status to Falsh status register.
* Please do not call this function in SDK.
*
* @param SpiFlashChip *spi : The information for Flash, which is exported from ld file.
*
* @param uint32_t status_value : Value to .
*
* @return SPI_FLASH_RESULT_OK : write OK.
* SPI_FLASH_RESULT_ERR : write error.
* SPI_FLASH_RESULT_TIMEOUT : write timeout.
*/
SpiFlashOpResult SPI_write_status(SpiFlashChip *spi, uint32_t status_value);
/**
* @brief Use a command to Read Flash status register.
* Please do not call this function in SDK.
*
* @param SpiFlashChip *spi : The information for Flash, which is exported from ld file.
*
* @param uint32_t*status : The pointer to which to return the Flash status value.
*
* @return SPI_FLASH_RESULT_OK : read OK.
* SPI_FLASH_RESULT_ERR : read error.
* SPI_FLASH_RESULT_TIMEOUT : read timeout.
*/
SpiFlashOpResult SPI_user_command_read(uint32_t *status, uint8_t cmd);
/**
* @brief Config SPI Flash read mode when init.
* Please do not call this function in SDK.
*
* @param SpiFlashRdMode mode : QIO/QOUT/DIO/DOUT/FastRD/SlowRD.
*
* @param uint8_t legacy: In legacy mode, more SPI command is used in line.
*
* @return SPI_FLASH_RESULT_OK : config OK.
* SPI_FLASH_RESULT_ERR : config error.
* SPI_FLASH_RESULT_TIMEOUT : config timeout.
*/
SpiFlashOpResult SPIReadModeCnfig(SpiFlashRdMode mode, bool legacy);
/**
* @brief Config SPI Flash read mode when Flash is running in some mode.
* Please do not call this function in SDK.
*
* @param SpiFlashRdMode mode : QIO/QOUT/DIO/DOUT/FastRD/SlowRD.
*
* @return SPI_FLASH_RESULT_OK : config OK.
* SPI_FLASH_RESULT_ERR : config error.
* SPI_FLASH_RESULT_TIMEOUT : config timeout.
*/
SpiFlashOpResult SPIMasterReadModeCnfig(SpiFlashRdMode mode);
/**
* @brief Config SPI Flash clock divisor.
* Please do not call this function in SDK.
*
* @param uint8_t freqdiv: clock divisor.
*
* @param uint8_t spi: 0 for SPI0, 1 for SPI1.
*
* @return SPI_FLASH_RESULT_OK : config OK.
* SPI_FLASH_RESULT_ERR : config error.
* SPI_FLASH_RESULT_TIMEOUT : config timeout.
*/
SpiFlashOpResult SPIClkConfig(uint8_t freqdiv, uint8_t spi);
/**
* @brief Send CommonCmd to Flash so that is can go into QIO mode, some Flash use different CMD.
* Please do not call this function in SDK.
*
* @param SpiCommonCmd *cmd : A struct to show the action of a command.
*
* @return uint16_t 0 : do not send command any more.
* 1 : go to the next command.
* n > 1 : skip (n - 1) commands.
*/
uint16_t SPI_Common_Command(SpiCommonCmd *cmd);
/**
* @brief Unlock SPI write protect.
* Please do not call this function in SDK.
*
* @param None.
*
* @return SPI_FLASH_RESULT_OK : Unlock OK.
* SPI_FLASH_RESULT_ERR : Unlock error.
* SPI_FLASH_RESULT_TIMEOUT : Unlock timeout.
*/
SpiFlashOpResult SPIUnlock(void);
/**
* @brief SPI write protect.
* Please do not call this function in SDK.
*
* @param None.
*
* @return SPI_FLASH_RESULT_OK : Lock OK.
* SPI_FLASH_RESULT_ERR : Lock error.
* SPI_FLASH_RESULT_TIMEOUT : Lock timeout.
*/
SpiFlashOpResult SPILock(void);
/**
* @brief Update SPI Flash parameter.
* Please do not call this function in SDK.
*
* @param uint32_t deviceId : Device ID read from SPI, the low 32 bit.
*
* @param uint32_t chip_size : The Flash size.
*
* @param uint32_t block_size : The Flash block size.
*
* @param uint32_t sector_size : The Flash sector size.
*
* @param uint32_t page_size : The Flash page size.
*
* @param uint32_t status_mask : The Mask used when read status from Flash(use single CMD).
*
* @return SPI_FLASH_RESULT_OK : Update OK.
* SPI_FLASH_RESULT_ERR : Update error.
* SPI_FLASH_RESULT_TIMEOUT : Update timeout.
*/
SpiFlashOpResult SPIParamCfg(uint32_t deviceId, uint32_t chip_size, uint32_t block_size, uint32_t sector_size, uint32_t page_size, uint32_t status_mask);
/**
* @brief Erase whole flash chip.
* Please do not call this function in SDK.
*
* @param None
*
* @return SPI_FLASH_RESULT_OK : Erase OK.
* SPI_FLASH_RESULT_ERR : Erase error.
* SPI_FLASH_RESULT_TIMEOUT : Erase timeout.
*/
SpiFlashOpResult SPIEraseChip(void);
/**
* @brief Erase a block of flash.
* Please do not call this function in SDK.
*
* @param uint32_t block_num : Which block to erase.
*
* @return SPI_FLASH_RESULT_OK : Erase OK.
* SPI_FLASH_RESULT_ERR : Erase error.
* SPI_FLASH_RESULT_TIMEOUT : Erase timeout.
*/
SpiFlashOpResult SPIEraseBlock(uint32_t block_num);
/**
* @brief Erase a sector of flash.
* Please do not call this function in SDK.
*
* @param uint32_t sector_num : Which sector to erase.
*
* @return SPI_FLASH_RESULT_OK : Erase OK.
* SPI_FLASH_RESULT_ERR : Erase error.
* SPI_FLASH_RESULT_TIMEOUT : Erase timeout.
*/
SpiFlashOpResult SPIEraseSector(uint32_t sector_num);
/**
* @brief Erase some sectors.
* Please do not call this function in SDK.
*
* @param uint32_t start_addr : Start addr to erase, should be sector aligned.
*
* @param uint32_t area_len : Length to erase, should be sector aligned.
*
* @return SPI_FLASH_RESULT_OK : Erase OK.
* SPI_FLASH_RESULT_ERR : Erase error.
* SPI_FLASH_RESULT_TIMEOUT : Erase timeout.
*/
SpiFlashOpResult SPIEraseArea(uint32_t start_addr, uint32_t area_len);
/**
* @brief Write Data to Flash, you should Erase it yourself if need.
* Please do not call this function in SDK.
*
* @param uint32_t dest_addr : Address to write, should be 4 bytes aligned.
*
* @param const uint32_t *src : The pointer to data which is to write.
*
* @param uint32_t len : Length to write, should be 4 bytes aligned.
*
* @return SPI_FLASH_RESULT_OK : Write OK.
* SPI_FLASH_RESULT_ERR : Write error.
* SPI_FLASH_RESULT_TIMEOUT : Write timeout.
*/
SpiFlashOpResult SPIWrite(uint32_t dest_addr, const uint32_t *src, int32_t len);
/**
* @brief Read Data from Flash, you should Erase it yourself if need.
* Please do not call this function in SDK.
*
* @param uint32_t src_addr : Address to read, should be 4 bytes aligned.
*
* @param uint32_t *dest : The buf to read the data.
*
* @param uint32_t len : Length to read, should be 4 bytes aligned.
*
* @return SPI_FLASH_RESULT_OK : Read OK.
* SPI_FLASH_RESULT_ERR : Read error.
* SPI_FLASH_RESULT_TIMEOUT : Read timeout.
*/
SpiFlashOpResult SPIRead(uint32_t src_addr, uint32_t *dest, int32_t len);
/**
* @brief SPI1 go into encrypto mode.
* Please do not call this function in SDK.
*
* @param None
*
* @return None
*/
void SPI_Write_Encrypt_Enable(void);
/**
* @brief Prepare 32 Bytes data to encrpto writing, you should Erase it yourself if need.
* Please do not call this function in SDK.
*
* @param uint32_t flash_addr : Address to write, should be 32 bytes aligned.
*
* @param uint32_t *data : The pointer to data which is to write.
*
* @return SPI_FLASH_RESULT_OK : Prepare OK.
* SPI_FLASH_RESULT_ERR : Prepare error.
* SPI_FLASH_RESULT_TIMEOUT : Prepare timeout.
*/
SpiFlashOpResult SPI_Prepare_Encrypt_Data(uint32_t flash_addr, uint32_t *data);
/**
* @brief SPI1 go out of encrypto mode.
* Please do not call this function in SDK.
*
* @param None
*
* @return None
*/
void SPI_Write_Encrypt_Disable(void);
/**
* @brief Encrpto writing data to flash, you should Erase it yourself if need.
* Please do not call this function in SDK.
*
* @param uint32_t flash_addr : Address to write, should be 32 bytes aligned.
*
* @param uint32_t *data : The pointer to data which is to write.
*
* @param uint32_t len : Length to write, should be 32 bytes aligned.
*
* @return SPI_FLASH_RESULT_OK : Encrypto write OK.
* SPI_FLASH_RESULT_ERR : Encrypto write error.
* SPI_FLASH_RESULT_TIMEOUT : Encrypto write timeout.
*/
SpiFlashOpResult SPI_Encrypt_Write(uint32_t flash_addr, uint32_t *data, uint32_t len);
/**
* @}
*/
#ifdef __cplusplus
}

View File

@ -1,85 +0,0 @@
// Copyright 2011-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ROM_SSC_H_
#define _ROM_SSC_H_
#include "esp_types.h"
#include "esp_attr.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct cmd_s {
char *cmd_str;
#define CMD_T_ASYNC 0x01
#define CMD_T_SYNC 0x02
uint8_t flag;
uint8_t id;
void (* cmd_func)(void);
void (* cmd_callback)(void *arg);
} ssc_cmd_t;
#define ssc_printf ets_printf
#define SSC_CMD_N 10 //since the command not added in ssc_cmd.c
#define MAX_LINE_N 40
#define PROMPT ":>"
#define SSC_EVT_N 4
#define SSC_PRIO 30
enum {
CMD_SET_SSID = 0,
CMD_SCAN,
CMD_CONNECT,
CMD_DISCONNECT,
CMD_SET_MACADDR,
CMD_PING,
CMD_PING_COUNT,
CMD_PING_LENGTH,
CMD_SET_IP,
// CMD_RD_I2C,
// CMD_SET_NULL, it's just for solving the old rom bug
// CMD_SET_I2C,
// CMD_RD_I2CM,
// CMD_SET_I2CM,
// CMD_SET_PBUS,
// CMD_SET_TXTONE,
// CMD_SET_STOPTONE,
CMD_END,
};
enum {
SIG_SSC_RUNCMD,
SIG_SSC_CMDDONE,
SIG_SSC_RESTART,
SIG_SSC_UART_RX_CHAR,
};
void ssc_attach(void) ROMFN_ATTR;
void ssc_cmd_done(int cmd_id, STATUS status) ROMFN_ATTR;
int ssc_param_len(void) ROMFN_ATTR;
char * ssc_param_str(void) ROMFN_ATTR;
void ssc_register(ssc_cmd_t *cmdset, uint8_t cmdnum, void (* help)(void)) ROMFN_ATTR;
extern ssc_cmd_t sscCmdSet[];
void ssc_help(void);
#ifdef __cplusplus
}
#endif
#endif /* _ROM_SSC_H_ */

282
components/esp32/include/rom/uart.h Executable file → Normal file
View File

@ -22,6 +22,14 @@
extern "C" {
#endif
/** \defgroup uart_apis, uart configuration and communication related apis
* @brief uart apis
*/
/** @addtogroup uart_apis
* @{
*/
#define RX_BUFF_SIZE 0x100
#define TX_BUFF_SIZE 100
@ -52,9 +60,9 @@ extern "C" {
#define UART_RCV_ERR_FLAG BIT7
//send and receive message frame head
#define FRAME_FLAG 0x7E
#define FRAME_FLAG 0x7E
typedef enum{
typedef enum {
UART_LINE_STATUS_INT_FLAG = 0x06,
UART_RCV_FIFO_INT_FLAG = 0x04,
UART_RCV_TMOUT_INT_FLAG = 0x0C,
@ -82,9 +90,9 @@ typedef enum {
} UartStopBitsNum;
typedef enum {
NONE_BITS = 0,
ODD_BITS = 2,
EVEN_BITS = 3
NONE_BITS = 0,
ODD_BITS = 2,
EVEN_BITS = 3
} UartParityMode;
@ -113,7 +121,7 @@ typedef enum {
typedef enum {
EMPTY,
UNDER_WRITE,
WRITE_OVER
WRITE_OVER
} RcvMsgBuffState;
typedef struct {
@ -121,9 +129,9 @@ typedef struct {
uint8_t *pRcvMsgBuff;
uint8_t *pWritePos;
uint8_t *pReadPos;
uint8_t TrigLvl; //JLU: may need to pad
uint8_t TrigLvl;
RcvMsgBuffState BuffState;
}RcvMsgBuff;
} RcvMsgBuff;
typedef struct {
uint32_t TrxBuffSize;
@ -138,7 +146,7 @@ typedef enum {
RCV_ESC_CHAR,
} RcvMsgState;
typedef struct{
typedef struct {
UartBautRate baut_rate;
UartBitsNum4Char data_bits;
UartExistParity exist_parity;
@ -153,33 +161,249 @@ typedef struct{
int received;
} UartDevice;
void Uart_Init(uint8_t uart_no, uint32_t clock) ROMFN_ATTR;
STATUS UartTxString(uint8_t* pString) ROMFN_ATTR;
STATUS UartRxString(uint8_t* pString, uint8_t MaxStrlen) ROMFN_ATTR;
/**
* @brief Init uart device struct value and reset uart0/uart1 rx.
* Please do not call this function in SDK.
*
* @param None
*
* @return None
*/
void uartAttach(void);
STATUS uart_tx_one_char(uint8_t TxChar) ROMFN_ATTR;//for print
STATUS uart_tx_one_char2(uint8_t TxChar) ROMFN_ATTR;//for send message
STATUS uart_rx_one_char(uint8_t* pRxChar) ROMFN_ATTR;
char uart_rx_one_char_block(void) ROMFN_ATTR;
void uart_rx_intr_handler(void * para) ROMFN_ATTR;
STATUS uart_rx_readbuff( RcvMsgBuff* pRxBuff, uint8_t* pRxByte) ROMFN_ATTR;
STATUS UartGetCmdLn(uint8_t * pCmdLn) ROMFN_ATTR;
UartDevice * GetUartDevice() ROMFN_ATTR;
/**
* @brief Init uart0 or uart1 for UART download booting mode.
* Please do not call this function in SDK.
*
* @param uint8_t uart_no : 0 for UART0, else for UART1.
*
* @param uint32_t clock : clock used by uart module, to adjust baudrate.
*
* @return None
*/
void Uart_Init(uint8_t uart_no, uint32_t clock);
void uartToggleInterrupt(bool en) ROMFN_ATTR;
/**
* @brief Modify uart baudrate.
* This function will reset RX/TX fifo for uart.
*
* @param uint8_t uart_no : 0 for UART0, 1 for UART1.
*
* @param uint32_t DivLatchValue : (clock << 4)/baudrate.
*
* @return None
*/
void uart_div_modify(uint8_t uart_no, uint32_t DivLatchValue);
STATUS SendMsg(uint8_t *pData, uint16_t DataLen) ROMFN_ATTR;
/**
* @brief Init uart0 or uart1 for UART download booting mode.
* Please do not call this function in SDK.
*
* @param uint8_t uart_no : 0 for UART0, 1 for UART1.
*
* @param uint8_t is_sync : 0, only one UART module, easy to detect, wait until detected;
* 1, two UART modules, hard to detect, detect and return.
*
* @return None
*/
int uart_baudrate_detect(uint8_t uart_no, uint8_t is_sync);
STATUS RcvMsg(uint8_t *pData, uint16_t MaxDataLen, uint8_t is_sync) ROMFN_ATTR;
/**
* @brief Switch printf channel of uart_tx_one_char.
* Please do not call this function when printf.
*
* @param uint8_t uart_no : 0 for UART0, 1 for UART1.
*
* @return None
*/
void uart_tx_switch(uint8_t uart_no);
/**
* @brief Switch message exchange channel for UART download booting.
* Please do not call this function in SDK.
*
* @param uint8_t uart_no : 0 for UART0, 1 for UART1.
*
* @return None
*/
void uart_buff_switch(uint8_t uart_no);
/**
* @brief Output a char to printf channel, wait until fifo not full.
*
* @param None
*
* @return OK.
*/
STATUS uart_tx_one_char(uint8_t TxChar);
/**
* @brief Output a char to message exchange channel, wait until fifo not full.
* Please do not call this function in SDK.
*
* @param None
*
* @return OK.
*/
STATUS uart_tx_one_char2(uint8_t TxChar);//for send message
/**
* @brief Wait until uart tx full empty.
*
* @param uint8_t uart_no : 0 for UART0, 1 for UART1.
*
* @return None.
*/
void uart_tx_flush(uint8_t uart_no);
/**
* @brief Wait until uart tx full empty and the last char send ok.
*
* @param uint8_t uart_no : 0 for UART0, 1 for UART1.
*
* @return None.
*/
void uart_tx_wait_idle(uint8_t uart_no);
/**
* @brief Get an input char from message channel.
* Please do not call this function in SDK.
*
* @param uint8_t *pRxChar : the pointer to store the char.
*
* @return OK for successful.
* FAIL for failed.
*/
STATUS uart_rx_one_char(uint8_t *pRxChar);
/**
* @brief Get an input char to message channel, wait until successful.
* Please do not call this function in SDK.
*
* @param None
*
* @return char : input char value.
*/
char uart_rx_one_char_block(void);
/**
* @brief Get an input string line from message channel.
* Please do not call this function in SDK.
*
* @param uint8_t *pString : the pointer to store the string.
*
* @param uint8_t MaxStrlen : the max string length, incude '\0'.
*
* @return OK.
*/
STATUS UartRxString(uint8_t *pString, uint8_t MaxStrlen);
/**
* @brief Process uart recevied information in the interrupt handler.
* Please do not call this function in SDK.
*
* @param void *para : the message receive buffer.
*
* @return None
*/
void uart_rx_intr_handler(void *para);
/**
* @brief Get an char from receive buffer.
* Please do not call this function in SDK.
*
* @param RcvMsgBuff *pRxBuff : the pointer to the struct that include receive buffer.
*
* @param uint8_t *pRxByte : the pointer to store the char.
*
* @return OK for successful.
* FAIL for failed.
*/
STATUS uart_rx_readbuff( RcvMsgBuff *pRxBuff, uint8_t *pRxByte);
/**
* @brief Get all chars from receive buffer.
* Please do not call this function in SDK.
*
* @param uint8_t *pCmdLn : the pointer to store the string.
*
* @return OK for successful.
* FAIL for failed.
*/
STATUS UartGetCmdLn(uint8_t *pCmdLn);
/**
* @brief Get uart configuration struct.
* Please do not call this function in SDK.
*
* @param None
*
* @return UartDevice * : uart configuration struct pointer.
*/
UartDevice *GetUartDevice(void);
/**
* @brief Send an packet to download tool, with SLIP escaping.
* Please do not call this function in SDK.
*
* @param uint8_t *p : the pointer to output string.
*
* @param int len : the string length.
*
* @return None.
*/
void send_packet(uint8_t *p, int len);
/**
* @brief Receive an packet from download tool, with SLIP escaping.
* Please do not call this function in SDK.
*
* @param uint8_t *p : the pointer to input string.
*
* @param int len : If string length > len, the string will be truncated.
*
* @param uint8_t is_sync : 0, only one UART module;
* 1, two UART modules.
*
* @return int : the length of the string.
*/
int recv_packet(uint8_t *p, int len, uint8_t is_sync);
/**
* @brief Send an packet to download tool, with SLIP escaping.
* Please do not call this function in SDK.
*
* @param uint8_t *pData : the pointer to input string.
*
* @param uint16_t DataLen : the string length.
*
* @return OK for successful.
* FAIL for failed.
*/
STATUS SendMsg(uint8_t *pData, uint16_t DataLen);
/**
* @brief Receive an packet from download tool, with SLIP escaping.
* Please do not call this function in SDK.
*
* @param uint8_t *pData : the pointer to input string.
*
* @param uint16_t MaxDataLen : If string length > MaxDataLen, the string will be truncated.
*
* @param uint8_t is_sync : 0, only one UART module;
* 1, two UART modules.
*
* @return OK for successful.
* FAIL for failed.
*/
STATUS RcvMsg(uint8_t *pData, uint16_t MaxDataLen, uint8_t is_sync);
void uartAttach() ROMFN_ATTR;
void uart_div_modify(uint8_t uart_no, uint32_t DivLatchValue) ROMFN_ATTR;
int uart_baudrate_detect(uint8_t uart_no, uint8_t is_sync) ROMFN_ATTR;
void uart_buff_switch(uint8_t uart_no) ROMFN_ATTR;
void uart_tx_flush(uint8_t uart_no) ROMFN_ATTR;
void uart_tx_wait_idle(uint8_t uart_no) ROMFN_ATTR;
extern UartDevice UartDev;
/**
* @}
*/
#ifdef __cplusplus
}
#endif

View File

@ -1,40 +0,0 @@
// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ROM_WDT_H_
#define _ROM_WDT_H_
#include "soc.h"
#include "ets_sys.h"
#define WDT_RESET_VALUE 0x73
#define WDT_RESET_LEN 7 //real time: (1<<(WDT_RESET_LEN+1))*pclk
#define WDT_CONTROL_ENABLED BIT0
#define WDT_MODE_SET(v) (v)
#define WDT_TARGET_SET(v) (v)
#define WDT_ADDRESS 0
#define SEC_TO_WDT_TICK(s) (s * WDT_CLK_FREQ) //it's Pclk clock,44MHz
typedef enum{
NEXT_OVERFLOW_RESET = 0,
NEXT_OVERFLOW_NO_RESET = 1,
EACH_OVERFLOW_RESET = 2,
} WDT_RESP_MODE;
#define WDT_DEFAULT_FEED_INTERVAL WDT_INTERVAL_SIX_SEC /* 6 seconds */
#define WDT_DEFAULT_EXPIRE_INTERVAL WDT_INTERVAL_TWELVE_SEC /* 12 seconds */
#endif /* _ROM_WDT_H_ */

View File

@ -80,21 +80,24 @@
#define FUNC_GPIO33_GPIO33_0 0
#define PERIPHS_IO_MUX_GPIO25_U (DR_REG_IO_MUX_BASE +0x24)
#define FUNC_GPIO25_EMAC_RXD0 5
#define FUNC_GPIO25_GPIO25 2
#define FUNC_GPIO25_GPIO25_0 0
#define PERIPHS_IO_MUX_GPIO26_U (DR_REG_IO_MUX_BASE +0x28)
#define FUNC_GPIO26_EMAC_RXD1 5
#define FUNC_GPIO26_GPIO26 2
#define FUNC_GPIO26_GPIO26_0 0
#define PERIPHS_IO_MUX_GPIO27_U (DR_REG_IO_MUX_BASE +0x2c)
#define FUNC_GPIO27_EMAC_RXD2 5
#define FUNC_GPIO27_EMAC_RX_DV 5
#define FUNC_GPIO27_GPIO27 2
#define FUNC_GPIO27_GPIO27_0 0
#define PERIPHS_IO_MUX_MTMS_U (DR_REG_IO_MUX_BASE +0x30)
#define FUNC_MTMS_EMAC_TXD2 5
#define FUNC_MTMS_SD_CLK 4
#define FUNC_MTMS_HS2_CLk 3
#define FUNC_MTMS_GPIO14 2
#define FUNC_MTMS_HSPICLK 1
#define FUNC_MTMS_MTMS 0
@ -102,6 +105,7 @@
#define PERIPHS_IO_MUX_MTDI_U (DR_REG_IO_MUX_BASE +0x34)
#define FUNC_MTDI_EMAC_TXD3 5
#define FUNC_MTDI_SD_DATA2 4
#define FUNC_MTDI_HS2_DATA2 3
#define FUNC_MTDI_GPIO12 2
#define FUNC_MTDI_HSPIQ 1
#define FUNC_MTDI_MTDI 0
@ -109,7 +113,7 @@
#define PERIPHS_IO_MUX_MTCK_U (DR_REG_IO_MUX_BASE +0x38)
#define FUNC_MTCK_EMAC_RX_ER 5
#define FUNC_MTCK_SD_DATA3 4
#define FUNC_MTCK_U0CTS 3
#define FUNC_MTCK_HS2_DATA3 3
#define FUNC_MTCK_GPIO13 2
#define FUNC_MTCK_HSPID 1
#define FUNC_MTCK_MTCK 0
@ -117,21 +121,20 @@
#define PERIPHS_IO_MUX_MTDO_U (DR_REG_IO_MUX_BASE +0x3c)
#define FUNC_MTDO_EMAC_RXD3 5
#define FUNC_MTDO_SD_CMD 4
#define FUNC_MTDO_U0RTS 3
#define FUNC_MTDO_HS2_CMD 3
#define FUNC_MTDO_GPIO15 2
#define FUNC_MTDO_HSPICS0 1
#define FUNC_MTDO_MTDO 0
#define PERIPHS_IO_MUX_GPIO2_U (DR_REG_IO_MUX_BASE +0x40)
#define FUNC_GPIO2_EMAC_RX_DV 5
#define FUNC_GPIO2_SD_DATA0 4
#define FUNC_GPIO2_HS2_DATA0 3
#define FUNC_GPIO2_GPIO2 2
#define FUNC_GPIO2_HSPIWP 1
#define FUNC_GPIO2_GPIO2_0 0
#define PERIPHS_IO_MUX_GPIO0_U (DR_REG_IO_MUX_BASE +0x44)
#define FUNC_GPIO0_EMAC_TX_CLK 5
#define FUNC_GPIO0_HS2_CMD 3
#define FUNC_GPIO0_GPIO0 2
#define FUNC_GPIO0_CLK_OUT1 1
#define FUNC_GPIO0_GPIO0_0 0
@ -139,6 +142,7 @@
#define PERIPHS_IO_MUX_GPIO4_U (DR_REG_IO_MUX_BASE +0x48)
#define FUNC_GPIO4_EMAC_TX_ER 5
#define FUNC_GPIO4_SD_DATA1 4
#define FUNC_GPIO4_HS2_DATA1 3
#define FUNC_GPIO4_GPIO4 2
#define FUNC_GPIO4_HSPIHD 1
#define FUNC_GPIO4_GPIO4_0 0
@ -207,15 +211,14 @@
#define FUNC_GPIO5_GPIO5_0 0
#define PERIPHS_IO_MUX_GPIO18_U (DR_REG_IO_MUX_BASE +0x70)
#define FUNC_GPIO18_EMAC_TXD0 5
#define FUNC_GPIO18_HS1_DATA7 3
#define FUNC_GPIO18_GPIO18 2
#define FUNC_GPIO18_VSPICLK 1
#define FUNC_GPIO18_GPIO18_0 0
#define PERIPHS_IO_MUX_GPIO19_U (DR_REG_IO_MUX_BASE +0x74)
#define FUNC_GPIO19_EMAC_TXD1 5
#define FUNC_GPIO19_HS2_DATA2 3
#define FUNC_GPIO19_EMAC_TXD0 5
#define FUNC_GPIO19_U0CTS 3
#define FUNC_GPIO19_GPIO19 2
#define FUNC_GPIO19_VSPIQ 1
#define FUNC_GPIO19_GPIO19_0 0
@ -225,33 +228,30 @@
#define FUNC_GPIO20_GPIO20_0 0
#define PERIPHS_IO_MUX_GPIO21_U (DR_REG_IO_MUX_BASE +0x7c)
#define FUNC_GPIO21_EMAC_RXD0 5
#define FUNC_GPIO21_HS2_DATA3 3
#define FUNC_GPIO21_EMAC_TX_EN 5
#define FUNC_GPIO21_GPIO21 2
#define FUNC_GPIO21_VSPIHD 1
#define FUNC_GPIO21_GPIO21_0 0
#define PERIPHS_IO_MUX_GPIO22_U (DR_REG_IO_MUX_BASE +0x80)
#define FUNC_GPIO22_EMAC_RXD1 5
#define FUNC_GPIO22_HS2_CLK 3
#define FUNC_GPIO22_EMAC_TXD1 5
#define FUNC_GPIO22_U0RTS 3
#define FUNC_GPIO22_GPIO22 2
#define FUNC_GPIO22_VSPIWP 1
#define FUNC_GPIO22_GPIO22_0 0
#define PERIPHS_IO_MUX_U0RXD_U (DR_REG_IO_MUX_BASE +0x84)
#define FUNC_U0RXD_HS2_DATA0 3
#define FUNC_U0RXD_GPIO3 2
#define FUNC_U0RXD_CLK_OUT2 1
#define FUNC_U0RXD_U0RXD 0
#define PERIPHS_IO_MUX_U0TXD_U (DR_REG_IO_MUX_BASE +0x88)
#define FUNC_U0TXD_HS2_DATA1 3
#define FUNC_U0TXD_EMAC_RXD2 3
#define FUNC_U0TXD_GPIO1 2
#define FUNC_U0TXD_CLK_OUT3 1
#define FUNC_U0TXD_U0TXD 0
#define PERIPHS_IO_MUX_GPIO23_U (DR_REG_IO_MUX_BASE +0x8c)
#define FUNC_GPIO23_EMAC_TX_EN 5
#define FUNC_GPIO23_HS1_STROBE 3
#define FUNC_GPIO23_GPIO23 2
#define FUNC_GPIO23_VSPID 1

View File

@ -58,98 +58,93 @@
#define BIT(nr) (1UL << (nr))
//write value to register
#define REG_WRITE(_r, _v) (*(volatile uint32_t *)(_r)) = (_v)
//read value from register
#define REG_READ(_r) (*(volatile uint32_t *)(_r))
//get bit or get bits from register
#define REG_GET_BIT(_r, _b) (*(volatile uint32_t*)(_r) & (_b))
//set bit or set bits to register
#define REG_SET_BIT(_r, _b) (*(volatile uint32_t*)(_r) |= (_b))
//clear bit or clear bits of register
#define REG_CLR_BIT(_r, _b) (*(volatile uint32_t*)(_r) &= ~(_b))
//set bits of register controlled by mask
#define REG_SET_BITS(_r, _b, _m) (*(volatile uint32_t*)(_r) = (*(volatile uint32_t*)(_r) & ~(_m)) | ((_b) & (_m)))
#define VALUE_GET_FIELD(_r, _f) (((_r) >> (_f##_S)) & (_f))
#define VALUE_GET_FIELD2(_r, _f) (((_r) & (_f))>> (_f##_S))
#define VALUE_SET_FIELD(_r, _f, _v) ((_r)=(((_r) & ~((_f) << (_f##_S)))|((_v)<<(_f##_S))))
#define VALUE_SET_FIELD2(_r, _f, _v) ((_r)=(((_r) & ~(_f))|((_v)<<(_f##_S))))
#define FIELD_TO_VALUE(_f, _v) (((_v)&(_f))<<_f##_S)
#define FIELD_TO_VALUE2(_f, _v) (((_v)<<_f##_S) & (_f))
//get field from register, used when _f is not left shifted by _f##_S
#define REG_GET_FIELD(_r, _f) ((REG_READ(_r) >> (_f##_S)) & (_f))
//set field to register, used when _f is not left shifted by _f##_S
#define REG_SET_FIELD(_r, _f, _v) (REG_WRITE((_r),((REG_READ(_r) & ~((_f) << (_f##_S)))|(((_v) & (_f))<<(_f##_S)))))
//get field value from a variable, used when _f is not left shifted by _f##_S
#define VALUE_GET_FIELD(_r, _f) (((_r) >> (_f##_S)) & (_f))
//get field value from a variable, used when _f is left shifted by _f##_S
#define VALUE_GET_FIELD2(_r, _f) (((_r) & (_f))>> (_f##_S))
//set field value to a variable, used when _f is not left shifted by _f##_S
#define VALUE_SET_FIELD(_r, _f, _v) ((_r)=(((_r) & ~((_f) << (_f##_S)))|((_v)<<(_f##_S))))
//set field value to a variable, used when _f is left shifted by _f##_S
#define VALUE_SET_FIELD2(_r, _f, _v) ((_r)=(((_r) & ~(_f))|((_v)<<(_f##_S))))
//generate a value from a field value, used when _f is not left shifted by _f##_S
#define FIELD_TO_VALUE(_f, _v) (((_v)&(_f))<<_f##_S)
//generate a value from a field value, used when _f is left shifted by _f##_S
#define FIELD_TO_VALUE2(_f, _v) (((_v)<<_f##_S) & (_f))
//read value from register
#define READ_PERI_REG(addr) (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr)))
//write value to register
#define WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)ETS_UNCACHED_ADDR(addr))) = (uint32_t)(val)
//clear bits of register controlled by mask
#define CLEAR_PERI_REG_MASK(reg, mask) WRITE_PERI_REG((reg), (READ_PERI_REG(reg)&(~(mask))))
//set bits of register controlled by mask
#define SET_PERI_REG_MASK(reg, mask) WRITE_PERI_REG((reg), (READ_PERI_REG(reg)|(mask)))
//get bits of register controlled by mask
#define GET_PERI_REG_MASK(reg, mask) (READ_PERI_REG(reg) & (mask))
#define GET_PERI_REG_BITS(reg, hipos,lowpos) ((READ_PERI_REG(reg)>>(lowpos))&((1<<((hipos)-(lowpos)+1))-1))
//get bits of register controlled by highest bit and lowest bit
#define GET_PERI_REG_BITS(reg, hipos,lowpos) ((READ_PERI_REG(reg)>>(lowpos))&((1<<((hipos)-(lowpos)+1))-1))
//set bits of register controlled by mask and shift
#define SET_PERI_REG_BITS(reg,bit_map,value,shift) (WRITE_PERI_REG((reg),(READ_PERI_REG(reg)&(~((bit_map)<<(shift))))|(((value) & bit_map)<<(shift)) ))
//get field of register
#define GET_PERI_REG_BITS2(reg, mask,shift) ((READ_PERI_REG(reg)>>(shift))&(mask))
//}}
//Periheral Clock {{
#define APB_CLK_FREQ_ROM 13*1000000
#define APB_CLK_FREQ_ROM 26*1000000
#define CPU_CLK_FREQ_ROM APB_CLK_FREQ_ROM
#define CPU_CLK_FREQ APB_CLK_FREQ
#define APB_CLK_FREQ 80*1000000 //unit: Hz
#define UART_CLK_FREQ APB_CLK_FREQ
//#define WDT_CLK_FREQ APB_CLK_FREQ
#define WDT_CLK_FREQ APB_CLK_FREQ
#define TIMER_CLK_FREQ (80000000>>4) //80MHz divided by 16
#define SPI_CLK_DIV 4
//#define RTC_CLK_FREQ 32768 //unit:Hz
//#define RTC_CLK_FREQ 100000 //unit:Hz
//#define CALIB_CLK_MHZ 40
#define TICKS_PER_US 13 // CPU is 80MHz
#define TICKS_PER_US_ROM 26 // CPU is 80MHz
//}}
#if 0
//Peripheral device base address define{{
#define DR_REG_DPORT_BASE 0x3ff00000
#define DR_REG_UART_BASE 0x60000000
#define DR_REG_SPI1_BASE 0x60002000 //no
#define DR_REG_SPI0_BASE 0x60003000 //no
#define DR_REG_GPIO_BASE 0x60004000 //no
#define DR_REG_FE2_BASE 0x60005000
#define DR_REG_FE_BASE 0x60006000
#define DR_REG_TIMER_BASE 0x60007000 //no
#define DR_REG_RTCCNTL_BASE 0x60008000
#define DR_REG_RTCIO_BASE 0x60008400
#define DR_REG_RTCMEM0_BASE 0x60021000
#define DR_REG_RTCMEM1_BASE 0x60022000
#define DR_REG_RTCMEM2_BASE 0x60023000
#define DR_REG_IO_MUX_BASE 0x60009000 //no
#define DR_REG_WDG_BASE 0x6000A000 //no
#define DR_REG_HINF_BASE 0x6000B000 //no
#define DR_REG_UHCI1_BASE 0x6000C000
//#define DR_REG_MISC_BASE 0x6000D000 //no use
#define DR_REG_I2C_BASE 0x6000E000 //no
#define DR_REG_I2S_BASE 0x6000F000
#define DR_REG_UART1_BASE 0x60010000
#define DR_REG_BT_BASE 0x60011000
//#define DR_REG_BT_BUFFER_BASE 0x60012000 //no use
#define DR_REG_I2C_EXT_BASE 0x60013000 //no
#define DR_REG_UHCI0_BASE 0x60014000
#define DR_REG_SLCHOST_BASE 0x60015000
#define DR_REG_RMT_BASE 0x60016000
#define DR_REG_PCNT_BASE 0x60017000
#define DR_REG_SLC_BASE 0x60018000
#define DR_REG_LEDC_BASE 0x60019000
#define DR_REG_EFUSE_BASE 0x6001A000
#define DR_REG_SPI_ENCRYPT_BASE 0x6001B000
#define DR_REG_PWM_BASE 0x6001C000 //no
#define DR_REG_TIMERGROUP_BASE 0x6001D000 //no
#define DR_REG_TIMERGROUP1_BASE 0x6001E000 //no
#define DR_REG_BB_BASE 0x6001F000
#define DR_REG_GPIO_SD_BASE 0x60004f00
#else
#define DR_REG_DPORT_BASE 0x3ff00000
#define DR_REG_UART_BASE 0x3ff40000
#define DR_REG_SPI1_BASE 0x3ff42000 //no
#define DR_REG_SPI0_BASE 0x3ff43000 //no
#define DR_REG_GPIO_BASE 0x3ff44000 //no
#define DR_REG_SPI1_BASE 0x3ff42000
#define DR_REG_SPI0_BASE 0x3ff43000
#define DR_REG_GPIO_BASE 0x3ff44000
#define DR_REG_FE2_BASE 0x3ff45000
#define DR_REG_FE_BASE 0x3ff46000
#define DR_REG_TIMER_BASE 0x3ff47000 //no
#define DR_REG_TIMER_BASE 0x3ff47000
#define DR_REG_RTCCNTL_BASE 0x3ff48000
#define DR_REG_RTCIO_BASE 0x3ff48400
@ -157,18 +152,16 @@
#define DR_REG_RTCMEM1_BASE 0x3ff62000
#define DR_REG_RTCMEM2_BASE 0x3ff63000
#define DR_REG_IO_MUX_BASE 0x3ff49000 //no
#define DR_REG_WDG_BASE 0x3ff4A000 //no
#define DR_REG_HINF_BASE 0x3ff4B000 //no
#define DR_REG_IO_MUX_BASE 0x3ff49000
#define DR_REG_WDG_BASE 0x3ff4A000
#define DR_REG_HINF_BASE 0x3ff4B000
#define DR_REG_UHCI1_BASE 0x3ff4C000
//#define DR_REG_MISC_BASE 0x6000D000 //no use
#define DR_REG_I2C_BASE 0x3ff4E000 //no
#define DR_REG_I2C_BASE 0x3ff4E000
#define DR_REG_I2S_BASE 0x3ff4F000
#define DR_REG_I2S1_BASE 0x3ff6D000
#define DR_REG_UART1_BASE 0x3ff50000
#define DR_REG_BT_BASE 0x3ff51000
//#define DR_REG_BT_BUFFER_BASE 0x60012000 //no use
#define DR_REG_I2C_EXT_BASE 0x3ff53000 //no
#define DR_REG_I2C_EXT_BASE 0x3ff53000
#define DR_REG_UHCI0_BASE 0x3ff54000
#define DR_REG_SLCHOST_BASE 0x3ff55000
#define DR_REG_RMT_BASE 0x3ff56000
@ -177,94 +170,139 @@
#define DR_REG_LEDC_BASE 0x3ff59000
#define DR_REG_EFUSE_BASE 0x3ff5A000
#define DR_REG_SPI_ENCRYPT_BASE 0x3ff5B000
#define DR_REG_PWM_BASE 0x3ff5C000 //no
#define DR_REG_TIMERS_BASE 0x3ff5F000 //no
#define DR_REG_TIMERGROUP1_BASE 0x3ff5E000 //no
#define DR_REG_BB_BASE 0x3ff5F000
#define DR_REG_BB_BASE 0x3ff5C000
#define DR_REG_PWM_BASE 0x3ff5E000
#define DR_REG_TIMERS_BASE(i) (0x3ff5F000 + i * (0x1000))
#define DR_REG_GPIO_SD_BASE 0x3ff44f00
#endif
//}}
#define REG_SPI_BASE(i) (DR_REG_SPI0_BASE - i*(0x1000))
#define PERIPHS_TIMER_BASEDDR DR_REG_TIMER_BASE
#define PERIPHS_SPI_ENCRYPT_BASEADDR DR_REG_SPI_ENCRYPT_BASE
#define UART0_UNHOLD_MASK 0x3
#define UART1_UNHOLD_MASK 0x60
#define SDIO_UNHOLD_MASK 0xfc
#define SPI_UNHOLD_MASK 0xfc
//Interrupt hardware source table
//This table is decided by hardware, don't touch this.
#define ETS_WIFI_MAC_INTR_SOURCE 0/**< interrupt of WiFi MAC, level*/
#define ETS_WIFI_MAC_NMI_SOURCE 1/**< interrupt of WiFi MAC, NMI, use if MAC have bug to fix in NMI*/
#define ETS_WIFI_BB_INTR_SOURCE 2/**< interrupt of WiFi BB, level, we can do some calibartion*/
#define ETS_BT_MAC_INTR_SOURCE 3/**< will be cancelled*/
#define ETS_BT_BB_INTR_SOURCE 4/**< interrupt of BT BB, level*/
#define ETS_BT_BB_NMI_SOURCE 5/**< interrupt of BT BB, NMI, use if BB have bug to fix in NMI*/
#define ETS_RWBT_INTR_SOURCE 6/**< interrupt of RWBT, level*/
#define ETS_RWBLE_INTR_SOURCE 7/**< interrupt of RWBLE, level*/
#define ETS_RWBT_NMI_SOURCE 8/**< interrupt of RWBT, NMI, use if RWBT have bug to fix in NMI*/
#define ETS_RWBLE_NMI_SOURCE 9/**< interrupt of RWBLE, NMI, use if RWBT have bug to fix in NMI*/
#define ETS_SLC0_INTR_SOURCE 10/**< interrupt of SLC0, level*/
#define ETS_SLC1_INTR_SOURCE 11/**< interrupt of SLC1, level*/
#define ETS_UHCI0_INTR_SOURCE 12/**< interrupt of UHCI0, level*/
#define ETS_UHCI1_INTR_SOURCE 13/**< interrupt of UHCI1, level*/
#define ETS_TG0_T0_LEVEL_INTR_SOURCE 14/**< interrupt of TIMER_GROUP0, TIMER0, level, we would like use EDGE for timer if permission*/
#define ETS_TG0_T1_LEVEL_INTR_SOURCE 15/**< interrupt of TIMER_GROUP0, TIMER1, level, we would like use EDGE for timer if permission*/
#define ETS_TG0_WDT_LEVEL_INTR_SOURCE 16/**< interrupt of TIMER_GROUP0, WATCHDOG, level*/
#define ETS_TG0_LACT_LEVEL_INTR_SOURCE 17/**< interrupt of TIMER_GROUP0, LACT, level*/
#define ETS_TG1_T0_LEVEL_INTR_SOURCE 18/**< interrupt of TIMER_GROUP1, TIMER0, level, we would like use EDGE for timer if permission*/
#define ETS_TG1_T1_LEVEL_INTR_SOURCE 19/**< interrupt of TIMER_GROUP1, TIMER1, level, we would like use EDGE for timer if permission*/
#define ETS_TG1_WDT_LEVEL_INTR_SOURCE 20/**< interrupt of TIMER_GROUP1, WATCHDOG, level*/
#define ETS_TG1_LACT_LEVEL_INTR_SOURCE 21/**< interrupt of TIMER_GROUP1, LACT, level*/
#define ETS_GPIO_INTR_SOURCE 22/**< interrupt of GPIO, level*/
#define ETS_GPIO_NMI_SOURCE 23/**< interrupt of GPIO, NMI*/
#define ETS_FROM_CPU_INTR0_SOURCE 24/**< interrupt0 generated from a CPU, level*/
#define ETS_FROM_CPU_INTR1_SOURCE 25/**< interrupt1 generated from a CPU, level*/
#define ETS_FROM_CPU_INTR2_SOURCE 26/**< interrupt2 generated from a CPU, level*/
#define ETS_FROM_CPU_INTR3_SOURCE 27/**< interrupt3 generated from a CPU, level*/
#define ETS_SPI0_INTR_SOURCE 28/**< interrupt of SPI0, level, SPI0 is for Cache Access, do not use this*/
#define ETS_SPI1_INTR_SOURCE 29/**< interrupt of SPI1, level, SPI1 is for flash read/write, do not use this*/
#define ETS_SPI2_INTR_SOURCE 30/**< interrupt of SPI2, level*/
#define ETS_SPI3_INTR_SOURCE 31/**< interrupt of SPI3, level*/
#define ETS_I2S0_INTR_SOURCE 32/**< interrupt of I2S0, level*/
#define ETS_I2S1_INTR_SOURCE 33/**< interrupt of I2S1, level*/
#define ETS_UART0_INTR_SOURCE 34/**< interrupt of UART0, level*/
#define ETS_UART1_INTR_SOURCE 35/**< interrupt of UART1, level*/
#define ETS_UART2_INTR_SOURCE 36/**< interrupt of UART2, level*/
#define ETS_SDIO_HOST_INTR_SOURCE 37/**< interrupt of SD/SDIO/MMC HOST, level*/
#define ETS_ETH_MAC_INTR_SOURCE 38/**< interrupt of ethernet mac, level*/
#define ETS_PWM0_INTR_SOURCE 39/**< interrupt of PWM0, level, Reserved*/
#define ETS_PWM1_INTR_SOURCE 40/**< interrupt of PWM1, level, Reserved*/
#define ETS_PWM2_INTR_SOURCE 41/**< interrupt of PWM2, level*/
#define ETS_PWM3_INTR_SOURCE 42/**< interruot of PWM3, level*/
#define ETS_LEDC_INTR_SOURCE 43/**< interrupt of LED PWM, level*/
#define ETS_EFUSE_INTR_SOURCE 44/**< interrupt of efuse, level, not likely to use*/
#define ETS_CAN_INTR_SOURCE 45/**< interrupt of can, level*/
#define ETS_RTC_CORE_INTR_SOURCE 46/**< interrupt of rtc core, level, include rtc watchdog*/
#define ETS_RMT_INTR_SOURCE 47/**< interrupt of remote controller, level*/
#define ETS_PCNT_INTR_SOURCE 48/**< interrupt of pluse count, level*/
#define ETS_I2C_EXT0_INTR_SOURCE 49/**< interrupt of I2C controller1, level*/
#define ETS_I2C_EXT1_INTR_SOURCE 50/**< interrupt of I2C controller0, level*/
#define ETS_RSA_INTR_SOURCE 51/**< interrupt of RSA accelerator, level*/
#define ETS_SPI1_DMA_INTR_SOURCE 52/**< interrupt of SPI1 DMA, SPI1 is for flash read/write, do not use this*/
#define ETS_SPI2_DMA_INTR_SOURCE 53/**< interrupt of SPI2 DMA, level*/
#define ETS_SPI3_DMA_INTR_SOURCE 54/**< interrupt of SPI3 DMA, level*/
#define ETS_WDT_INTR_SOURCE 55/**< will be cancelled*/
#define ETS_TIMER1_INTR_SOURCE 56/**< will be cancelled*/
#define ETS_TIMER2_INTR_SOURCE 57/**< will be cancelled*/
#define ETS_TG0_T0_EDGE_INTR_SOURCE 58/**< interrupt of TIMER_GROUP0, TIMER0, EDGE*/
#define ETS_TG0_T1_EDGE_INTR_SOURCE 59/**< interrupt of TIMER_GROUP0, TIMER1, EDGE*/
#define ETS_TG0_WDT_EDGE_INTR_SOURCE 60/**< interrupt of TIMER_GROUP0, WATCH DOG, EDGE*/
#define ETS_TG0_LACT_EDGE_INTR_SOURCE 61/**< interrupt of TIMER_GROUP0, LACT, EDGE*/
#define ETS_TG1_T0_EDGE_INTR_SOURCE 62/**< interrupt of TIMER_GROUP1, TIMER0, EDGE*/
#define ETS_TG1_T1_EDGE_INTR_SOURCE 63/**< interrupt of TIMER_GROUP1, TIMER1, EDGE*/
#define ETS_TG1_WDT_EDGE_INTR_SOURCE 64/**< interrupt of TIMER_GROUP1, WATCHDOG, EDGE*/
#define ETS_TG1_LACT_EDGE_INTR_SOURCE 65/**< interrupt of TIMER_GROUP0, LACT, EDGE*/
#define ETS_MMU_IA_INTR_SOURCE 66/**< interrupt of MMU Invalid Access, LEVEL*/
#define ETS_MPU_IA_INTR_SOURCE 67/**< interrupt of MPU Invalid Access, LEVEL*/
#define ETS_CACHE_IA_INTR_SOURCE 68/**< interrupt of Cache Invalied Access, LEVEL*/
// TIMER reg {{
#define TIMER_REG_READ(addr) READ_PERI_REG(addr)
#define TIMER_REG_WRITE(addr, val) WRITE_PERI_REG(addr, val)
#define TIMER_SET_REG_MASK(reg, mask) WRITE_PERI_REG(reg, (READ_PERI_REG(reg)|(mask)))
/* Returns the current time according to the timer timer. */
#define NOW() TIMER_REG_READ(FRC2_COUNT_ADDRESS)
//load initial_value to timer1
#define FRC1_LOAD_ADDRESS (PERIPHS_TIMER_BASEDDR +0x00)
#define FRC1_LOAD_DATA_MSB 22
#define FRC1_LOAD_DATA_LSB 0
#define FRC1_LOAD_DATA_MASK 0x007fffff
//interrupt cpu using table, Please see the core-isa.h
/*************************************************************************************************************
* Intr num Level Type PRO CPU usage APP CPU uasge
* 0 1 extern level WMAC Reserved
* 1 1 extern level BT/BLE Host Reserved
* 2 1 extern level FROM_CPU FROM_CPU
* 3 1 extern level TG0_WDT Reserved
* 4 1 extern level WBB
* 5 1 extern level Reserved
* 6 1 timer FreeRTOS Tick(L1) FreeRTOS Tick(L1)
* 7 1 software Reserved Reserved
* 8 1 extern level Reserved
* 9 1 extern level
* 10 1 extern edge Internal Timer
* 11 3 profiling
* 12 1 extern level
* 13 1 extern level
* 14 7 nmi Reserved Reserved
* 15 3 timer FreeRTOS Tick(L3) FreeRTOS Tick(L3)
* 16 5 timer
* 17 1 extern level
* 18 1 extern level
* 19 2 extern level
* 20 2 extern level
* 21 2 extern level
* 22 3 extern edge
* 23 3 extern level
* 24 4 extern level
* 25 4 extern level Reserved Reserved
* 26 5 extern level Reserved Reserved
* 27 3 extern level Reserved Reserved
* 28 4 extern edge
* 29 3 software Reserved Reserved
* 30 4 extern edge Reserved Reserved
* 31 5 extern level Reserved Reserved
*************************************************************************************************************
*/
//timer1's counter value(count from initial_value to 0)
#define FRC1_COUNT_ADDRESS (PERIPHS_TIMER_BASEDDR +0x04)
#define FRC1_COUNT_DATA_MSB 22
#define FRC1_COUNT_DATA_LSB 0
#define FRC1_COUNT_DATA_MASK 0x007fffff
//CPU0 Interrupt number reserved, not touch this.
#define ETS_WMAC_INUM 0
#define ETS_BT_HOST_INUM 1
#define ETS_FROM_CPU_INUM 2
#define ETS_T0_WDT_INUM 3
#define ETS_WBB_INUM 4
#define ETS_TG0_T1_INUM 10 /**< use edge interrupt*/
#define FRC1_CTRL_ADDRESS (PERIPHS_TIMER_BASEDDR +0x08)
#define FRC1_CTRL_DATA_MSB 7
#define FRC1_CTRL_DATA_LSB 0
#define FRC1_CTRL_DATA_MASK 0x000000ff
//CPU0 Intrrupt number used in ROM, should be cancelled in SDK
#define ETS_SLC_INUM 1
#define ETS_UART0_INUM 5
#define ETS_UART1_INUM 5
//clear timer1's interrupt when write this address
#define FRC1_INT_ADDRESS (PERIPHS_TIMER_BASEDDR +0x0c)
#define FRC1_INT_CLR_MSB 0
#define FRC1_INT_CLR_LSB 0
#define FRC1_INT_CLR_MASK 0x00000001
//only used for simulation
#define FRC1_TEST_ADDRESS (PERIPHS_TIMER_BASEDDR +0x10)
#define FRC1_TEST_MODE_MSB 0
#define FRC1_TEST_MODE_LSB 0
#define FRC1_TEST_MODE_MASK 0x00000001
//load initial_value to timer2
#define FRC2_LOAD_ADDRESS (PERIPHS_TIMER_BASEDDR +0x20)
#define FRC2_LOAD_DATA_MSB 31
#define FRC2_LOAD_DATA_LSB 0
#define FRC2_LOAD_DATA_MASK 0xffffffff
//timer2's counter value(count from initial_value to 0)
#define FRC2_COUNT_ADDRESS (PERIPHS_TIMER_BASEDDR +0x24)
#define FRC2_COUNT_DATA_MSB 31
#define FRC2_COUNT_DATA_LSB 0
#define FRC2_COUNT_DATA_MASK 0xffffffff
#define FRC2_CTRL_ADDRESS (PERIPHS_TIMER_BASEDDR +0x28)
#define FRC2_CTRL_DATA_MSB 7
#define FRC2_CTRL_DATA_LSB 0
#define FRC2_CTRL_DATA_MASK 0x000000ff
//clear interrupt when write this address
#define FRC2_INT_ADDRESS (PERIPHS_TIMER_BASEDDR +0x2c)
#define FRC2_INT_CLR_MSB 0
#define FRC2_INT_CLR_LSB 0
#define FRC2_INT_CLR_MASK 0x00000001
//set Alarm_value for timer2 to generate interrupt
#define FRC2_ALARM_ADDRESS (PERIPHS_TIMER_BASEDDR +0x30)
#define FRC2_ALARM_DATA_MSB 31
#define FRC2_ALARM_DATA_LSB 0
#define FRC2_ALARM_DATA_MASK 0xffffffff
// }}
#define SPI_ENCRYPT_CNTL (PERIPHS_SPI_ENCRYPT_BASEADDR + 0x20)
#define SPI_ENCRYPT_CNTL_ENA BIT(0)
#define SPI_ENCRYPT_ADDR (PERIPHS_SPI_ENCRYPT_BASEADDR + 0x24)
#define SPI_ENCRYPT_CHECKDONE (PERIPHS_SPI_ENCRYPT_BASEADDR + 0x28)
#define SPI_ENCRYPT_CHECKDONE_STATUS BIT(0)
#endif /* _ESP32_SOC_H_ */

View File

@ -16,7 +16,7 @@
#include "soc.h"
#define T0CONFIG (DR_REG_TIMERS_BASE + 0x0000)
#define T0CONFIG(i) (DR_REG_TIMERS_BASE(i) + 0x0000)
#define TIMERS_T0_EN (BIT(31))
#define TIMERS_T0_EN_S 31
#define TIMERS_T0_INCREASE (BIT(30))
@ -32,39 +32,39 @@
#define TIMERS_T0_ALARM_EN (BIT(10))
#define TIMERS_T0_ALARM_EN_S 10
#define T0LO (DR_REG_TIMERS_BASE + 0x0004)
#define T0LO(i) (DR_REG_TIMERS_BASE(i) + 0x0004)
#define TIMERS_T0_LO 0xFFFFFFFF
#define TIMERS_T0_LO_S 0
#define T0HI (DR_REG_TIMERS_BASE + 0x0008)
#define T0HI(i) (DR_REG_TIMERS_BASE(i) + 0x0008)
#define TIMERS_T0_HI 0xFFFFFFFF
#define TIMERS_T0_HI_S 0
#define T0UPDATE (DR_REG_TIMERS_BASE + 0x000c)
#define T0UPDATE(i) (DR_REG_TIMERS_BASE(i) + 0x000c)
#define TIMERS_T0_UPDATE 0xFFFFFFFF
#define TIMERS_T0_UPDATE_S 0
#define T0ALARMLO (DR_REG_TIMERS_BASE + 0x0010)
#define T0ALARMLO(i) (DR_REG_TIMERS_BASE(i) + 0x0010)
#define TIMERS_T0_ALARM_LO 0xFFFFFFFF
#define TIMERS_T0_ALARM_LO_S 0
#define T0ALARMHI (DR_REG_TIMERS_BASE + 0x0014)
#define T0ALARMHI(i) (DR_REG_TIMERS_BASE(i) + 0x0014)
#define TIMERS_T0_ALARM_HI 0xFFFFFFFF
#define TIMERS_T0_ALARM_HI_S 0
#define T0LOADLO (DR_REG_TIMERS_BASE + 0x0018)
#define T0LOADLO(i) (DR_REG_TIMERS_BASE(i) + 0x0018)
#define TIMERS_T0_LOAD_LO 0xFFFFFFFF
#define TIMERS_T0_LOAD_LO_S 0
#define T0LOADHI (DR_REG_TIMERS_BASE + 0x001c)
#define T0LOADHI(i) (DR_REG_TIMERS_BASE(i) + 0x001c)
#define TIMERS_T0_LOAD_HI 0xFFFFFFFF
#define TIMERS_T0_LOAD_HI_S 0
#define T0LOAD (DR_REG_TIMERS_BASE + 0x0020)
#define T0LOAD(i) (DR_REG_TIMERS_BASE(i) + 0x0020)
#define TIMERS_T0_LOAD 0xFFFFFFFF
#define TIMERS_T0_LOAD_S 0
#define T1CONFIG (DR_REG_TIMERS_BASE + 0x0024)
#define T1CONFIG(i) (DR_REG_TIMERS_BASE(i) + 0x0024)
#define TIMERS_T1_EN (BIT(31))
#define TIMERS_T1_EN_S 31
#define TIMERS_T1_INCREASE (BIT(30))
@ -80,39 +80,39 @@
#define TIMERS_T1_ALARM_EN (BIT(10))
#define TIMERS_T1_ALARM_EN_S 10
#define T1LO (DR_REG_TIMERS_BASE + 0x0028)
#define T1LO(i) (DR_REG_TIMERS_BASE(i) + 0x0028)
#define TIMERS_T1_LO 0xFFFFFFFF
#define TIMERS_T1_LO_S 0
#define T1HI (DR_REG_TIMERS_BASE + 0x002c)
#define T1HI(i) (DR_REG_TIMERS_BASE(i) + 0x002c)
#define TIMERS_T1_HI 0xFFFFFFFF
#define TIMERS_T1_HI_S 0
#define T1UPDATE (DR_REG_TIMERS_BASE + 0x0030)
#define T1UPDATE(i) (DR_REG_TIMERS_BASE(i) + 0x0030)
#define TIMERS_T1_UPDATE 0xFFFFFFFF
#define TIMERS_T1_UPDATE_S 0
#define T1ALARMLO (DR_REG_TIMERS_BASE + 0x0034)
#define T1ALARMLO(i) (DR_REG_TIMERS_BASE(i) + 0x0034)
#define TIMERS_T1_ALARM_LO 0xFFFFFFFF
#define TIMERS_T1_ALARM_LO_S 0
#define T1ALARMHI (DR_REG_TIMERS_BASE + 0x0038)
#define T1ALARMHI(i) (DR_REG_TIMERS_BASE(i) + 0x0038)
#define TIMERS_T1_ALARM_HI 0xFFFFFFFF
#define TIMERS_T1_ALARM_HI_S 0
#define T1LOADLO (DR_REG_TIMERS_BASE + 0x003c)
#define T1LOADLO(i) (DR_REG_TIMERS_BASE(i) + 0x003c)
#define TIMERS_T1_LOAD_LO 0xFFFFFFFF
#define TIMERS_T1_LOAD_LO_S 0
#define T1LOADHI (DR_REG_TIMERS_BASE + 0x0040)
#define T1LOADHI(i) (DR_REG_TIMERS_BASE(i) + 0x0040)
#define TIMERS_T1_LOAD_HI 0xFFFFFFFF
#define TIMERS_T1_LOAD_HI_S 0
#define T1LOAD (DR_REG_TIMERS_BASE + 0x0044)
#define T1LOAD(i) (DR_REG_TIMERS_BASE(i) + 0x0044)
#define TIMERS_T1_LOAD 0xFFFFFFFF
#define TIMERS_T1_LOAD_S 0
#define WDTCONFIG0 (DR_REG_TIMERS_BASE + 0x0048)
#define WDTCONFIG0(i) (DR_REG_TIMERS_BASE(i) + 0x0048)
#define TIMERS_WDT_EN (BIT(31))
#define TIMERS_WDT_EN_S 31
#define TIMERS_WDT_STG0 0x00000003
@ -134,35 +134,35 @@
#define TIMERS_WDT_FLASHBOOT_MOD_EN (BIT(14))
#define TIMERS_WDT_FLASHBOOT_MOD_EN_S 14
#define WDTCONFIG1 (DR_REG_TIMERS_BASE + 0x004c)
#define WDTCONFIG1(i) (DR_REG_TIMERS_BASE(i) + 0x004c)
#define TIMERS_WDT_CLK_PRESCALE 0x0000FFFF
#define TIMERS_WDT_CLK_PRESCALE_S 16
#define WDTCONFIG2 (DR_REG_TIMERS_BASE + 0x0050)
#define WDTCONFIG2(i) (DR_REG_TIMERS_BASE(i) + 0x0050)
#define TIMERS_WDT_STG0_HOLD 0xFFFFFFFF
#define TIMERS_WDT_STG0_HOLD_S 0
#define WDTCONFIG3 (DR_REG_TIMERS_BASE + 0x0054)
#define WDTCONFIG3(i) (DR_REG_TIMERS_BASE(i) + 0x0054)
#define TIMERS_WDT_STG1_HOLD 0xFFFFFFFF
#define TIMERS_WDT_STG1_HOLD_S 0
#define WDTCONFIG4 (DR_REG_TIMERS_BASE + 0x0058)
#define WDTCONFIG4(i) (DR_REG_TIMERS_BASE(i) + 0x0058)
#define TIMERS_WDT_STG2_HOLD 0xFFFFFFFF
#define TIMERS_WDT_STG2_HOLD_S 0
#define WDTCONFIG5 (DR_REG_TIMERS_BASE + 0x005c)
#define WDTCONFIG5(i) (DR_REG_TIMERS_BASE(i) + 0x005c)
#define TIMERS_WDT_STG3_HOLD 0xFFFFFFFF
#define TIMERS_WDT_STG3_HOLD_S 0
#define WDTFEED (DR_REG_TIMERS_BASE + 0x0060)
#define WDTFEED(i) (DR_REG_TIMERS_BASE(i) + 0x0060)
#define TIMERS_WDT_FEED 0xFFFFFFFF
#define TIMERS_WDT_FEED_S 0
#define WDTWPROTECT (DR_REG_TIMERS_BASE + 0x0064)
#define WDTWPROTECT(i) (DR_REG_TIMERS_BASE(i) + 0x0064)
#define TIMERS_WDT_WKEY 0xFFFFFFFF
#define TIMERS_WDT_WKEY_S 0
#define RTCCALICFG (DR_REG_TIMERS_BASE + 0x0068)
#define RTCCALICFG(i) (DR_REG_TIMERS_BASE(i) + 0x0068)
#define TIMERS_RTC_CALI_START (BIT(31))
#define TIMERS_RTC_CALI_START_S 31
#define TIMERS_RTC_CALI_MAX 0x00007FFF
@ -174,11 +174,11 @@
#define TIMERS_RTC_CALI_START_CYCLING (BIT(12))
#define TIMERS_RTC_CALI_START_CYCLING_S 12
#define RTCCALICFG1 (DR_REG_TIMERS_BASE + 0x006c)
#define RTCCALICFG1(i) (DR_REG_TIMERS_BASE(i) + 0x006c)
#define TIMERS_RTC_CALI_VALUE 0x01FFFFFF
#define TIMERS_RTC_CALI_VALUE_S 7
#define LACTCONFIG (DR_REG_TIMERS_BASE + 0x0070)
#define LACTCONFIG(i) (DR_REG_TIMERS_BASE(i) + 0x0070)
#define TIMERS_LACT_EN (BIT(31))
#define TIMERS_LACT_EN_S 31
#define TIMERS_LACT_INCREASE (BIT(30))
@ -200,43 +200,43 @@
#define TIMERS_LACT_RTC_ONLY (BIT(7))
#define TIMERS_LACT_RTC_ONLY_S 7
#define LACTRTC (DR_REG_TIMERS_BASE + 0x0074)
#define LACTRTC(i) (DR_REG_TIMERS_BASE(i) + 0x0074)
#define TIMERS_LACT_RTC_STEP_LEN 0x03FFFFFF
#define TIMERS_LACT_RTC_STEP_LEN_S 6
#define LACTLO (DR_REG_TIMERS_BASE + 0x0078)
#define LACTLO(i) (DR_REG_TIMERS_BASE(i) + 0x0078)
#define TIMERS_LACT_LO 0xFFFFFFFF
#define TIMERS_LACT_LO_S 0
#define LACTHI (DR_REG_TIMERS_BASE + 0x007c)
#define LACTHI(i) (DR_REG_TIMERS_BASE(i) + 0x007c)
#define TIMERS_LACT_HI 0xFFFFFFFF
#define TIMERS_LACT_HI_S 0
#define LACTUPDATE (DR_REG_TIMERS_BASE + 0x0080)
#define LACTUPDATE(i) (DR_REG_TIMERS_BASE(i) + 0x0080)
#define TIMERS_LACT_UPDATE 0xFFFFFFFF
#define TIMERS_LACT_UPDATE_S 0
#define LACTALARMLO (DR_REG_TIMERS_BASE + 0x0084)
#define LACTALARMLO(i) (DR_REG_TIMERS_BASE(i) + 0x0084)
#define TIMERS_LACT_ALARM_LO 0xFFFFFFFF
#define TIMERS_LACT_ALARM_LO_S 0
#define LACTALARMHI (DR_REG_TIMERS_BASE + 0x0088)
#define LACTALARMHI(i) (DR_REG_TIMERS_BASE(i) + 0x0088)
#define TIMERS_LACT_ALARM_HI 0xFFFFFFFF
#define TIMERS_LACT_ALARM_HI_S 0
#define LACTLOADLO (DR_REG_TIMERS_BASE + 0x008c)
#define LACTLOADLO(i) (DR_REG_TIMERS_BASE(i) + 0x008c)
#define TIMERS_LACT_LOAD_LO 0xFFFFFFFF
#define TIMERS_LACT_LOAD_LO_S 0
#define LACTLOADHI (DR_REG_TIMERS_BASE + 0x0090)
#define LACTLOADHI(i) (DR_REG_TIMERS_BASE(i) + 0x0090)
#define TIMERS_LACT_LOAD_HI 0xFFFFFFFF
#define TIMERS_LACT_LOAD_HI_S 0
#define LACTLOAD (DR_REG_TIMERS_BASE + 0x0094)
#define LACTLOAD(i) (DR_REG_TIMERS_BASE(i) + 0x0094)
#define TIMERS_LACT_LOAD 0xFFFFFFFF
#define TIMERS_LACT_LOAD_S 0
#define INT_ENA_TIMERS (DR_REG_TIMERS_BASE + 0x0098)
#define INT_ENA_TIMERS(i) (DR_REG_TIMERS_BASE(i) + 0x0098)
#define TIMERS_LACT_INT_ENA (BIT(3))
#define TIMERS_LACT_INT_ENA_S 3
#define TIMERS_WDT_INT_ENA (BIT(2))
@ -246,7 +246,7 @@
#define TIMERS_T0_INT_ENA (BIT(0))
#define TIMERS_T0_INT_ENA_S 0
#define INT_RAW_TIMERS (DR_REG_TIMERS_BASE + 0x009c)
#define INT_RAW_TIMERS(i) (DR_REG_TIMERS_BASE(i) + 0x009c)
#define TIMERS_LACT_INT_RAW (BIT(3))
#define TIMERS_LACT_INT_RAW_S 3
#define TIMERS_WDT_INT_RAW (BIT(2))
@ -256,7 +256,7 @@
#define TIMERS_T0_INT_RAW (BIT(0))
#define TIMERS_T0_INT_RAW_S 0
#define INT_ST_TIMERS (DR_REG_TIMERS_BASE + 0x00a0)
#define INT_ST_TIMERS(i) (DR_REG_TIMERS_BASE(i) + 0x00a0)
#define TIMERS_LACT_INT_ST (BIT(3))
#define TIMERS_LACT_INT_ST_S 3
#define TIMERS_WDT_INT_ST (BIT(2))
@ -266,7 +266,7 @@
#define TIMERS_T0_INT_ST (BIT(0))
#define TIMERS_T0_INT_ST_S 0
#define INT_CLR_TIMERS (DR_REG_TIMERS_BASE + 0x00a4)
#define INT_CLR_TIMERS(i) (DR_REG_TIMERS_BASE(i) + 0x00a4)
#define TIMERS_LACT_INT_CLR (BIT(3))
#define TIMERS_LACT_INT_CLR_S 3
#define TIMERS_WDT_INT_CLR (BIT(2))
@ -276,12 +276,12 @@
#define TIMERS_T0_INT_CLR (BIT(0))
#define TIMERS_T0_INT_CLR_S 0
#define NTIMERS_DATE (DR_REG_TIMERS_BASE + 0x00f8)
#define NTIMERS_DATE(i) (DR_REG_TIMERS_BASE(i) + 0x00f8)
#define TIMERS_NTIMERS_DATE 0x0FFFFFFF
#define TIMERS_NTIMERS_DATE_S 0
#define TIMERS_NTIMERS_DATE_VERSION 0x1604290
#define REGCLK (DR_REG_TIMERS_BASE + 0x00fc)
#define REGCLK(i) (DR_REG_TIMERS_BASE(i) + 0x00fc)
#define TIMERS_CLK_EN (BIT(31))
#define TIMERS_CLK_EN_S 31

117
components/esp32/ipc.c Normal file
View File

@ -0,0 +1,117 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "esp_err.h"
#include "esp_ipc.h"
#include "esp_attr.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
static TaskHandle_t s_ipc_tasks[portNUM_PROCESSORS]; // Two high priority tasks, one for each CPU
static SemaphoreHandle_t s_ipc_mutex; // This mutex is used as a global lock for esp_ipc_* APIs
static SemaphoreHandle_t s_ipc_sem[portNUM_PROCESSORS]; // Two semaphores used to wake each of s_ipc_tasks
static SemaphoreHandle_t s_ipc_ack; // Semaphore used to acknowledge that task was woken up,
// or function has finished running
static volatile esp_ipc_func_t s_func; // Function which should be called by high priority task
static void * volatile s_func_arg; // Argument to pass into s_func
typedef enum {
IPC_WAIT_FOR_START,
IPC_WAIT_FOR_END
} esp_ipc_wait_t;
static volatile esp_ipc_wait_t s_ipc_wait; // This variable tells high priority task when it should give
// s_ipc_ack semaphore: before s_func is called, or
// after it returns
static void IRAM_ATTR ipc_task(void* arg)
{
const uint32_t cpuid = (uint32_t) arg;
assert(cpuid == xPortGetCoreID());
while (true) {
// Wait for IPC to be initiated.
// This will be indicated by giving the semaphore corresponding to
// this CPU.
if (xSemaphoreTake(s_ipc_sem[cpuid], portMAX_DELAY) != pdTRUE) {
// TODO: when can this happen?
abort();
}
esp_ipc_func_t func = s_func;
void* arg = s_func_arg;
if (s_ipc_wait == IPC_WAIT_FOR_START) {
xSemaphoreGive(s_ipc_ack);
}
(*func)(arg);
if (s_ipc_wait == IPC_WAIT_FOR_END) {
xSemaphoreGive(s_ipc_ack);
}
}
// TODO: currently this is unreachable code. Introduce esp_ipc_uninit
// function which will signal to both tasks that they can shut down.
// Not critical at this point, we don't have a use case for stopping
// IPC yet.
// Also need to delete the semaphore here.
vTaskDelete(NULL);
}
void esp_ipc_init()
{
s_ipc_mutex = xSemaphoreCreateMutex();
s_ipc_ack = xSemaphoreCreateBinary();
const char* task_names[2] = {"ipc0", "ipc1"};
for (int i = 0; i < portNUM_PROCESSORS; ++i) {
s_ipc_sem[i] = xSemaphoreCreateBinary();
xTaskCreatePinnedToCore(ipc_task, task_names[i], XT_STACK_MIN_SIZE, (void*) i,
configMAX_PRIORITIES - 1, &s_ipc_tasks[i], i);
}
}
static esp_err_t esp_ipc_call_and_wait(uint32_t cpu_id, esp_ipc_func_t func, void* arg, esp_ipc_wait_t wait_for)
{
if (cpu_id >= portNUM_PROCESSORS) {
return ESP_ERR_INVALID_ARG;
}
if (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING) {
return ESP_ERR_INVALID_STATE;
}
xSemaphoreTake(s_ipc_mutex, portMAX_DELAY);
s_func = func;
s_func_arg = arg;
s_ipc_wait = IPC_WAIT_FOR_START;
xSemaphoreGive(s_ipc_sem[cpu_id]);
xSemaphoreTake(s_ipc_ack, portMAX_DELAY);
xSemaphoreGive(s_ipc_mutex);
return ESP_OK;
}
esp_err_t esp_ipc_call(uint32_t cpu_id, esp_ipc_func_t func, void* arg)
{
return esp_ipc_call_and_wait(cpu_id, func, arg, IPC_WAIT_FOR_START);
}
esp_err_t esp_ipc_call_blocking(uint32_t cpu_id, esp_ipc_func_t func, void* arg)
{
return esp_ipc_call_and_wait(cpu_id, func, arg, IPC_WAIT_FOR_END);
}

View File

@ -64,6 +64,8 @@ PROVIDE ( Cache_Read_Disable = 0x40009ab8 );
PROVIDE ( Cache_Read_Enable = 0x40009a84 );
PROVIDE ( Cache_Read_Init = 0x40009950 );
PROVIDE ( cache_sram_mmu_set = 0x400097f4 );
/* This is static function, but can be used, not generated by script*/
PROVIDE ( calc_rtc_memory_crc = 0x40008170 );
PROVIDE ( calloc = 0x4000bee4 );
PROVIDE ( _calloc_r = 0x4000bbf8 );
PROVIDE ( check_pos = 0x400068b8 );
@ -1585,12 +1587,20 @@ PROVIDE ( SPIParamCfg = 0x40063238 );
PROVIDE ( SPI_Prepare_Encrypt_Data = 0x40062e1c );
PROVIDE ( SPIRead = 0x40062ed8 );
PROVIDE ( SPIReadModeCnfig = 0x40062944 );
/* This is static function, but can be used, not generated by script*/
PROVIDE ( SPI_read_status = 0x4006226c );
/* This is static function, but can be used, not generated by script*/
PROVIDE ( SPI_read_status_high = 0x40062448 );
PROVIDE ( SPIUnlock = 0x400628b0 );
PROVIDE ( SPI_user_command_read = 0x400621b0 );
PROVIDE ( spi_w25q16 = 0x3ffae270 );
PROVIDE ( SPIWrite = 0x40062d50 );
/* This is static function, but can be used, not generated by script*/
PROVIDE ( SPI_write_enable = 0x40062320 );
PROVIDE ( SPI_Write_Encrypt_Disable = 0x40062e60 );
PROVIDE ( SPI_Write_Encrypt_Enable = 0x40062df4 );
/* This is static function, but can be used, not generated by script*/
PROVIDE ( SPI_write_status = 0x400622f0 );
PROVIDE ( sprintf = 0x40056c08 );
PROVIDE ( _sprintf_r = 0x40056bbc );
PROVIDE ( __sprint_r = 0x400577e4 );
@ -1826,4 +1836,4 @@ PROVIDE ( _xtos_unhandled_exception = 0x4000c024 );
PROVIDE ( _xtos_unhandled_interrupt = 0x4000c01c );
PROVIDE ( _xtos_vpri_enabled = 0x3ffe0654 );
PROVIDE ( I2S0 = 0x6000F000 );
PROVIDE ( I2S0 = 0x6000F000 );

@ -1 +1 @@
Subproject commit b95a359c344cd052f45e3c38515e4613dd29f298
Subproject commit e793e8ac04cae3a5ca87bbccc46021a93288df05

View File

@ -44,10 +44,17 @@ void _free_r(struct _reent *r, void* ptr) {
return vPortFree(ptr);
}
// TODO: improve realloc to grow buffer in place if possible
void* _realloc_r(struct _reent *r, void* ptr, size_t size) {
void* new_chunk = pvPortMalloc(size);
if (new_chunk) {
void* new_chunk;
if (size == 0) {
if (ptr) {
vPortFree(ptr);
}
return NULL;
}
new_chunk = pvPortMalloc(size);
if (new_chunk && ptr) {
memcpy(new_chunk, ptr, size);
vPortFree(ptr);
}

View File

@ -11,6 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
@ -26,9 +27,12 @@
#if CONFIG_WIFI_ENABLED
static wifi_startup_cb_t startup_cb;
static bool wifi_startup_flag = false;
#define WIFI_DEBUG(...)
static wifi_startup_cb_t startup_cb;
static void *startup_ctx;
#define WIFI_DEBUG(...)
#define WIFI_API_CALL_CHECK(info, api_call, ret) \
do{\
esp_err_t __err = (api_call);\
@ -54,7 +58,7 @@ static void esp_wifi_task(void *pvParameters)
}
if (startup_cb) {
err = (*startup_cb)();
err = (*startup_cb)(startup_ctx);
if (err != ESP_OK) {
WIFI_DEBUG("startup_cb fail, ret=%d\n", err);
break;
@ -71,7 +75,7 @@ static void esp_wifi_task(void *pvParameters)
wifi_mode_t mode;
bool auto_connect;
err = esp_wifi_get_mode(&mode);
if (err != ESP_OK){
if (err != ESP_OK) {
WIFI_DEBUG("esp_wifi_get_mode fail, ret=%d\n", err);
}
@ -94,9 +98,17 @@ static void esp_wifi_task(void *pvParameters)
vTaskDelete(NULL);
}
void esp_wifi_startup(wifi_startup_cb_t cb)
esp_err_t esp_wifi_startup(wifi_startup_cb_t cb, void *ctx)
{
if (wifi_startup_flag) {
return ESP_FAIL;
}
startup_cb = cb;
startup_ctx = ctx;
xTaskCreatePinnedToCore(esp_wifi_task, "wifiTask", 4096, NULL, 5, NULL, 0);// TODO: rearrange task priority
return ESP_OK;
}
#endif

View File

@ -11,19 +11,23 @@ PYTHON ?= $(call dequote,$(CONFIG_PYTHON))
# to invoke esptool.py (with or without serial port args)
#
# NB: esptool.py lives in the sdk/bin directory not the component directory
ESPTOOLPY := $(PYTHON) $(IDF_PATH)/bin/esptool.py --chip esp32
ESPTOOLPY_SRC := $(COMPONENT_PATH)/esptool/esptool.py
ESPTOOLPY := $(PYTHON) $(ESPTOOLPY_SRC) --chip esp32
ESPTOOLPY_SERIAL := $(ESPTOOLPY) --port $(ESPPORT) --baud $(ESPBAUD)
ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) write_flash $(if $(CONFIG_ESPTOOLPY_COMPRESSED),-z) --flash_mode $(ESPFLASHMODE) --flash_freq $(ESPFLASHFREQ)
# the no-stub argument is temporary until esptool.py fully supports compressed uploads
ESPTOOLPY_WRITE_FLASH=$(ESPTOOLPY_SERIAL) $(if $(CONFIG_ESPTOOLPY_COMPRESSED),--no-stub) write_flash $(if $(CONFIG_ESPTOOLPY_COMPRESSED),-z) --flash_mode $(ESPFLASHMODE) --flash_freq $(ESPFLASHFREQ)
ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_APP_OFFSET) $(APP_BIN)
$(APP_BIN): $(APP_ELF)
$(APP_BIN): $(APP_ELF) $(ESPTOOLPY_SRC)
$(Q) $(ESPTOOLPY) elf2image --flash_mode $(ESPFLASHMODE) --flash_freq $(ESPFLASHFREQ) -o $@ $<
flash: all_binaries
flash: all_binaries $(ESPTOOLPY_SRC)
@echo "Flashing project app to $(CONFIG_APP_OFFSET)..."
$(Q) $(ESPTOOLPY_WRITE_FLASH) $(ESPTOOL_ALL_FLASH_ARGS)
app-flash: $(APP_BIN)
app-flash: $(APP_BIN) $(ESPTOOLPY_SRC)
$(Q) $(ESPTOOLPY_WRITE_FLASH) $(CONFIG_APP_OFFSET) $(APP_BIN)
$(eval $(call SubmoduleRequiredForFiles,$(ESPTOOLPY_SRC)))

@ -0,0 +1 @@
Subproject commit 7c84dd433512bac80e4c01c569e42b4fe76646a7

View File

@ -6,4 +6,4 @@ COMPONENT_ADD_LDFLAGS = -l$(COMPONENT_NAME) -Wl,--undefined=uxTopUsedPriority
COMPONENT_ADD_INCLUDEDIRS := include
COMPONENT_PRIV_INCLUDEDIRS := include/freertos
include $(IDF_PATH)/make/component.mk
include $(IDF_PATH)/make/component_common.mk

View File

@ -167,6 +167,9 @@ typedef struct {
#define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); } while (0)
#define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE(0); XTOS_SET_INTLEVEL(0); } while (0)
#define portASSERT_IF_IN_ISR() vPortAssertIfInISR()
void vPortAssertIfInISR();
#define portCRITICAL_NESTING_IN_TCB 1
/*
@ -213,6 +216,7 @@ portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux);
// Cleaner and preferred solution allows nested interrupts disabling and restoring via local registers or stack.
// They can be called from interrupts too.
//NOT SMP-COMPATIBLE! Use only if all you want is to disable the interrupts locally!
static inline unsigned portENTER_CRITICAL_NESTED() { unsigned state = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); portbenchmarkINTERRUPT_DISABLE(); return state; }
#define portEXIT_CRITICAL_NESTED(state) do { portbenchmarkINTERRUPT_RESTORE(state); XTOS_RESTORE_JUST_INTLEVEL(state); } while (0)

View File

@ -248,14 +248,17 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMOR
#endif
void vPortAssertIfInISR()
{
configASSERT(port_interruptNesting[xPortGetCoreID()]==0)
}
/*
* Wrapper for the Xtensa compare-and-set instruction. This subroutine will atomically compare
* *mux to compare, and if it's the same, will set *mux to set. It will return the old value
* of *addr.
*
* Note: the NOPs are needed on the ESP31 processor but superfluous on the ESP32.
*
* Warning: From the ISA docs: in some (unspecified) cases, the s32c1i instruction may return the
* *bitwise inverse* of the old mem if the mem wasn't written. This doesn't seem to happen on the
* ESP32, though. (Would show up directly if it did because the magic wouldn't match.)

View File

@ -163,6 +163,7 @@ typedef struct tskTaskControlBlock
#if ( portCRITICAL_NESTING_IN_TCB == 1 )
UBaseType_t uxCriticalNesting; /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
uint32_t uxOldInterruptState; /*< Interrupt state before the outer taskEnterCritical was called */
#endif
#if ( configUSE_TRACE_FACILITY == 1 )
@ -2595,8 +2596,7 @@ BaseType_t xReturn;
/* THIS FUNCTION MUST BE CALLED FROM A CRITICAL SECTION. It can also be
called from a critical section within an ISR. */
//That makes the taskENTER_CRITICALs here unnecessary, right? -JD
// taskENTER_CRITICAL(&xTaskQueueMutex);
taskENTER_CRITICAL_ISR(&xTaskQueueMutex);
/* The event list is sorted in priority order, so the first in the list can
be removed as it is known to be the highest priority. Remove the TCB from
the delayed list, and add it to the ready list.
@ -2654,7 +2654,7 @@ BaseType_t xReturn;
prvResetNextTaskUnblockTime();
}
#endif
// taskEXIT_CRITICAL(&xTaskQueueMutex);
taskEXIT_CRITICAL_ISR(&xTaskQueueMutex);
return xReturn;
}
@ -3614,6 +3614,7 @@ In fact, nothing below this line has/is.
{
if( pxTCB->uxPriority < pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
{
taskENTER_CRITICAL(&xTaskQueueMutex);
/* Adjust the mutex holder state to account for its new
priority. Only reset the event list item value if the value is
not being used for anything else. */
@ -3649,6 +3650,8 @@ In fact, nothing below this line has/is.
pxTCB->uxPriority = pxCurrentTCB[ xPortGetCoreID() ]->uxPriority;
}
taskEXIT_CRITICAL(&xTaskQueueMutex);
traceTASK_PRIORITY_INHERIT( pxTCB, pxCurrentTCB[ xPortGetCoreID() ]->uxPriority );
}
else
@ -3686,6 +3689,7 @@ In fact, nothing below this line has/is.
/* Only disinherit if no other mutexes are held. */
if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
{
taskENTER_CRITICAL(&xTaskQueueMutex);
/* A task can only have an inhertied priority if it holds
the mutex. If the mutex is held by a task then it cannot be
given from an interrupt, and if a mutex is given by the
@ -3720,6 +3724,7 @@ In fact, nothing below this line has/is.
switch should occur when the last mutex is returned whether
a task is waiting on it or not. */
xReturn = pdTRUE;
taskEXIT_CRITICAL(&xTaskQueueMutex);
}
else
{
@ -3761,7 +3766,14 @@ scheduler will re-enable the interrupts instead. */
void vTaskEnterCritical( portMUX_TYPE *mux )
#endif
{
portDISABLE_INTERRUPTS();
BaseType_t oldInterruptLevel=0;
if( xSchedulerRunning != pdFALSE )
{
//Interrupts may already be disabled (because we're doing this recursively) but we can't get the interrupt level after
//vPortCPUAquireMutex, because it also may mess with interrupts. Get it here first, then later figure out if we're nesting
//and save for real there.
oldInterruptLevel=portENTER_CRITICAL_NESTED();
}
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
vPortCPUAcquireMutex( mux, function, line );
#else
@ -3772,16 +3784,30 @@ scheduler will re-enable the interrupts instead. */
{
( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting )++;
/* This is not the interrupt safe version of the enter critical
if( xSchedulerRunning != pdFALSE && pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting == 1 )
{
//This is the first time we get called. Save original interrupt level.
pxCurrentTCB[ xPortGetCoreID() ]->uxOldInterruptState=oldInterruptLevel;
}
/* Original FreeRTOS comment, saved for reference:
This is not the interrupt safe version of the enter critical
function so assert() if it is being called from an interrupt
context. Only API functions that end in "FromISR" can be used in an
interrupt. Only assert if the critical nesting count is 1 to
protect against recursive calls if the assert function also uses a
critical section. */
/* DISABLED in the esp32 port - because of SMP, vTaskEnterCritical
has to be used in way more places than before, and some are called
both from ISR as well as non-ISR code, thus we re-organized
vTaskEnterCritical to also work in ISRs. */
#if 0
if( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting == 1 )
{
portASSERT_IF_IN_ISR();
}
#endif
}
else
@ -3814,7 +3840,7 @@ scheduler will re-enable the interrupts instead. */
if( pxCurrentTCB[ xPortGetCoreID() ]->uxCriticalNesting == 0U )
{
portENABLE_INTERRUPTS();
portEXIT_CRITICAL_NESTED(pxCurrentTCB[ xPortGetCoreID() ]->uxOldInterruptState);
}
else
{

View File

@ -388,19 +388,30 @@ static void lwip_socket_drop_registered_memberships(int s);
#endif /* LWIP_IGMP */
#ifdef LWIP_ESP8266
extern size_t system_get_free_heap_size(void);
#define DELAY_WHEN_MEMORY_NOT_ENOUGH() \
do{\
uint8_t _wait_delay = 0;\
while (system_get_free_heap_size() < HEAP_HIGHWAT){\
vTaskDelay(_wait_delay/portTICK_RATE_MS);\
if (_wait_delay < 64) _wait_delay *= 2;\
}\
}while(0)
/* Since esp_wifi_tx_is_stop/system_get_free_heap_size are not an public wifi API, so extern them here*/
extern size_t system_get_free_heap_size(void);
extern bool esp_wifi_tx_is_stop(void);
/* Please be notified that this flow control is just a workaround for fixing wifi Q full issue.
* Under UDP/TCP pressure test, we found that the sockets may cause wifi tx queue full if the socket
* sending speed is faster than the wifi sending speed, it will finally cause the packet to be dropped
* in wifi layer, it's not acceptable in some application. That's why we introdue the tx flow control here.
* However, current solution is just a workaround, we need to consider the return value of wifi tx interface,
* and feedback the return value to lwip and let lwip do the flow control itself.
*/
static inline void esp32_tx_flow_ctrl(void)
{
uint8_t _wait_delay = 0;
while ((system_get_free_heap_size() < HEAP_HIGHWAT) || esp_wifi_tx_is_stop()){
vTaskDelay(_wait_delay/portTICK_RATE_MS);
if (_wait_delay < 64) _wait_delay *= 2;
}
}
#else
#define DELAY_WHEN_MEMORY_NOT_ENOUGH()
#define esp32_tx_flow_ctrl()
#endif
/** The global array of available sockets */
@ -1219,7 +1230,7 @@ lwip_send(int s, const void *data, size_t size, int flags)
#endif /* (LWIP_UDP || LWIP_RAW) */
}
DELAY_WHEN_MEMORY_NOT_ENOUGH();
esp32_tx_flow_ctrl();
write_flags = NETCONN_COPY |
((flags & MSG_MORE) ? NETCONN_MORE : 0) |
@ -1402,7 +1413,7 @@ lwip_sendto(int s, const void *data, size_t size, int flags,
#endif /* LWIP_TCP */
}
DELAY_WHEN_MEMORY_NOT_ENOUGH();
esp32_tx_flow_ctrl();
if ((to != NULL) && !SOCK_ADDR_TYPE_MATCH(to, sock)) {
/* sockaddr does not match socket type (IPv4/IPv6) */

View File

@ -6,6 +6,6 @@ COMPONENT_ADD_INCLUDEDIRS := include/lwip include/lwip/port
COMPONENT_SRCDIRS := api apps/sntp apps core/ipv4 core/ipv6 core netif port/freertos port/netif port
EXTRA_CFLAGS := -Wno-error=address -Waddress -DLWIP_ESP8266
EXTRA_CFLAGS := -Wno-error=address -Waddress
include $(IDF_PATH)/make/component.mk
include $(IDF_PATH)/make/component_common.mk

View File

@ -712,10 +712,10 @@ void dhcp_cleanup(struct netif *netif)
/* Espressif add start. */
/** Set callback for dhcp, reversed parameter for future use.
/** Set callback for dhcp, reserved parameter for future use.
*
* @param netif the netif from which to remove the struct dhcp
* @param cb callback for chcp
* @param cb callback for dhcp
*/
void dhcp_set_cb(struct netif *netif, void (*cb)(void))
{

View File

@ -68,7 +68,5 @@ void sys_delay_ms(uint32_t ms);
sys_sem_t* sys_thread_sem_init(void);
void sys_thread_sem_deinit(void);
sys_sem_t* sys_thread_sem_get(void);
#endif /* __SYS_ARCH_H__ */

View File

@ -34,6 +34,8 @@
#include <stdlib.h>
/* Enable all Espressif-only options */
#define LWIP_ESP8266
/*
-----------------------------------------------

View File

@ -5,4 +5,4 @@ define COMPONENT_BUILDRECIPE
#Nothing to do; this does not generate a library.
endef
include $(IDF_PATH)/make/component.mk
include $(IDF_PATH)/make/component_common.mk

View File

@ -6,4 +6,4 @@ COMPONENT_ADD_INCLUDEDIRS := include
COMPONENT_SRCDIRS := src
include $(IDF_PATH)/make/component.mk
include $(IDF_PATH)/make/component_common.mk

View File

@ -9,7 +9,7 @@
.PHONY: partition_table partition_table-flash partition_table-clean
# NB: gen_esp32part.py lives in the sdk/bin/ dir not component dir
GEN_ESP32PART := $(PYTHON) $(IDF_PATH)/bin/gen_esp32part.py -q
GEN_ESP32PART := $(PYTHON) $(COMPONENT_PATH)/gen_esp32part.py -q
# Path to partition CSV file is relative to project path for custom
# partition CSV files, but relative to component dir otherwise.$

View File

@ -1,3 +0,0 @@
COMPONENT_ADD_INCLUDEDIRS := include
include $(IDF_PATH)/make/component.mk

View File

@ -0,0 +1,3 @@
COMPONENT_ADD_INCLUDEDIRS := include
include $(IDF_PATH)/make/component_common.mk

View File

@ -12,15 +12,217 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdlib.h>
#include <assert.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
#include <esp_spi_flash.h>
#include <rom/spi_flash.h>
#include <rom/cache.h>
#include <esp_attr.h>
#include <soc/soc.h>
#include <soc/dport_reg.h>
#include "sdkconfig.h"
#include "esp_ipc.h"
#include "esp_attr.h"
#include "esp_spi_flash.h"
/*
Driver for SPI flash read/write/erase operations
In order to perform some flash operations, we need to make sure both CPUs
are not running any code from flash for the duration of the flash operation.
In a single-core setup this is easy: we disable interrupts/scheduler and do
the flash operation. In the dual-core setup this is slightly more complicated.
We need to make sure that the other CPU doesn't run any code from flash.
When SPI flash API is called on CPU A (can be PRO or APP), we start
spi_flash_op_block_func function on CPU B using esp_ipc_call API. This API
wakes up high priority task on CPU B and tells it to execute given function,
in this case spi_flash_op_block_func. This function disables cache on CPU B and
signals that cache is disabled by setting s_flash_op_can_start flag.
Then the task on CPU A disables cache as well, and proceeds to execute flash
operation.
While flash operation is running, interrupts can still run on CPU B.
We assume that all interrupt code is placed into RAM.
Once flash operation is complete, function on CPU A sets another flag,
s_flash_op_complete, to let the task on CPU B know that it can re-enable
cache and release the CPU. Then the function on CPU A re-enables the cache on
CPU A as well and returns control to the calling code.
Additionally, all API functions are protected with a mutex (s_flash_op_mutex).
In a single core environment (CONFIG_FREERTOS_UNICORE enabled), we simply
disable both caches, no inter-CPU communication takes place.
*/
static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc);
static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t* saved_state);
static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state);
static uint32_t s_flash_op_cache_state[2];
#ifndef CONFIG_FREERTOS_UNICORE
static SemaphoreHandle_t s_flash_op_mutex;
static bool s_flash_op_can_start = false;
static bool s_flash_op_complete = false;
#endif //CONFIG_FREERTOS_UNICORE
#ifndef CONFIG_FREERTOS_UNICORE
static void IRAM_ATTR spi_flash_op_block_func(void* arg)
{
// Disable scheduler on this CPU
vTaskSuspendAll();
uint32_t cpuid = (uint32_t) arg;
// Disable cache so that flash operation can start
spi_flash_disable_cache(cpuid, &s_flash_op_cache_state[cpuid]);
s_flash_op_can_start = true;
while (!s_flash_op_complete) {
// until we have a way to use interrupts for inter-CPU communication,
// busy loop here and wait for the other CPU to finish flash operation
}
// Flash operation is complete, re-enable cache
spi_flash_restore_cache(cpuid, s_flash_op_cache_state[cpuid]);
// Re-enable scheduler
xTaskResumeAll();
}
void spi_flash_init()
{
s_flash_op_mutex = xSemaphoreCreateMutex();
}
static void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu()
{
// Take the API lock
xSemaphoreTake(s_flash_op_mutex, portMAX_DELAY);
const uint32_t cpuid = xPortGetCoreID();
const uint32_t other_cpuid = (cpuid == 0) ? 1 : 0;
if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) {
// Scheduler hasn't been started yet, it means that spi_flash API is being
// called from the 2nd stage bootloader or from user_start_cpu0, i.e. from
// PRO CPU. APP CPU is either in reset or spinning inside user_start_cpu1,
// which is in IRAM. So it is safe to disable cache for the other_cpuid here.
assert(other_cpuid == 1);
spi_flash_disable_cache(other_cpuid, &s_flash_op_cache_state[other_cpuid]);
} else {
// Signal to the spi_flash_op_block_task on the other CPU that we need it to
// disable cache there and block other tasks from executing.
s_flash_op_can_start = false;
s_flash_op_complete = false;
esp_ipc_call(other_cpuid, &spi_flash_op_block_func, (void*) other_cpuid);
while (!s_flash_op_can_start) {
// Busy loop and wait for spi_flash_op_block_func to disable cache
// on the other CPU
}
// Disable scheduler on CPU cpuid
vTaskSuspendAll();
// This is guaranteed to run on CPU <cpuid> because the other CPU is now
// occupied by highest priority task
assert(xPortGetCoreID() == cpuid);
}
// Disable cache on this CPU as well
spi_flash_disable_cache(cpuid, &s_flash_op_cache_state[cpuid]);
}
static void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu()
{
const uint32_t cpuid = xPortGetCoreID();
const uint32_t other_cpuid = (cpuid == 0) ? 1 : 0;
// Re-enable cache on this CPU
spi_flash_restore_cache(cpuid, s_flash_op_cache_state[cpuid]);
if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) {
// Scheduler is not running yet — this means we are running on PRO CPU.
// other_cpuid is APP CPU, and it is either in reset or is spinning in
// user_start_cpu1, which is in IRAM. So we can simply reenable cache.
assert(other_cpuid == 1);
spi_flash_restore_cache(other_cpuid, s_flash_op_cache_state[other_cpuid]);
} else {
// Signal to spi_flash_op_block_task that flash operation is complete
s_flash_op_complete = true;
// Resume tasks on the current CPU
xTaskResumeAll();
}
// Release API lock
xSemaphoreGive(s_flash_op_mutex);
}
#else // CONFIG_FREERTOS_UNICORE
void spi_flash_init()
{
// No-op in single core mode
}
static void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu()
{
vTaskSuspendAll();
spi_flash_disable_cache(0, &s_flash_op_cache_state[0]);
}
static void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu()
{
spi_flash_restore_cache(0, s_flash_op_cache_state[0]);
xTaskResumeAll();
}
#endif // CONFIG_FREERTOS_UNICORE
SpiFlashOpResult IRAM_ATTR spi_flash_unlock()
{
static bool unlocked = false;
if (!unlocked) {
SpiFlashOpResult rc = SPIUnlock();
if (rc != SPI_FLASH_RESULT_OK) {
return rc;
}
unlocked = true;
}
return SPI_FLASH_RESULT_OK;
}
esp_err_t IRAM_ATTR spi_flash_erase_sector(uint16_t sec)
{
spi_flash_disable_interrupts_caches_and_other_cpu();
SpiFlashOpResult rc;
rc = spi_flash_unlock();
if (rc == SPI_FLASH_RESULT_OK) {
rc = SPIEraseSector(sec);
}
spi_flash_enable_interrupts_caches_and_other_cpu();
return spi_flash_translate_rc(rc);
}
esp_err_t IRAM_ATTR spi_flash_write(uint32_t dest_addr, const uint32_t *src, uint32_t size)
{
spi_flash_disable_interrupts_caches_and_other_cpu();
SpiFlashOpResult rc;
rc = spi_flash_unlock();
if (rc == SPI_FLASH_RESULT_OK) {
rc = SPIWrite(dest_addr, src, (int32_t) size);
}
spi_flash_enable_interrupts_caches_and_other_cpu();
return spi_flash_translate_rc(rc);
}
esp_err_t IRAM_ATTR spi_flash_read(uint32_t src_addr, uint32_t *dest, uint32_t size)
{
spi_flash_disable_interrupts_caches_and_other_cpu();
SpiFlashOpResult rc;
rc = SPIRead(src_addr, dest, (int32_t) size);
spi_flash_enable_interrupts_caches_and_other_cpu();
return spi_flash_translate_rc(rc);
}
static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc)
{
@ -35,72 +237,36 @@ static esp_err_t spi_flash_translate_rc(SpiFlashOpResult rc)
}
}
extern void Cache_Flush(int);
static const uint32_t cache_mask = DPORT_APP_CACHE_MASK_OPSDRAM | DPORT_APP_CACHE_MASK_DROM0 |
DPORT_APP_CACHE_MASK_DRAM1 | DPORT_APP_CACHE_MASK_IROM0 |
DPORT_APP_CACHE_MASK_IRAM1 | DPORT_APP_CACHE_MASK_IRAM0;
static void IRAM_ATTR spi_flash_disable_interrupts_caches_and_app_cpu()
static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t* saved_state)
{
vTaskSuspendAll();
// SET_PERI_REG_MASK(APPCPU_CTRL_REG_C, DPORT_APPCPU_RUNSTALL);
Cache_Read_Disable(0);
Cache_Read_Disable(1);
}
static void IRAM_ATTR spi_flash_enable_interrupts_caches_and_app_cpu()
{
Cache_Read_Enable(0);
Cache_Read_Enable(1);
// CLEAR_PERI_REG_MASK(APPCPU_CTRL_REG_C, DPORT_APPCPU_RUNSTALL);
xTaskResumeAll();
}
esp_err_t IRAM_ATTR spi_flash_erase_sector(uint16_t sec)
{
spi_flash_disable_interrupts_caches_and_app_cpu();
SpiFlashOpResult rc;
if (xPortGetCoreID() == 1) {
rc = SPI_FLASH_RESULT_ERR;
}
else {
rc = SPIUnlock();
if (rc == SPI_FLASH_RESULT_OK) {
rc = SPIEraseSector(sec);
uint32_t ret = 0;
if (cpuid == 0) {
ret |= GET_PERI_REG_BITS2(PRO_CACHE_CTRL1_REG, cache_mask, 0);
while (GET_PERI_REG_BITS2(PRO_DCACHE_DBUG_REG0, DPORT_PRO_CACHE_STATE, DPORT_PRO_CACHE_STATE_S) != 1) {
;
}
}
Cache_Flush(0);
Cache_Flush(1);
spi_flash_enable_interrupts_caches_and_app_cpu();
return spi_flash_translate_rc(rc);
}
esp_err_t IRAM_ATTR spi_flash_write(uint32_t dest_addr, const uint32_t *src, uint32_t size)
{
spi_flash_disable_interrupts_caches_and_app_cpu();
SpiFlashOpResult rc;
if (xPortGetCoreID() == 1) {
rc = SPI_FLASH_RESULT_ERR;
}
else {
rc = SPIUnlock();
if (rc == SPI_FLASH_RESULT_OK) {
rc = SPIWrite(dest_addr, src, (int32_t) size);
SET_PERI_REG_BITS(PRO_CACHE_CTRL_REG, 1, 0, DPORT_PRO_CACHE_ENABLE_S);
} else {
ret |= GET_PERI_REG_BITS2(APP_CACHE_CTRL1_REG, cache_mask, 0);
while (GET_PERI_REG_BITS2(APP_DCACHE_DBUG_REG0, DPORT_APP_CACHE_STATE, DPORT_APP_CACHE_STATE_S) != 1) {
;
}
SET_PERI_REG_BITS(APP_CACHE_CTRL_REG, 1, 0, DPORT_APP_CACHE_ENABLE_S);
}
Cache_Flush(0);
Cache_Flush(1);
spi_flash_enable_interrupts_caches_and_app_cpu();
return spi_flash_translate_rc(rc);
*saved_state = ret;
}
esp_err_t IRAM_ATTR spi_flash_read(uint32_t src_addr, uint32_t *dest, uint32_t size)
static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state)
{
spi_flash_disable_interrupts_caches_and_app_cpu();
SpiFlashOpResult rc;
if (xPortGetCoreID() == 1) {
rc = SPI_FLASH_RESULT_ERR;
if (cpuid == 0) {
SET_PERI_REG_BITS(PRO_CACHE_CTRL_REG, 1, 1, DPORT_PRO_CACHE_ENABLE_S);
SET_PERI_REG_BITS(PRO_CACHE_CTRL1_REG, cache_mask, saved_state, 0);
} else {
SET_PERI_REG_BITS(APP_CACHE_CTRL_REG, 1, 1, DPORT_APP_CACHE_ENABLE_S);
SET_PERI_REG_BITS(APP_CACHE_CTRL1_REG, cache_mask, saved_state, 0);
}
else {
rc = SPIRead(src_addr, dest, (int32_t) size);
}
spi_flash_enable_interrupts_caches_and_app_cpu();
return spi_flash_translate_rc(rc);
}

View File

@ -28,6 +28,15 @@ extern "C" {
#define SPI_FLASH_SEC_SIZE 4096 /**< SPI Flash sector size */
/**
* @brief Initialize SPI flash access driver
*
* This function must be called exactly once, before any other
* spi_flash_* functions are called.
*
*/
void spi_flash_init();
/**
* @brief Erase the Flash sector.
*

View File

@ -1,7 +0,0 @@
#
# Component Makefile
#
EXTRA_CFLAGS := -DLWIP_ESP8266
include $(IDF_PATH)/make/component.mk

View File

@ -0,0 +1,5 @@
#
# Component Makefile
#
include $(IDF_PATH)/make/component_common.mk

View File

@ -454,7 +454,7 @@ static void tcpip_adapter_dhcpc_cb(void)
ip4_addr_set(&ip_info->gw, ip_2_ip4(&netif->gw));
//notify event
evt.event_id = SYSTEM_EVENT_STA_GOTIP;
evt.event_id = SYSTEM_EVENT_STA_GOT_IP;
memcpy(&evt.event_info.got_ip.ip_info, ip_info, sizeof(tcpip_adapter_ip_info_t));
esp_event_send(&evt);

302
docs/build_system.rst Normal file
View File

@ -0,0 +1,302 @@
Build System
------------
This document explains the Espressif IoT Development Framework build system and the
concept of "components"
Read this document if you want to know how to organise a new ESP-IDF project.
We recommend using the esp-idf-template_ project as a starting point for your project.
Overview
========
An ESP-IDF project can be seen as an almagation of a number of components.
For example, for a webserver that shows the current humidity, we would
have:
- The ESP32 base libraries (libc, rom bindings etc)
- The WiFi drivers
- A TCP/IP stack
- The FreeRTOS operating system
- A webserver
- A driver for an humidity sensor
- Main code tying it all together
ESP-IDF makes these components explicit and configurable. To do that, when a project
is compiled, the build environment will look up all the components in the
ESP-IDF directories, the project directories and optionally custom other component
directories. It then allows the user to configure compile-time options using
a friendly text-based menu system to customize the ESP-IDF as well as other components
to the requirements of the project. After the components are customized, the
build process will compile everything into an output file, which can then be uploaded
into a board in a way that can also be defined by components.
A project in this sense is defined as a directory under which all the files required
to build it live, excluding the ESP-IDF files and the toolchain. A simple project
tree might look like this::
- myProject/ - build/
- components/ - component1/ - component.mk
- Kconfig
- src1.c
- component2/ - component.mk
- Kconfig
- src1.c
- main/ - src1.c
- src2.c
- Makefile
As we can see, a project consists of a components/ subdirectory containing its
components as well as one or more directories containing the project-specific
sources; by default a single directory called 'main' is assumed. The project
directory will also have a Makefile where the projects name as well as optionally
other options are defined. After compilation, the project directory will contain
a 'build'-directory containing all of the objects, libraries and other generated
files as well as the final binary.
Components also have a custom makefile - ``component.mk``. This contains various definititions
influencing the build process of the component as well as the project it's used
in. Components may also include a Kconfig file defining the compile-time options that are
settable by means of the menu system.
Project makefile variables that can be set by the programmer::
PROJECT_NAME: Mandatory. Name for the project
BUILD_DIR_BASE: Set the directory where all objects/libraries/binaries end up in.
Defaults to $(PROJECT_PATH)/build
COMPONENT_DIRS: Search path for components. Defaults to the component/ directories
in the ESP-IDF path and the project path.
COMPONENTS: A list of component names. Defaults to all the component found in the
COMPONENT_DIRS directory
EXTRA_COMPONENT_DIRS: Defaults to unset. Use this to add directories to the default
COMPONENT_DIRS.
SRCDIRS: Directories under the project dir containing project-specific sources.
Defaults to 'main'. These are treated as 'lite' components: they do not have
include directories that are passed to the compilation pass of all components and
they do not have a Kconfig option.
Component makefile variables that can be set by the programmer::
COMPONENT_ADD_INCLUDEDIRS: Relative path to include directories to be added to
the entire project
COMPONENT_PRIV_INCLUDEDIRS: Relative path to include directories that are only used
when compiling this specific component
COMPONENT_DEPENDS: Names of any components that need to be compiled before this component.
COMPONENT_ADD_LDFLAGS: Ld flags to add for this project. Defaults to -l$(COMPONENT_NAME).
Add libraries etc in the current directory as $(abspath libwhatever.a)
COMPONENT_EXTRA_INCLUDES: Any extra include paths. These will be prefixed with '-I' and
passed to the compiler; please put absolute paths here.
COMPONENT_SRCDIRS: Relative directories to look in for sources. Defaults to '.', the current
directory (the root of the component) only. Use this to specify any subdirectories. Note
that specifying this overwrites the default action of compiling everything in the
components root dir; to keep this behaviour please also add '.' as a directory in this
list.
COMPONENT_OBJS: Object files to compile. Defaults to the .o variants of all .c and .S files
that are found in COMPONENT_SRCDIRS.
COMPONENT_EXTRA_CLEAN: Files that are generated using rules in the components Makefile
that also need to be cleaned
COMPONENT_BUILDRECIPE: Recipe to build the component. Optional. Defaults to building all
COMPONENT_OBJS and linking them into lib(componentname).a
COMPONENT_CLEANRECIPE: Recipe to clean the component. Optional. Defaults to removing
all built objects and libraries.
COMPONENT_BUILD_DIR: Equals the cwd of the component build, which is the build dir
of the component (where all the .o etc files should be created).
These variables are already set early on in the Makefile and the values in it will
be usable in component or project Makefiles::
CC, LD, AR, OBJCOPY: Xtensa gcc tools
HOSTCC, HOSTLD etc: Host gcc tools
LDFLAGS, CFLAGS: Set to usable values as defined in ESP-IDF Makefile
PROJECT_NAME: Name of the project, as set in project makefile
PROJECT_PATH: Path to the root of the project folder
COMPONENTS: Name of the components to be included
CONFIG_*: All values set by 'make menuconfig' have corresponding Makefile variables.
For components, there also are these defines::
COMPONENT_PATH: Absolute path to the root of the source tree of the component we're
compiling
COMPONENT_LIBRARY: The full path to the static library the components compilation pass
is supposed to generate
Make Process
------------
The Make process is always invoked from the project directory by the
user; invoking it anywhere else gives an error. This is what happens if
we build a binary:
The Makefile first determines how it was included. It figures out
various paths as well as the components available to it. It will also
collect the ldflags and includes that the components specify they need.
It does this by running a dummy make on the components with a "get_variable"
target that will output these values.
The Makefile will then create targets to build the lib*.a libraries of
all components and make the elf target depend on this. The main Makefile
invokes Make on the componen.mk of each components inside a sub-mke: this way
the components have full freedom to do whatever is necessary to build
the library without influencing other components. By default, the
component.mk includes the utility makefile $(IDF_PATH)/make/component_common.mk.
This provides default targets and configurations that will work
out-of-the-box for most projects.
KConfig
-------
Each component can also have a Kconfig file, alongside the component.mk, that contains
details to add to "menuconfig" for this component.
Makefile.projbuild
------------------
For components that have parts that need to be run when building of the
project is done, you can create a file called Makefile.projbuild in the
component root directory. This file will be included in the main
Makefile.
KConfig.projbuild
-----------------
There's an equivalent to Makefile.projbuild for KConfig: if you want to include
options at the top-level, not inside the 'components' submenu then create a Kconfig.projbuild and
it will be included in the main menu of menuconfig.
Take good care when (re)defining stuff here: because it's included with all the other
.projbuild files, it's possible to overwrite variables or re-declare targets defined in
the ESP-IDF makefile/Kconfig and other .projbuild files. It's generally better to just
create a KConfig file, if you can.
Writing Component Makefiles
---------------------------
A component consists of a directory which doubles as the name for the
component: a component named 'httpd' lives in a directory called 'httpd'
Because components usually live under the project directory (although
they can also reside in an other folder), the path to this may be
something like /home/myuser/projects/myprojects/components/httpd .
One of the things that most components will have is a component.mk makefile,
containing instructions on how to build the component. Because the
build environment tries to set reasonable defaults that will work most
of the time, component.mk can be very small.
Simplest component.mk
=====================
At the minimum, component.mk will just include the ESP-IDF component "common" makefile,
which adds common component functionality::
include $(IDF_PATH)/make/component_common.mk
This will take all the .c and .S files in the component root and compile
them into object files, finally linking them into a library.
Adding source directories
=========================
By default, subdirectories are ignored. If your project has sources in subdirectories
instead of in the root of the component then you can tell that to the build
system by setting COMPONENT_SRCDIRS::
COMPONENT_SRCDIRS := src1 src2
include $(IDF_PATH)/make/component_common.mk
This will compile all source files in the src1/ and src2/ subdirectories
instead.
Specifying source files
=======================
The standard component.mk logic adds all .S and .c files in the source
directories as sources to be compiled unconditionally. It is possible
to circumvent that logic and hardcode the objects to be compiled by
manually setting the COMPONENT_OBJS variable to the name of the
objects that need to be generated::
COMPONENT_OBJS := file1.o file2.o thing/filea.o thing/fileb.o anotherthing/main.o
include $(IDF_PATH)/make/component_common.mk
Adding conditional configuration
================================
The configuration system can be used to conditionally compile some files
dependending on the options selected in ``make menuconfig``:
Kconfig::
config FOO_ENABLE_BAR
bool "Enable the BAR feature."
help
This enables the BAR feature of the FOO component.
Makefile::
COMPONENT_OBJS := foo_a.o foo_b.o $(if $(CONFIG_FOO_ENABLE_BAR),foo_bar.o foo_bar_interface.o)
include $(IDF_PATH)/make/component_common.mk
Source Code Generation
======================
Some components will have a situation where a source file isn't supplied
with the component itself but has to be generated from another file. Say
our component has a header file that consists of the converted binary
data of a BMP file, converted using a hypothetical tool called bmp2h. The
header file is then included in as C source file called graphics_lib.c::
COMPONENT_EXTRA_CLEAN := logo.h
graphics_lib.o: logo.h
logo.h: $(COMPONENT_PATH)/logo.bmp
bmp2h -i $^ -o $@
include $(IDF_PATH)/make/component_common.mk
In this example, graphics_lib.o and logo.h will be generated in the
current directory (the build directory) while logo.bmp comes with the
component and resides under the component path. Because logo.h is a
generated file, it needs to be cleaned when make clean is called which
why it is added to the COMPONENT_EXTRA_CLEAN variable.
Cosmetic Improvements
=====================
The above example will work just fine, but there's one last cosmetic
improvement that can be done. The make system tries to make the make
process somewhat easier on the eyes by hiding the commands (unless you
run make with the V=1 switch) and this does not do that yet. Here's an
improved version that will output in the same style as the rest of the
make process::
COMPONENT_EXTRA_CLEAN := test_tjpgd_logo.h
graphics_lib.o: logo.h
logo.h: $(COMPONENT_PATH)/logo.bmp
$(summary) BMP2H $@
$(Q) bmp2h -i $^ -o $@
include $(IDF_PATH)/make/component_common.mk
Fully Overriding The Component Makefile
---------------------------------------
Obviously, there are cases where all these recipes are insufficient for a
certain component, for example when the component is basically a wrapper
around another third-party component not originally intended to be
compiled under this build system. In that case, it's possible to forego
the build system entirely by setting COMPONENT_OWNBUILDTARGET and
possibly COMPONENT_OWNCLEANTARGET and defining your own build- and clean
target. The build target can do anything as long as it creates
$(COMPONENT_LIBRARY) for the main file to link into the project binary,
and even that is not necessary: if the COMPONENT_ADD_LDFLAGS variable
is set, the component can instruct the linker to do anything else as well.
.. _esp-idf-template: https://github.com/espressif/esp-idf-template

View File

@ -39,9 +39,9 @@ Project Properties
*Windows users only, follow these two additional steps:*
* On the same Environment property page, edit the PATH environment variable and append ``;C:\msys32\usr\bin;C:\msys32\mingw32\bin;C:\msys32\opt\xtensa-esp32-elf\bin`` to the end of the default value. (If you installed msys32 to a different directory then you'll need to change these paths to match.)
* On the same Environment property page, edit the PATH environment variable. Delete the existing value and replace it with ``C:\msys32\usr\bin;C:\msys32\mingw32\bin;C:\msys32\opt\xtensa-esp32-elf\bin`` (If you installed msys32 to a different directory then you'll need to change these paths to match).
* Click on the "C/C++ Build" top-level properties page then uncheck "Use default build command" and enter this for the custom build command: ``bash ${IDF_PATH}/bin/eclipse_windows_make.sh``.
* Click on the "C/C++ Build" top-level properties page then uncheck "Use default build command" and enter this for the custom build command: ``bash ${IDF_PATH}/tools/windows/eclipse_make.sh``.
*All users, continue with these steps:*
@ -60,7 +60,7 @@ Flash from Eclipse
You can integrate the "make flash" target into your Eclipse project to flash using esptool.py from the Eclipse UI:
* Right-click your project in Project Explorer (important to make sure you don't select a subdirectory of the project or Eclipse may find the wrong Makefile.)
* Right-click your project in Project Explorer (important to make sure you select the project, not a directory in the project, or Eclipse may find the wrong Makefile.)
* Select Make Targets -> Create from the context menu.
@ -73,3 +73,8 @@ Note that you will need to use "make menuconfig" to set the serial port and othe
Follow the same steps to add ``bootloader`` and ``partition_table`` targets, if necessary.
.. _eclipse.org: http://www.eclipse.org/
Eclipse Troubleshooting
-----------------------
* ``*** Make was invoked from ... However please do not run make from the sdk or a component directory; ...`` - Eclipse will detect any directory with a Makefile in it as being a possible directory to run "make" in. All component directories also contain a Makefile (the wrong one), so it is important when using Project -> Make Target to always select the top-level project directory in Project Explorer.

View File

@ -49,6 +49,23 @@ summary := @echo
details := @true
endif
# Pseudo-target to handle the case where submodules need to be
# re-initialised.
#
# $(eval $(call SubmoduleRequiredForFiles,FILENAMES)) to create a target that
# automatically runs 'git submodule update --init' if those files
# are missing, and fails if this is not possible.
define SubmoduleRequiredForFiles
$(1):
@echo "WARNING: Missing submodule for $$@..."
$(Q) [ -d ${IDF_PATH}/.git ] || ( echo "ERROR: esp-idf must be cloned from git to work."; exit 1)
$(Q) [ -x $(which git) ] || ( echo "ERROR: Need to run 'git submodule --init' in esp-idf root directory."; exit 1)
@echo "Attempting 'git submodule update --init' in esp-idf root directory..."
cd ${IDF_PATH} && git submodule update --init
endef
# General make utilities
# convenience variable for printing an 80 asterisk wide separator line

View File

@ -1,13 +1,13 @@
#
# Main Project Makefile
# This Makefile is included directly from the user project Makefile in order to call the Makefiles of all the
# components (in a separate make process) to build all the libraries, then links them together
# into the final file. If so, PWD is the project dir (we assume).
# This Makefile is included directly from the user project Makefile in order to call the component.mk
# makefiles of all components (in a separate make process) to build all the libraries, then links them
# together into the final file. If so, PWD is the project dir (we assume).
#
#
# This Makefile requires the environment variable IDF_PATH to be set to the directory where this
# Makefile is located.
# This makefile requires the environment variable IDF_PATH to be set to the top-level esp-idf directory
# where this file is located.
#
.PHONY: build-components menuconfig defconfig all build clean all_binaries
@ -77,9 +77,9 @@ SRCDIRS ?= main
COMPONENT_PATHS := $(foreach comp,$(COMPONENTS),$(firstword $(foreach dir,$(COMPONENT_DIRS),$(wildcard $(dir)/$(comp)))))
COMPONENT_PATHS += $(abspath $(SRCDIRS))
#A component is buildable if it has a Makefile; we assume that a 'make -C $(component dir) build' results in a
#lib$(componentname).a.
COMPONENT_PATHS_BUILDABLE := $(foreach cp,$(COMPONENT_PATHS),$(if $(wildcard $(cp)/Makefile),$(cp)))
#A component is buildable if it has a component.mk makefile; we assume that a
# 'make -C $(component dir) -f component.mk build' results in a lib$(componentname).a
COMPONENT_PATHS_BUILDABLE := $(foreach cp,$(COMPONENT_PATHS),$(if $(wildcard $(cp)/component.mk),$(cp)))
# Assemble global list of include dirs (COMPONENT_INCLUDES), and
# LDFLAGS args (COMPONENT_LDFLAGS) supplied by each component.
@ -98,7 +98,7 @@ COMPONENT_LDFLAGS :=
#
# Debugging this? Replace $(shell with $(error and you'll see the full command as-run.
define GetVariable
$(shell "$(MAKE)" -s --no-print-directory -C $(1) get_variable PROJECT_PATH=$(PROJECT_PATH) GET_VARIABLE=$(2) | sed -En "s/^$(2)=(.+)/\1/p" )
$(shell "$(MAKE)" -s --no-print-directory -C $(1) -f component.mk get_variable PROJECT_PATH=$(PROJECT_PATH) GET_VARIABLE=$(2) | sed -En "s/^$(2)=(.+)/\1/p" )
endef
COMPONENT_INCLUDES := $(abspath $(foreach comp,$(COMPONENT_PATHS_BUILDABLE),$(addprefix $(comp)/, \
@ -193,7 +193,7 @@ define GenerateComponentPhonyTarget
# $(2) - target to generate (build, clean)
.PHONY: $(notdir $(1))-$(2)
$(notdir $(1))-$(2): | $(BUILD_DIR_BASE)/$(notdir $(1))
@+$(MAKE) -C $(BUILD_DIR_BASE)/$(notdir $(1)) -f $(1)/Makefile COMPONENT_BUILD_DIR=$(BUILD_DIR_BASE)/$(notdir $(1)) $(2)
@+$(MAKE) -C $(BUILD_DIR_BASE)/$(notdir $(1)) -f $(1)/component.mk COMPONENT_BUILD_DIR=$(BUILD_DIR_BASE)/$(notdir $(1)) $(2)
endef
define GenerateComponentTargets
@ -206,7 +206,7 @@ $(BUILD_DIR_BASE)/$(notdir $(1)):
# only invoked for the targets whose libraries appear in COMPONENT_LIBRARIES and hence the
# APP_ELF dependencies.)
$(BUILD_DIR_BASE)/$(notdir $(1))/lib$(notdir $(1)).a: $(notdir $(1))-build
$(details) echo "$$^ responsible for $$@" # echo which build target built this file
$(details) "Target '$$^' responsible for '$$@'" # echo which build target built this file
endef
$(foreach component,$(COMPONENT_PATHS_BUILDABLE),$(eval $(call GenerateComponentTargets,$(component))))

View File

@ -26,9 +26,10 @@ function run_tests()
print_status "Checking prerequisites"
[ -z ${IDF_PATH} ] && echo "IDF_PATH is not set. Need path to esp-idf installation." && exit 2
print_status "Cloning template..."
print_status "Cloning template from ${ESP_IDF_TEMPLATE_GIT}..."
git clone ${ESP_IDF_TEMPLATE_GIT} template
cd template
git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..."
print_status "Updating template config..."
make defconfig || exit $?

View File

@ -5,5 +5,5 @@
# process uses MinGW paths of the form /c/dir/dir/file. So parse these out...
#
# (regexp deliberate only matches after a space character to try and avoid false-positives.)
echo "Running make in $(dirname $0)"
echo "Running make in $(pwd)"
make $@ V=1 | sed -E "s@ /([a-z])/(.+)/@ \1:/\2/@g" | sed -E "s@-I/([a-z])/(.+)/@-I\1:/\2/@g" | sed -E "s@-L/([a-z])/(.+)/@-L\1:/\2/@g"