diff --git a/boards/common/esp8266/Makefile.features b/boards/common/esp8266/Makefile.features index c41253575691..6d3d608e468a 100644 --- a/boards/common/esp8266/Makefile.features +++ b/boards/common/esp8266/Makefile.features @@ -11,3 +11,5 @@ FEATURES_PROVIDED += periph_pwm FEATURES_PROVIDED += periph_spi FEATURES_PROVIDED += periph_uart FEATURES_PROVIDED += periph_uart_modecfg + +FEATURES_PROVIDED += arduino diff --git a/boards/esp8266-esp-12x/include/arduino_board.h b/boards/esp8266-esp-12x/include/arduino_board.h index a3260f957687..07465013ec9d 100644 --- a/boards/esp8266-esp-12x/include/arduino_board.h +++ b/boards/esp8266-esp-12x/include/arduino_board.h @@ -27,9 +27,9 @@ extern "C" { #endif /** - * @brief The on-board LED is connected to pin 2 on this board + * @brief The on-board LED is connected to GPIO2 (Arduino pin 3) on this board */ -#define ARDUINO_LED (GPIO2) +#define ARDUINO_LED (3) /** * @brief Look-up table for the Arduino's digital pins diff --git a/boards/esp8266-olimex-mod/include/arduino_board.h b/boards/esp8266-olimex-mod/include/arduino_board.h index c0470c1a4532..7da0540f29b2 100644 --- a/boards/esp8266-olimex-mod/include/arduino_board.h +++ b/boards/esp8266-olimex-mod/include/arduino_board.h @@ -25,9 +25,9 @@ extern "C" { #endif /** - * @brief The on-board LED is connected to pin 2 on this board + * @brief The on-board LED is connected to GPIO1 (Arduino pin 0) on this board */ -#define ARDUINO_LED (GPIO1) +#define ARDUINO_LED (0) /** * @brief Look-up table for the Arduino's digital pins diff --git a/boards/esp8266-sparkfun-thing/include/arduino_board.h b/boards/esp8266-sparkfun-thing/include/arduino_board.h index b9a7ff0ceaef..c7949427be13 100644 --- a/boards/esp8266-sparkfun-thing/include/arduino_board.h +++ b/boards/esp8266-sparkfun-thing/include/arduino_board.h @@ -25,9 +25,9 @@ extern "C" { #endif /** - * @brief The on-board LED is connected to pin 2 on this board + * @brief The on-board LED is connected to GPIO5 (Arduino pin 6) on this board */ -#define ARDUINO_LED (GPIO5) +#define ARDUINO_LED (6) /** * @brief Look-up table for the Arduino's digital pins diff --git a/cpu/esp32/Makefile b/cpu/esp32/Makefile index bdefcdb5294d..15bb780b8142 100644 --- a/cpu/esp32/Makefile +++ b/cpu/esp32/Makefile @@ -14,11 +14,7 @@ ifneq (, $(filter esp_eth, $(USEMODULE))) DIRS += esp-eth endif -ifneq (, $(filter esp_wifi, $(USEMODULE))) - DIRS += esp-wifi -endif - -ifneq (, $(filter riot_freertos, $(USEMODULE))) +ifneq (, $(filter esp_freertos, $(USEMODULE))) DIRS += freertos endif diff --git a/cpu/esp32/Makefile.dep b/cpu/esp32/Makefile.dep index 95f671cbb10c..d2ff55b88d6f 100644 --- a/cpu/esp32/Makefile.dep +++ b/cpu/esp32/Makefile.dep @@ -1,46 +1,36 @@ # additional modules dependencies +include $(RIOTCPU)/esp_common/Makefile.dep + ifneq (,$(filter cpp,$(FEATURES_USED))) - USEMODULE += pthread - BASELIBS += -lstdc++ + USEMODULE += pthread + BASELIBS += -lstdc++ endif ifneq (,$(filter esp_eth,$(USEMODULE))) - USEMODULE += esp_idf_eth - USEMODULE += esp_idf_eth_phy - USEMODULE += netdev_eth - USEMODULE += netopt - USEMODULE += riot_freertos - USEMODULE += xtimer - INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include/ethernet - INCLUDES += -I$(ESP32_SDK_DIR)/components/ethernet/include -endif - -ifneq (,$(filter esp_now,$(USEMODULE))) - USEMODULE += esp_wifi_any - USEMODULE += netopt -endif - -ifneq (,$(filter esp_wifi,$(USEMODULE))) - USEMODULE += esp_wifi_any - USEMODULE += netopt - USEMODULE += netdev_eth + USEMODULE += esp_freertos + USEMODULE += esp_idf_eth + USEMODULE += esp_idf_eth_phy + USEMODULE += netdev_eth + USEMODULE += netopt + USEMODULE += xtimer + INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include/ethernet + INCLUDES += -I$(ESP32_SDK_DIR)/components/ethernet/include endif ifneq (,$(filter esp_wifi_any,$(USEMODULE))) - # add additional modules used for any WiFi interface - USEMODULE += esp_idf_heap - USEMODULE += esp_idf_wpa_supplicant_crypto - USEMODULE += esp_idf_wpa_supplicant_port - USEMODULE += esp_idf_nvs_flash - USEMODULE += riot_freertos - USEMODULE += xtimer + # add additional modules used for any WiFi interface + USEMODULE += esp_freertos + USEMODULE += esp_idf_heap + USEMODULE += esp_idf_nvs_flash + USEMODULE += esp_idf_wpa_supplicant_crypto + USEMODULE += esp_idf_wpa_supplicant_port endif ifneq (,$(filter esp_idf_nvs_flash,$(USEMODULE))) - # add additional modules required by esp_idf_nvs_flash - USEMODULE += mtd - USEMODULE += pthread + # add additional modules required by esp_idf_nvs_flash + USEMODULE += mtd + USEMODULE += pthread endif ifneq (,$(filter periph_rtc,$(USEMODULE))) @@ -56,68 +46,37 @@ ifneq (,$(filter esp_rtc_timer_32k,$(USEMODULE))) endif ifneq (,$(filter periph_i2c,$(USEMODULE))) - ifneq (,$(filter esp_i2c_hw,$(USEMODULE))) - USEMODULE += core_thread_flags - USEMODULE += xtimer - USEMODULE += periph_i2c_hw - else - # PLEASE NOTE: because of the very poor and faulty hardware implementation - # we use software implementation by default for the moment (if module - # esp_i2c_hw is not explicitly used) - USEMODULE += esp_i2c_sw - USEMODULE += periph_i2c_sw - endif + ifneq (,$(filter esp_i2c_hw,$(USEMODULE))) + USEMODULE += core_thread_flags + USEMODULE += xtimer + USEMODULE += periph_i2c_hw + else + # PLEASE NOTE: because of the very poor and faulty hardware implementation + # we use software implementation by default for the moment (if module + # esp_i2c_hw is not explicitly used) + USEMODULE += esp_i2c_sw + USEMODULE += periph_i2c_sw + endif endif -ifneq (, $(filter esp_spi_ram, $(DISABLE_MODULE))) - USEMODULE := $(filter-out esp_spi_ram, $(USEMODULE)) +ifneq (,$(filter esp_spi_ram,$(DISABLE_MODULE))) + USEMODULE := $(filter-out esp_spi_ram,$(USEMODULE)) endif -# each device has SPI flash memory, but must be explicitly enabled -ifneq (,$(filter esp_spiffs,$(USEMODULE))) - USEMODULE += spiffs +ifneq (,$(filter esp_now esp_wifi esp_spi_ram,$(USEMODULE))) + # the ESP-IDF heap has to be used if SPI RAM is used + USEMODULE += esp_idf_heap endif ifneq (,$(filter mtd,$(USEMODULE))) - USEMODULE += esp_idf_spi_flash + USEMODULE += esp_idf_spi_flash endif ifneq (,$(filter ndn-riot,$(USEPKG))) - USEMODULE += crypto - USEMODULE += cipher_modes + USEMODULE += crypto + USEMODULE += cipher_modes endif ifneq (,$(filter shell,$(USEMODULE))) - USEMODULE += ps -endif - -ifneq (,$(filter log_color,$(USEMODULE))) - USEMODULE += esp_log_colored -endif - -# if SPI RAM is enabled, ESP-IDF heap and quot flash mode have to be used -ifneq (,$(filter esp_spi_ram,$(USEMODULE))) - USEMODULE += esp_idf_heap - export FLASH_MODE = qout - CFLAGS += -DFLASH_MODE_QOUT=1 -else - ifeq ($(FLASH_MODE), qio) - CFLAGS += -DFLASH_MODE_QIO=1 - endif - ifeq ($(FLASH_MODE), qout) - CFLAGS += -DFLASH_MODE_QOUT=1 - endif - ifeq ($(FLASH_MODE), dio) - CFLAGS += -DFLASH_MODE_DIO=1 - endif - ifeq ($(FLASH_MODE), dout) - CFLAGS += -DFLASH_MODE_DOUT=1 - endif -endif - -ifneq (,$(filter esp_idf_heap,$(USEMODULE))) - LINKFLAGS += -Wl,-wrap,_malloc_r - LINKFLAGS += -Wl,-wrap,_calloc_r - LINKFLAGS += -Wl,-wrap,_realloc_r - LINKFLAGS += -Wl,-wrap,_free_r + USEMODULE += ps endif diff --git a/cpu/esp32/Makefile.features b/cpu/esp32/Makefile.features index 4bcca1eb06e8..7b7c97e8e643 100644 --- a/cpu/esp32/Makefile.features +++ b/cpu/esp32/Makefile.features @@ -1,9 +1,6 @@ -FEATURES_PROVIDED += arch_32bit +# MCU defined features that are provided independent on board definitions + +include $(RIOTCPU)/esp_common/Makefile.features + FEATURES_PROVIDED += arch_esp32 -FEATURES_PROVIDED += cpp -FEATURES_PROVIDED += periph_cpuid -FEATURES_PROVIDED += periph_hwrng -FEATURES_PROVIDED += periph_pm FEATURES_PROVIDED += periph_rtc -FEATURES_PROVIDED += periph_timer -FEATURES_PROVIDED += ssp diff --git a/cpu/esp32/Makefile.include b/cpu/esp32/Makefile.include index 0d73eebb5871..391ad0c3fa11 100644 --- a/cpu/esp32/Makefile.include +++ b/cpu/esp32/Makefile.include @@ -1,123 +1,55 @@ # check some environment variables first ifndef ESP32_SDK_DIR - $(info ESP32_SDK_DIR should be defined as /path/to/esp-idf directory) - $(info ESP32_SDK_DIR is set by default to /opt/esp/esp-idf) - export ESP32_SDK_DIR=/opt/esp/esp-idf + $(info ESP32_SDK_DIR should be defined as /path/to/esp-idf directory) + $(info ESP32_SDK_DIR is set by default to /opt/esp/esp-idf) + export ESP32_SDK_DIR=/opt/esp/esp-idf endif -# DEFAULT compile configuration +ESP_SDK_DIR = $(ESP32_SDK_DIR) -# FLASH_MODE=[ dout | dio | qout | qio ] -# use flash mode dout by default to keep GPIO9 and GPIO10 free for use -export FLASH_MODE ?= dout +# With the '-Os' option, the ESP32 hangs sporadically in 'tests/bench*' if +# interrupts are disabled too early by benchmark tests. +CFLAGS_OPT ?= -O2 -# enable GDBSTUP for debugging on exceptions -ifeq ($(ENABLE_GDBSTUB), 1) - USEMODULE += esp_gdbstub -endif - -# enable GDB for compilation with debug info -ifeq ($(ENABLE_GDB), 1) - USEMODULE += esp_gdb -endif - -# enable modules at command line for testing -ifneq ($(USE_MODULES), ) - USEMODULE += $(USE_MODULES) -endif +# ESP32 specific flashing options +FLASH_CHIP = esp32 +FLASH_MODE ?= dout +FLASH_FREQ = 40m # DO NOT CHANGE +FLASH_SIZE ?= 4 +BOOTLOADER_POS = 0x1000 # SPECIAL module dependencies # cannot be done in Makefile.dep since Makefile.dep is included too late -ifneq (,$(findstring core_thread_flags,$(USEMODULE))) - USEMODULE += pthread -endif - ifneq (,$(filter cpp,$(FEATURES_USED))) - USEMODULE += esp_cxx -endif - -ifneq (,$(filter esp_gdbstub,$(USEMODULE))) - USEMODULE += esp_gdb -endif - -ifneq (,$(filter netdev_default gnrc_netdev_default,$(USEMODULE))) - ifneq (,$(filter lwip,$(USEMODULE))) - # for lwip, use esp_wifi as default netdev if no other netdev is enabled - ifeq (,$(filter esp_eth,$(USEMODULE))) - USEMODULE += esp_wifi - endif - else - # otherwise use esp_now as default netdev if no other netdev is enabled - ifeq (,$(filter esp_wifi esp_eth,$(USEMODULE))) - USEMODULE += esp_now - endif - endif -endif - -ifneq (,$(filter esp_now,$(USEMODULE))) - $(eval GNRC_NETIF_NUMOF=$(shell echo $$(($(GNRC_NETIF_NUMOF)+1)))) - USEMODULE += esp_wifi_any -endif - -ifneq (,$(filter esp_wifi,$(USEMODULE))) - $(eval GNRC_NETIF_NUMOF=$(shell echo $$(($(GNRC_NETIF_NUMOF)+1)))) - USEMODULE += esp_wifi_any + USEMODULE += esp_cxx endif -ifneq (,$(filter esp_eth,$(USEMODULE))) - $(eval GNRC_NETIF_NUMOF=$(shell echo $$(($(GNRC_NETIF_NUMOF)+1)))) +ifneq (,$(filter esp_now esp_wifi esp_spi_ram,$(USEMODULE))) + # the ESP-IDF heap has to be used if any WiFi interface or SPI RAM is used + USEMODULE += esp_idf_heap endif -ifneq (,$(filter spiffs,$(USEMODULE))) - export RIOT_TEST_TIMEOUT = 120 -endif +include $(RIOTCPU)/esp_common/Makefile.include -ifneq (,$(filter littlefs,$(USEMODULE))) - export RIOT_TEST_TIMEOUT = 120 -endif +# regular Makefile -ifneq (,$(filter 4 5,$(LOG_LEVEL))) - USEMODULE += esp_log_startup -endif +TARGET_ARCH ?= xtensa-esp32-elf -# ESP32 pseudomodules PSEUDOMODULES += esp_eth_hw -PSEUDOMODULES += esp_gdb PSEUDOMODULES += esp_gdbstub PSEUDOMODULES += esp_hw_counter -PSEUDOMODULES += esp_i2c_sw PSEUDOMODULES += esp_i2c_hw PSEUDOMODULES += esp_idf_newlib -PSEUDOMODULES += esp_log_colored -PSEUDOMODULES += esp_log_tagged -PSEUDOMODULES += esp_log_startup PSEUDOMODULES += esp_rtc_timer PSEUDOMODULES += esp_rtc_timer_32k PSEUDOMODULES += esp_spi_ram -PSEUDOMODULES += esp_spiffs -PSEUDOMODULES += esp_wifi_any - -export TARGET_ARCH ?= xtensa-esp32-elf -USEMODULE += esp_common -USEMODULE += esp_idf USEMODULE += esp_idf_driver USEMODULE += esp_idf_esp32 USEMODULE += esp_idf_soc -USEMODULE += log -USEMODULE += newlib -USEMODULE += periph USEMODULE += periph_adc_ctrl -USEMODULE += periph_hwrng -USEMODULE += periph_flash -USEMODULE += periph_uart -USEMODULE += riot_freertos -USEMODULE += random -USEMODULE += stdio_uart -USEMODULE += xtensa -INCLUDES += -I$(RIOTCPU)/esp_common/vendor/ INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/ INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include/esp32 @@ -130,76 +62,20 @@ INCLUDES += -I$(ESP32_SDK_DIR)/components/esp32/include INCLUDES += -I$(ESP32_SDK_DIR)/components/heap/include INCLUDES += -I$(ESP32_SDK_DIR)/components/soc/esp32/include INCLUDES += -I$(ESP32_SDK_DIR)/components/soc/include -INCLUDES += -I$(RIOTBOARD)/common/$(CPU)/include INCLUDES += -I$(RIOTCPU)/$(CPU) -# if any WiFi interface is used, the number of priority levels has to be 32 -ifneq (,$(filter esp_wifi_any esp_eth,$(USEMODULE))) - CFLAGS += -DSCHED_PRIO_LEVELS=32 -endif +CFLAGS += -DSDK_NOT_USED -DCONFIG_FREERTOS_UNICORE=1 -DESP_PLATFORM +CFLAGS += -DLOG_TAG_IN_BRACKETS -ifneq (,$(filter lwip,$(USEMODULE))) - # The thread for handling the WiFi hardware has the priority. The priority - # of the lwIP TCP/IP thread should be lower than this priority. - CFLAGS += -DTCPIP_THREAD_PRIO=2 +ifneq (,$(filter esp_now esp_wifi,$(USEMODULE))) + BASELIBS += -lcore -lrtc -lnet80211 -lpp -lcoexist + BASELIBS += -lwps -lwpa -lwpa2 -lphy -lstdc++ endif -CFLAGS += -DSDK_NOT_USED -DCONFIG_FREERTOS_UNICORE=1 -DESP_PLATFORM -CFLAGS += -DLOG_TAG_IN_BRACKETS -CFLAGS += -Wno-unused-parameter -Wformat=0 -CFLAGS += -mlongcalls -mtext-section-literals -fstrict-volatile-bitfields -CFLAGS += -fdata-sections -ffunction-sections -fzero-initialized-in-bss - -OPTIONAL_CFLAGS_BLACKLIST += -Wformat-overflow -OPTIONAL_CFLAGS_BLACKLIST += -Wformat-truncation -OPTIONAL_CFLAGS_BLACKLIST += -gz - -ASFLAGS += --longcalls --text-section-literals - -# thin archives trigger a reboot loop - see #12258, #12035, #12346 -ARFLAGS = rcs - -ifneq ($(CONFIGS),) - CFLAGS += $(CONFIGS) -endif - -# if any WiFi interface is used, the number of priority levels has to be 32 -ifneq (,$(filter esp_wifi_any,$(USEMODULE))) - CFLAGS += -DSCHED_PRIO_LEVELS=32 -endif - -ifneq (,$(filter esp_gdb,$(USEMODULE))) - CFLAGS += -Og -ggdb -g3 -else - CFLAGS += -Os -endif - -ifeq ($(QEMU), 1) - CFLAGS += -DQEMU -endif - -ifneq (,$(filter esp_log_colored,$(USEMODULE))) - BOOTLOADER_COLOR = _colors -endif - -ifneq (,$(filter esp_log_startup,$(USEMODULE))) - BOOTLOADER_INFO = _info -endif - -BOOTLOADER_BIN = bootloader$(BOOTLOADER_COLOR)$(BOOTLOADER_INFO).bin - -# LINKFLAGS += -Wl,--verbose - -LINKFLAGS += -L$(ESP32_SDK_DIR)/components/esp32 -LINKFLAGS += -L$(ESP32_SDK_DIR)/components/esp32/lib - -ifneq (,$(filter esp_wifi_any,$(USEMODULE))) - BASELIBS += -lcore -lrtc -lnet80211 -lpp -lsmartconfig -lcoexist - BASELIBS += -lwps -lwpa -lwpa2 -lespnow -lmesh -lphy -lstdc++ +ifneq (,$(filter esp_now,$(USEMODULE))) + BASELIBS += -lespnow -lmesh endif -BASELIBS += -lhal -lg -lc - LINKFLAGS += -L$(RIOTCPU)/$(CPU)/ld/ LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp32.ld LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp32.common.ld @@ -209,53 +85,11 @@ LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp32.rom.nanofmt.ld LINKFLAGS += -nostdlib -lgcc -Wl,-gc-sections ifneq (,$(filter esp_cxx,$(USEMODULE))) - UNDEF += $(BINDIR)/esp_cxx/cxa_guard.o + UNDEF += $(BINDIR)/esp_cxx/cxa_guard.o endif -ESPTOOL ?= $(RIOTBASE)/dist/tools/esptool/esptool.py - -# The ELFFILE is the base one used for flashing -FLASHFILE ?= $(ELFFILE) - -# configure preflasher to convert .elf to .bin before flashing -FLASH_MODE ?= dout # FIX configuration, DO NOT CHANGE -FLASH_FREQ = 40m # FIX configuration, DO NOT CHANGE -FLASH_SIZE ?= 2MB - -PREFLASHER = $(ESPTOOL) -PREFFLAGS = --chip esp32 elf2image -PREFFLAGS += -fm $(FLASH_MODE) -fs $(FLASH_SIZE) -ff $(FLASH_FREQ) -PREFFLAGS += -o $(FLASHFILE).bin $(FLASHFILE); -PREFFLAGS += printf "\n" > $(BINDIR)/partitions.csv; -PREFFLAGS += printf "nvs, data, nvs, 0x9000, 0x6000\n" >> $(BINDIR)/partitions.csv; -PREFFLAGS += printf "phy_init, data, phy, 0xf000, 0x1000\n" >> $(BINDIR)/partitions.csv; -PREFFLAGS += printf "factory, app, factory, 0x10000, " >> $(BINDIR)/partitions.csv; -PREFFLAGS += ls -l $(FLASHFILE).bin | awk '{ print $$5 }' >> $(BINDIR)/partitions.csv; - -PREFFLAGS += python $(RIOTCPU)/$(CPU)/gen_esp32part.py --disable-sha256sum -PREFFLAGS += --verify $(BINDIR)/partitions.csv $(BINDIR)/partitions.bin -FLASHDEPS += preflash - -# flasher configuration -ifeq ($(QEMU), 1) - FLASHER = dd - FFLAGS += if=/dev/zero bs=1M count=4 | tr "\\000" "\\377" > tmp.bin && cat tmp.bin | - FFLAGS += head -c $$((0x1000)) | - FFLAGS += cat - $(RIOTCPU)/$(CPU)/bin/$(BOOTLOADER_BIN) tmp.bin | - FFLAGS += head -c $$((0x8000)) | - FFLAGS += cat - $(BINDIR)/partitions.bin tmp.bin | - FFLAGS += head -c $$((0x10000)) | - FFLAGS += cat - $(FLASHFILE).bin tmp.bin | - FFLAGS += head -c $$((0x400000)) > $(BINDIR)/esp32flash.bin && rm tmp.bin && - FFLAGS += cp $(RIOTCPU)/$(CPU)/bin/rom_0x3ff90000_0x00010000.bin $(BINDIR)/rom1.bin && - FFLAGS += cp $(RIOTCPU)/$(CPU)/bin/rom_0x40000000_0x000c2000.bin $(BINDIR)/rom.bin -else - export PROGRAMMER_SPEED ?= 460800 - FLASHER = $(ESPTOOL) - FFLAGS += --chip esp32 -p $(PROG_DEV) -b $(PROGRAMMER_SPEED) - FFLAGS += --before default_reset --after hard_reset write_flash - FFLAGS += -z -fm $(FLASH_MODE) -fs detect -ff $(FLASH_FREQ) - FFLAGS += 0x1000 $(RIOTCPU)/$(CPU)/bin/$(BOOTLOADER_BIN) - FFLAGS += 0x8000 $(BINDIR)/partitions.bin - FFLAGS += 0x10000 $(FLASHFILE).bin +# additional flasher configuration for ESP32 QEMU +ifneq (,$(filter esp_qemu,$(USEMODULE))) + FFLAGS += cp $(RIOTCPU)/$(CPU)/bin/rom_0x3ff90000_0x00010000.bin $(BINDIR)/rom1.bin && + FFLAGS += cp $(RIOTCPU)/$(CPU)/bin/rom_0x40000000_0x000c2000.bin $(BINDIR)/rom.bin endif diff --git a/cpu/esp32/doc.txt b/cpu/esp32/doc.txt index 56f8cf86eb89..624e525cbe45 100644 --- a/cpu/esp32/doc.txt +++ b/cpu/esp32/doc.txt @@ -1154,19 +1154,18 @@ Therefore, it is often necessary to change some of these default configurations There are two ways to give the application the ability to change some of these default configurations: -- make variable ```CONFIGS``` +- make variable `CFLAGS` - application-specific board or driver configuration file -## Make Variable ```CONFIGS```  [[TOC](#esp32_toc)] +## Make Variable `CFLAGS`  [[TOC](#esp32_toc)] - -Using the ```CONFIGS``` make variable at the command line, board or driver parameter definitions can be overridden. +Using the `CFLAGS` make variable at the command line, board or driver parameter definitions can be overridden. Example: -``` -CONFIGS='-DESP_LCD_PLUGGED_IN=1 -DLIS3DH_PARAM_INT2=GPIO4' -``` +` +CFLAGS='-DESP_LCD_PLUGGED_IN=1 -DLIS3DH_PARAM_INT2=GPIO4' +` When a larger number of board definitions needs be overridden, this approach becomes impractical. In that case, an application-specific board configuration file located in application directory can be used, see sections below. diff --git a/cpu/esp32/esp-wifi/doc.txt b/cpu/esp32/esp-wifi/doc.txt deleted file mode 100644 index d3e064e41763..000000000000 --- a/cpu/esp32/esp-wifi/doc.txt +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @defgroup cpu_esp32_esp_wifi ESP32 WiFi netdev interface - * @ingroup cpu_esp32 - * @brief Network device driver for the ESP32 WiFi interface - * - * @author Gunar Schorcht - -This module realizes a `netdev` interface for the built-in WiFi interface -of ESP32. To enable the WiFi interface, module `esp_wifi` has to be used. - -@note Due to symbol conflicts with the `crypto` and `hash` modules of RIOT -in module `esp_idf_wpa_supplicant_crypto`, which is required by module -`esp_wifi`, `esp_wifi` cannot be used for applications that use these modules. -Therefore, module `esp_wifi` is not automatically enabled when module -`netdev_default` is used. Instead, if necessary, the application has to add -the module `esp_wifi` in the Makefile. - -``` -USEMODULE += esp_wifi -``` - -Furthermore, the following configuration parameters have to be defined: - -Configuration Parameter | Description -------------------------|------------ -ESP_WIFI_SSID | SSID of the AP to be used. -ESP_WIFI_PASS | Passphrase used for the AP as clear text (max. 64 chars). -ESP_WIFI_STACKSIZE | Stack size used for the WiFi netdev driver thread. - -These configuration parameter definitions, as well as enabling the `esp_wifi` -module, can be done either in the makefile of the project or at make command -line, e.g.: - -``` -USEMODULE=esp_wifi \ -CFLAGS='-DESP_WIFI_SSID=\"MySSID\" -DESP_WIFI_PASS=\"MyPassphrase\"' \ -make -C examples/gnrc_networking BOARD=... -``` - -@note The Wifi network interface (module `esp_wifi`) and the -\ref esp32_esp_now_network_interface "ESP-NOW network interface" (module `esp_now`) -can be used simultaneously, for example, to realize a border router for -a mesh network which uses ESP-NOW. - */ diff --git a/cpu/esp32/esp-wifi/esp_wifi_gnrc.c b/cpu/esp32/esp-wifi/esp_wifi_gnrc.c deleted file mode 100644 index d40884296cab..000000000000 --- a/cpu/esp32/esp-wifi/esp_wifi_gnrc.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32_esp_wifi - * @{ - * - * @file - * @brief GNRC network interface part for ESP32 WiFi interface - * - * @author Gunar Schorcht - */ - -#if defined(MODULE_ESP_WIFI) && defined(MODULE_GNRC_NETIF_ETHERNET) - -#include "esp_wifi_params.h" -#include "esp_wifi_netdev.h" -#include "net/gnrc/netif/ethernet.h" - -/** the only ESP WiFi device */ -extern esp_wifi_netdev_t _esp_wifi_dev; - -/** device thread stack */ -static char _esp_wifi_stack[ESP_WIFI_STACKSIZE]; - -/** setup function for the ESP WiFi */ -extern void esp_wifi_setup (esp_wifi_netdev_t* dev); - -void auto_init_esp_wifi (void) -{ - esp_wifi_setup(&_esp_wifi_dev); - gnrc_netif_ethernet_create(_esp_wifi_stack, ESP_WIFI_STACKSIZE, -#ifdef MODULE_ESP_NOW - ESP_WIFI_PRIO - 1, -#else - ESP_WIFI_PRIO, -#endif - "netif-esp-wifi", - (netdev_t *)&_esp_wifi_dev); -} - -#else /* defined(MODULE_ESP_WIFI) && defined(MODULE_GNRC_NETIF_ETHERNET) */ - -typedef int dont_be_pedantic; - -#endif /* defined(MODULE_ESP_WIFI) && defined(MODULE_GNRC_NETIF_ETHERNET) */ -/**@}*/ diff --git a/cpu/esp32/esp-wifi/esp_wifi_netdev.c b/cpu/esp32/esp-wifi/esp_wifi_netdev.c deleted file mode 100644 index e5463d6a4b67..000000000000 --- a/cpu/esp32/esp-wifi/esp_wifi_netdev.c +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32_esp_wifi - * @{ - * - * @file - * @brief Network device driver for the ESP32 WiFi interface - * - * @author Gunar Schorcht - */ - -#ifdef MODULE_ESP_WIFI - -#include "log.h" -#include "tools.h" - -#include -#include -#include - -#include "net/gnrc/netif/ethernet.h" -#include "net/gnrc/netif/raw.h" -#include "net/gnrc.h" -#include "net/ethernet.h" -#include "net/netdev/eth.h" -#include "od.h" -#include "xtimer.h" - -#include "esp_common.h" -#include "esp_attr.h" -#include "esp_event_loop.h" -#include "esp_now.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "esp_wifi_internal.h" -#include "irq_arch.h" - -#include "nvs_flash/include/nvs_flash.h" - -#include "esp_wifi_params.h" -#include "esp_wifi_netdev.h" - -#define ENABLE_DEBUG (0) -#include "debug.h" - -#define ESP_WIFI_EVENT_RX_DONE BIT(0) -#define ESP_WIFI_EVENT_TX_DONE BIT(1) -#define ESP_WIFI_EVENT_STA_CONNECTED BIT(2) -#define ESP_WIFI_EVENT_STA_DISCONNECTED BIT(3) - -#define ESP_WIFI_DEBUG(f, ...) \ - DEBUG("[esp_wifi] %s: " f "\n", __func__, ## __VA_ARGS__) - -#define ESP_WIFI_LOG_INFO(f, ...) \ - LOG_TAG_INFO("esp_wifi", f "\n", ## __VA_ARGS__) - -#define ESP_WIFI_LOG_ERROR(f, ...) \ - LOG_TAG_ERROR("esp_wifi", f "\n", ## __VA_ARGS__) - -#define MAC_STR "%02x:%02x:%02x:%02x:%02x:%02x" -#define MAC_STR_ARG(m) m[0], m[1], m[2], m[3], m[4], m[5] - -/* - * There is only one ESP WiFi device. We define it as static device variable - * to have access to the device inside ESP WiFi interrupt routines which do - * not provide an argument that could be used as pointer to the ESP WiFi - * device which triggers the interrupt. - */ -esp_wifi_netdev_t _esp_wifi_dev; -static const netdev_driver_t _esp_wifi_driver; - -/* - * Ring buffer for rx_buf elements which hold a pointer to the WiFi frame - * buffer, a pointer to the ethernet frame and the frame length for each - * received frame. Since we have only one device, it the ring buffer can be - * static and has not to be exposed as part of the network device. - */ -#ifndef ESP_WIFI_MAX_RX_BUF -/** The maximum of pending incoming WiFi frames */ -#define ESP_WIFI_MAX_RX_BUF 20 -#endif - -typedef struct { - void* buffer; - void* eb; - uint16_t len; -} rx_buf_t; - -static rx_buf_t rx_buf[ESP_WIFI_MAX_RX_BUF] = { 0 }; - -static unsigned int rx_buf_write = 0; -static unsigned int rx_buf_read = 0; - -extern esp_err_t esp_system_event_add_handler (system_event_cb_t handler, - void *arg); - -/** - * @brief Callback when ethernet frame is received. Has to run in IRAM. - * @param buffer pointer to the begin of the ethernet frame in *eb - * @param eb allocated buffer in WiFi interface - */ -esp_err_t _esp_wifi_rx_cb(void *buffer, uint16_t len, void *eb) -{ - assert(buffer); - assert(eb); - - /* - * When interrupts of the WiFi hardware interface occur, the ISRs only - * send events to the message queue of the `wifi-event-loop` thread. - * The `wifi-event-loop` thread then processes these events sequentially - * and invokes callback functions like the function `esp_wifi_recv_cb` - * asynchronously. - * - * This means that the function `_esp_wifi_rx_cb` is never executed in - * the interrupt context, but always in the context of the thread - * `wifi-event-loop`. Furthermore, function `_esp_wifi_rx_cb` can't - * never be reentered. - */ - ESP_WIFI_DEBUG("buf=%p len=%d eb=%p", buffer, len, eb); - - /* check packet buffer for the minimum packet size */ - if (len < sizeof(ethernet_hdr_t)) { - ESP_WIFI_DEBUG("frame length is less than the size of an Ethernet" - "header (%u < %u)", len, sizeof(ethernet_hdr_t)); - esp_wifi_internal_free_rx_buffer(eb); - return ESP_ERR_INVALID_SIZE; - } - - /* check whether packet buffer fits into receive buffer */ - if (len > ETHERNET_MAX_LEN) { - ESP_WIFI_DEBUG("frame length is greater than the maximum size of an " - "Ethernet frame (%u > %u)", len, ETHERNET_MAX_LEN); - esp_wifi_internal_free_rx_buffer(eb); - return ESP_ERR_INVALID_SIZE; - } - - /* check whether rx buffer is full, that is, rx_buf_write points to an - element that is already in use */ - if (rx_buf[rx_buf_write].buffer) { - ESP_WIFI_LOG_ERROR("no space left in receive buffer"); - esp_wifi_internal_free_rx_buffer(eb); - return ESP_ERR_NO_MEM; - } - - critical_enter(); - - /* fill the rx_buf element */ - rx_buf[rx_buf_write].buffer = buffer; - rx_buf[rx_buf_write].eb = eb; - rx_buf[rx_buf_write].len = len; - - /* point to the next element */ - rx_buf_write = (rx_buf_write + 1) % ESP_WIFI_MAX_RX_BUF; - - critical_exit(); - - /* trigger netdev event to read the data */ - _esp_wifi_dev.event |= ESP_WIFI_EVENT_RX_DONE; - _esp_wifi_dev.netdev.event_callback(&_esp_wifi_dev.netdev, NETDEV_EVENT_ISR); - - return ESP_OK; -} - -#define REASON_BEACON_TIMEOUT (200) -#define REASON_HANDSHAKE_TIMEOUT (204) -#define INDEX_BEACON_TIMEOUT (REASON_BEACON_TIMEOUT - 24) - -static const char *_esp_wifi_disc_reasons [] = { - "INVALID", /* 0 */ - "UNSPECIFIED", /* 1 */ - "AUTH_EXPIRE", /* 2 */ - "AUTH_LEAVE", /* 3 */ - "ASSOC_EXPIRE", /* 4 */ - "ASSOC_TOOMANY", /* 5 */ - "NOT_AUTHED", /* 6 */ - "NOT_ASSOCED", /* 7 */ - "ASSOC_LEAVE", /* 8 */ - "ASSOC_NOT_AUTHED", /* 9 */ - "DISASSOC_PWRCAP_BAD", /* 10 (11h) */ - "DISASSOC_SUPCHAN_BAD", /* 11 (11h) */ - "IE_INVALID", /* 13 (11i) */ - "MIC_FAILURE", /* 14 (11i) */ - "4WAY_HANDSHAKE_TIMEOUT", /* 15 (11i) */ - "GROUP_KEY_UPDATE_TIMEOUT", /* 16 (11i) */ - "IE_IN_4WAY_DIFFERS", /* 17 (11i) */ - "GROUP_CIPHER_INVALID", /* 18 (11i) */ - "PAIRWISE_CIPHER_INVALID", /* 19 (11i) */ - "AKMP_INVALID", /* 20 (11i) */ - "UNSUPP_RSN_IE_VERSION", /* 21 (11i) */ - "INVALID_RSN_IE_CAP", /* 22 (11i) */ - "802_1X_AUTH_FAILED", /* 23 (11i) */ - "CIPHER_SUITE_REJECTED", /* 24 (11i) */ - "BEACON_TIMEOUT", /* 200 */ - "NO_AP_FOUND", /* 201 */ - "AUTH_FAIL", /* 202 */ - "ASSOC_FAIL", /* 203 */ - "HANDSHAKE_TIMEOUT" /* 204 */ -}; - -/* - * Event handler for esp system events. - */ -static esp_err_t IRAM_ATTR _esp_system_event_handler(void *ctx, system_event_t *event) -{ - esp_err_t result; - - uint8_t reason; - const char* reason_str = "UNKNOWN"; - - switch(event->event_id) { - case SYSTEM_EVENT_STA_START: - ESP_WIFI_DEBUG("WiFi started"); - result = esp_wifi_connect(); - if (result != ESP_OK) { - LOG_TAG_ERROR("esp_wifi", "esp_wifi_connect failed with return " - "value %d\n", result); - } - break; - - case SYSTEM_EVENT_SCAN_DONE: - ESP_WIFI_DEBUG("WiFi scan done"); - break; - - case SYSTEM_EVENT_STA_CONNECTED: - ESP_WIFI_LOG_INFO("WiFi connected to ssid %s, channel %d", - event->event_info.connected.ssid, - event->event_info.connected.channel); - - /* register RX callback function */ - esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, _esp_wifi_rx_cb); - - _esp_wifi_dev.connected = true; - _esp_wifi_dev.event |= ESP_WIFI_EVENT_STA_CONNECTED; - _esp_wifi_dev.netdev.event_callback(&_esp_wifi_dev.netdev, NETDEV_EVENT_ISR); - - break; - - case SYSTEM_EVENT_STA_DISCONNECTED: - reason = event->event_info.disconnected.reason; - if (reason < REASON_BEACON_TIMEOUT) { - reason_str = _esp_wifi_disc_reasons[reason]; - } - else if (reason <= REASON_HANDSHAKE_TIMEOUT) { - reason_str = _esp_wifi_disc_reasons[reason - INDEX_BEACON_TIMEOUT]; - } - ESP_WIFI_LOG_INFO("Wifi disconnected from ssid %s, reason %d (%s)", - event->event_info.disconnected.ssid, - event->event_info.disconnected.reason, reason_str); - - /* unregister RX callback function */ - esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, NULL); - - _esp_wifi_dev.connected = false; - _esp_wifi_dev.event |= ESP_WIFI_EVENT_STA_DISCONNECTED; - _esp_wifi_dev.netdev.event_callback(&_esp_wifi_dev.netdev, NETDEV_EVENT_ISR); - - /* call disconnect to reset internal state */ - result = esp_wifi_disconnect(); - if (result != ESP_OK) { - LOG_TAG_ERROR("esp_wifi", "esp_wifi_disconnect failed with " - "return value %d\n", result); - return result; - } - - /* try to reconnect */ - result = esp_wifi_connect(); - if (result != ESP_OK) { - LOG_TAG_ERROR("esp_wifi", "esp_wifi_connect failed with " - "return value %d\n", result); - } - - break; - - default: - ESP_WIFI_DEBUG("event %d", event->event_id); - break; - } - return ESP_OK; -} - -/* we use predefined station configuration */ -static wifi_config_t wifi_config_sta = { - .sta = { - .ssid = ESP_WIFI_SSID, - .password = ESP_WIFI_PASS, - .bssid_set = 0, - .channel = 0, - .scan_method = WIFI_ALL_CHANNEL_SCAN, - .sort_method = WIFI_CONNECT_AP_BY_SIGNAL, - .threshold.rssi = -127, - .threshold.authmode = WIFI_AUTH_WPA_WPA2_PSK - } -}; - -void esp_wifi_setup (esp_wifi_netdev_t* dev) -{ - ESP_WIFI_DEBUG("%p", dev); - - /* set the event handler */ - esp_system_event_add_handler(_esp_system_event_handler, NULL); - - /* - * Init the WiFi driver. TODO It is not only required before ESP_WIFI is - * initialized but also before other WiFi functions are used. Once other - * WiFi functions are realized it has to be moved to a more common place. - */ - esp_err_t result; - -#ifndef MODULE_ESP_NOW - /* if esp_now is used, the following part is already done */ - extern portMUX_TYPE g_intr_lock_mux; - mutex_init(&g_intr_lock_mux); - -#if CONFIG_ESP32_WIFI_NVS_ENABLED - result = nvs_flash_init(); - if (result != ESP_OK) { - LOG_TAG_ERROR("esp_wifi", "nfs_flash_init failed " - "with return value %d\n", result); - return; - } -#endif /* CONFIG_ESP32_WIFI_NVS_ENABLED */ - - /* initialize the WiFi driver with default configuration */ - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - result = esp_wifi_init(&cfg); - if (result != ESP_OK) { - LOG_TAG_ERROR("esp_wifi", "esp_wifi_init failed " - "with return value %d\n", result); - return; - } - - /* set configuration storage type */ - result = esp_wifi_set_storage(WIFI_STORAGE_RAM); - if (result != ESP_OK) { - LOG_TAG_ERROR("esp_now", "esp_wifi_set_storage failed " - "with return value %d\n", result); - return NULL; - } - -#ifdef CONFIG_WIFI_COUNTRY - /* TODO */ -#endif /* CONFIG_WIFI_COUNTRY */ - - result = esp_wifi_set_mode(WIFI_MODE_STA); - if (result != ESP_OK) { - LOG_TAG_ERROR("esp_wifi", "esp_wifi_set_mode failed " - "with return value %d\n", result); - return; - } -#endif /* MODULE_ESP_NOW */ - - /* set the Station configuration */ - result = esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config_sta); - if (result != ESP_OK) { - LOG_TAG_ERROR("esp_wifi", "esp_wifi_set_config station failed " - "with return value %d\n", result); - return; - } - - /* start the WiFi driver */ - result = esp_wifi_start(); - if (result != ESP_OK) { - LOG_TAG_ERROR("esp_wifi", "esp_wifi_start failed " - "with return value %d\n", result); - return; - } - - /* register RX callback function */ - esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, _esp_wifi_rx_cb); - - /* set the netdev driver */ - dev->netdev.driver = &_esp_wifi_driver; - - /* initialize netdev data structure */ - dev->connected = false; -} - -static int _esp_wifi_init(netdev_t *netdev) -{ - ESP_WIFI_DEBUG("%p", netdev); - - _esp_wifi_dev.event = 0; /* no event */ - - return 0; -} - -/* transmit buffer should bot be on stack */ -static uint8_t tx_buf[ETHERNET_MAX_LEN]; - -static int _esp_wifi_send(netdev_t *netdev, const iolist_t *iolist) -{ - ESP_WIFI_DEBUG("%p %p", netdev, iolist); - - assert(netdev != NULL); - assert(iolist != NULL); - - if (!_esp_wifi_dev.connected) { - ESP_WIFI_DEBUG("WiFi is still not connected to AP, cannot send"); - return -EIO; - } - - uint16_t tx_len = 0; /**< number of bytes in transmit buffer */ - - /* load packet data into TX buffer */ - for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) { - if (tx_len + iol->iol_len > ETHERNET_MAX_LEN) { - return -EOVERFLOW; - } - if (iol->iol_len) { - memcpy (tx_buf + tx_len, iol->iol_base, iol->iol_len); - tx_len += iol->iol_len; - } - } - -#if ENABLE_DEBUG - const ethernet_hdr_t* hdr = (const ethernet_hdr_t *)tx_buf; - - ESP_WIFI_DEBUG("send %u byte to " MAC_STR, - (unsigned)tx_len, MAC_STR_ARG(hdr->dst)); -#if MODULE_OD - od_hex_dump(tx_buf, tx_len, OD_WIDTH_DEFAULT); -#endif /* MODULE_OD */ -#endif /* ENABLE_DEBUG */ - - /* send the the packet to the peer(s) mac address */ - if (esp_wifi_internal_tx(ESP_IF_WIFI_STA, tx_buf, tx_len) == ESP_OK) { - netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE); - return tx_len; - } - else { - ESP_WIFI_DEBUG("sending WiFi packet failed"); - return -EIO; - } -} - -static int _esp_wifi_recv(netdev_t *netdev, void *buf, size_t len, void *info) -{ - ESP_WIFI_DEBUG("%p %p %u %p", netdev, buf, len, info); - - assert(netdev != NULL); - - if (!rx_buf[rx_buf_read].buffer) { - /* there is nothing in rx_buf */ - return 0; - } - - uint16_t size = rx_buf[rx_buf_read].len; - - if (buf == NULL && len == 0) { - /* just return the size */ - return size; - } - - if (buf && len >= size) { - /* copy the buffer */ - memcpy(buf, rx_buf[rx_buf_read].buffer, size); -#if ENABLE_DEBUG - ethernet_hdr_t *hdr = (ethernet_hdr_t *)buf; - - ESP_WIFI_DEBUG("received %u byte from addr " MAC_STR, - size, MAC_STR_ARG(hdr->src)); -#if MODULE_OD - od_hex_dump(buf, size, OD_WIDTH_DEFAULT); -#endif /* MODULE_OD */ -#endif /* ENABLE_DEBUG */ - } - - /* - * free the packet buffer and clean the rx_buf element at the read pointer, - * it covers the also the cases where the packet is simply dropped when - * (buf == NULL && len != 0) or (buf != NULL && len < size) - */ - esp_wifi_internal_free_rx_buffer(rx_buf[rx_buf_read].eb); - - critical_enter(); - rx_buf[rx_buf_read].buffer = NULL; - rx_buf[rx_buf_write].len = len; - rx_buf_read = (rx_buf_read + 1) % ESP_WIFI_MAX_RX_BUF; - critical_exit(); - - return size; -} - -static int _esp_wifi_get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len) -{ - ESP_WIFI_DEBUG("%s %p %p %u", netopt2str(opt), netdev, val, max_len); - - assert(netdev != NULL); - assert(val != NULL); - - esp_wifi_netdev_t* dev = (esp_wifi_netdev_t*)netdev; - - switch (opt) { - case NETOPT_ADDRESS: - assert(max_len >= ETHERNET_ADDR_LEN); - esp_wifi_get_mac(ESP_MAC_WIFI_STA,(uint8_t *)val); - return ETHERNET_ADDR_LEN; - case NETOPT_IS_WIRED: - return false; - case NETOPT_LINK_CONNECTED: - assert(max_len == 1); - *((netopt_enable_t *)val) = (dev->connected) ? NETOPT_ENABLE - : NETOPT_DISABLE; - return 1; - default: - return netdev_eth_get(netdev, opt, val, max_len); - } -} - -static int _esp_wifi_set(netdev_t *netdev, netopt_t opt, const void *val, size_t max_len) -{ - ESP_WIFI_DEBUG("%s %p %p %u", netopt2str(opt), netdev, val, max_len); - - assert(netdev != NULL); - assert(val != NULL); - - switch (opt) { - case NETOPT_ADDRESS: - assert(max_len == ETHERNET_ADDR_LEN); - esp_wifi_set_mac(ESP_MAC_WIFI_STA, (uint8_t *)val); - return ETHERNET_ADDR_LEN; - default: - return netdev_eth_set(netdev, opt, val, max_len); - } -} - -static void _esp_wifi_isr(netdev_t *netdev) -{ - ESP_WIFI_DEBUG("%p", netdev); - - assert(netdev != NULL); - - esp_wifi_netdev_t *dev = (esp_wifi_netdev_t *) netdev; - - dev->event &= ~ESP_WIFI_EVENT_RX_DONE; - while (rx_buf[rx_buf_read].buffer) { - dev->netdev.event_callback(netdev, NETDEV_EVENT_RX_COMPLETE); - } - if (dev->event & ESP_WIFI_EVENT_TX_DONE) { - dev->event &= ~ESP_WIFI_EVENT_TX_DONE; - dev->netdev.event_callback(netdev, NETDEV_EVENT_TX_COMPLETE); - } - if (dev->event & ESP_WIFI_EVENT_STA_CONNECTED) { - dev->event &= ~ESP_WIFI_EVENT_STA_CONNECTED; - dev->netdev.event_callback(netdev, NETDEV_EVENT_LINK_UP); - } - if (dev->event & ESP_WIFI_EVENT_STA_DISCONNECTED) { - dev->event &= ~ESP_WIFI_EVENT_STA_DISCONNECTED; - dev->netdev.event_callback(netdev, NETDEV_EVENT_LINK_DOWN); - } - - return; -} - -static const netdev_driver_t _esp_wifi_driver = -{ - .send = _esp_wifi_send, - .recv = _esp_wifi_recv, - .init = _esp_wifi_init, - .isr = _esp_wifi_isr, - .get = _esp_wifi_get, - .set = _esp_wifi_set, -}; - -#endif /* MODULE_ESP_WIFI */ -/**@}*/ diff --git a/cpu/esp32/esp-wifi/esp_wifi_netdev.h b/cpu/esp32/esp-wifi/esp_wifi_netdev.h deleted file mode 100644 index b36242322f6d..000000000000 --- a/cpu/esp32/esp-wifi/esp_wifi_netdev.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32_esp_wifi - * @{ - * - * @file - * @brief Network device driver for the ESP32 WiFi interface - * - * @author Gunar Schorcht - */ - -#ifndef ESP_WIFI_NETDEV_H -#define ESP_WIFI_NETDEV_H - -#include - -#include "mutex.h" -#include "net/ethernet.h" -#include "net/netdev.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Reference to the netdev device driver struct - */ -extern const netdev_driver_t esp_wifi_driver; - -/** - * @brief Device descriptor for ESP WiFi devices - */ -typedef struct -{ - netdev_t netdev; /**< netdev parent struct */ - - uint32_t event; /**< received event */ - bool connected; /**< indicates whether connected to AP */ - -} esp_wifi_netdev_t; - -#ifdef __cplusplus -} -#endif - -#endif /* ESP_WIFI_NETDEV_H */ -/** @} */ diff --git a/cpu/esp32/esp-wifi/esp_wifi_params.h b/cpu/esp32/esp-wifi/esp_wifi_params.h deleted file mode 100644 index e6c0c9adfb10..000000000000 --- a/cpu/esp32/esp-wifi/esp_wifi_params.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32_esp_wifi - * @ingroup cpu_esp32_conf - * @{ - * - * @file - * @brief Parameters for the ESP32 WiFi netdev interface - * - * @author Gunar Schorcht - */ - -#ifndef ESP_WIFI_PARAMS_H -#define ESP_WIFI_PARAMS_H - -#if defined(MODULE_ESP_WIFI) || defined(DOXYGEN) - -/** - * @name Set default configuration parameters for the ESP WiFi netdev driver - * @{ - */ - -/** - * @brief The size of the stack used for the ESP WIFI netdev driver thread. - */ -#ifndef ESP_WIFI_STACKSIZE -#define ESP_WIFI_STACKSIZE (THREAD_STACKSIZE_DEFAULT) -#endif - -/** - * @brief The priority of the ESP WiFi netdev driver thread. Should not be changed. - */ -#ifndef ESP_WIFI_PRIO -#define ESP_WIFI_PRIO (GNRC_NETIF_PRIO) -#endif - -/** - * @brief SSID of the AP to be used. - */ -#ifndef ESP_WIFI_SSID -#define ESP_WIFI_SSID "RIOT_AP" -#endif - -/** - * @brief Passphrase used for the AP as clear text (max. 64 chars). - */ -#ifndef ESP_WIFI_PASS -#define ESP_WIFI_PASS "ThisistheRIOTporttoESP" -#endif - -/**@}*/ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* MODULE_ESP_WIFI || DOXYGEN */ - -#endif /* ESP_WIFI_PARAMS_H */ -/**@}*/ diff --git a/cpu/esp32/esp_events.c b/cpu/esp32/esp_events.c deleted file mode 100644 index 4e3cf8a9a43b..000000000000 --- a/cpu/esp32/esp_events.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @{ - * - * @file - * @brief ESP system event handler - * - * @author Gunar Schorcht - * - * @} - */ - -#if defined(MODULE_ESP_WIFI_ANY) || defined(MODULE_ESP_ETH) - -#define ENABLE_DEBUG 0 -#include "debug.h" - -#include - -#include "esp_common.h" -#include "log.h" - -#include "esp_attr.h" -#include "esp_event_loop.h" -#include "irq_arch.h" - -#define MAX_HANDLER_NUM 5 - -static system_event_cb_t _handler[MAX_HANDLER_NUM] = {}; -static void* _handler_arg[MAX_HANDLER_NUM] = {}; - -esp_err_t esp_system_event_add_handler (system_event_cb_t handler, void *arg) -{ - int i; - - /* determine next free handler entry */ - for (i = 0; i < MAX_HANDLER_NUM; i++) { - if (_handler[i] == NULL) { - break; - } - } - - /* return if there is no free entry */ - if (i == MAX_HANDLER_NUM) { - return ESP_FAIL; - } - - /* set the handler and argument entry */ - _handler[i] = handler; - _handler_arg[i] = arg; - - return ESP_OK; -} - -esp_err_t esp_system_event_del_handler (system_event_cb_t handler) -{ - int i; - - /* determine the handler entry */ - for (i = 0; i < MAX_HANDLER_NUM; i++) { - if (_handler[i] == handler) { - break; - } - } - - /* return if entry was not found */ - if (i == MAX_HANDLER_NUM) { - return ESP_FAIL; - } - - /* clean handler and arg entry */ - _handler[i] = NULL; - _handler_arg[i] = NULL; - - return ESP_OK; -} - -static esp_err_t esp_system_event_handler(void *ctx, system_event_t *event) -{ - for (int i = 0; i < MAX_HANDLER_NUM; i++) { - if (_handler[i] != NULL) { - _handler[i](_handler_arg[i], event); - } - } - return ESP_OK; -} - -#endif - -void esp_event_handler_init(void) -{ - #if defined(MODULE_ESP_WIFI_ANY) || defined(MODULE_ESP_ETH) - esp_event_loop_init(esp_system_event_handler, NULL); - #endif -} diff --git a/cpu/esp32/exceptions.c b/cpu/esp32/exceptions.c deleted file mode 100644 index 693a4739172b..000000000000 --- a/cpu/esp32/exceptions.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @{ - * - * @file - * @brief ESP32 exception handling - * - * @author Gunar Schorcht - * @} - */ - -#define ENABLE_DEBUG 0 -#include "debug.h" - -#include -#include -#include - -#include "esp_common.h" -#include "irq.h" -#include "log.h" -#include "periph/pm.h" -#include "ps.h" - -#include "esp/common_macros.h" -#include "esp/xtensa_ops.h" -#include "rom/ets_sys.h" -#include "rom/rtc.h" -#include "rom/uart.h" -#include "sdk_conf.h" -#include "xtensa/corebits.h" -#include "freertos/xtensa_api.h" - -#ifdef MODULE_ESP_GDBSTUB -#include "esp_gdbstub.h" -#endif - -#ifdef MODULE_ESP_IDF_HEAP -#include "heap/esp_heap_caps.h" -#endif - -extern void malloc_stats (void); -extern unsigned int get_free_heap_size (void); -extern uint8_t _eheap; /* end of heap (defined in esp32.common.ld) */ -extern uint8_t _sheap; /* start of heap (defined in esp32.common.ld) */ - -static const char* exception_names [] = -{ - "IllegalInstructionCause", /* 0 */ - "SyscallCause", /* 1 */ - "InstructionFetchErrorCause", /* 2 */ - "LoadStoreErrorCause", /* 3 */ - "Level1InterruptCause", /* 4 */ - "AllocaCause", /* 5 */ - "IntegerDivideByZeroCause", /* 6 */ - "", /* 7 - reserved */ - "PrivilegedCause", /* 8 */ - "LoadStoreAlignmentCause", /* 9 */ - "", /* 10 - reserved */ - "", /* 11 - reserved */ - "InstrPIFDataErrorCause", /* 12 */ - "LoadStorePIFDataErrorCause", /* 13 */ - "InstrPIFAddrErrorCause", /* 14 */ - "LoadStorePIFAddrErrorCause", /* 15 */ - "InstTLBMissCause", /* 16 */ - "InstTLBMultiHitCause", /* 17 */ - "InstFetchPrivilegeCause", /* 18 */ - "", /* 19 - reserved */ - "InstFetchProhibitedCause", /* 20 */ - "", /* 21 - reserved */ - "", /* 22 - reserved */ - "", /* 23 - reserved */ - "LoadStoreTLBMissCause", /* 24 */ - "LoadStoreTLBMultiHitCause", /* 25 */ - "LoadStorePrivilegeCause", /* 26 */ - "", /* 27 - reserved */ - "LoadProhibitedCause", /* 28 */ - "StoreProhibitedCause", /* 29 */ - "", /* 30 - reserved */ - "", /* 31 - reserved */ - "Coprocessor0Disabled", /* 32 */ - "Coprocessor1Disabled", /* 33 */ - "Coprocessor2Disabled", /* 34 */ - "Coprocessor3Disabled", /* 35 */ - "Coprocessor4Disabled", /* 36 */ - "Coprocessor5Disabled", /* 37 */ - "Coprocessor6Disabled", /* 38 */ - "Coprocessor7Disabled", /* 39 */ -}; - -const char *reg_names[] = { - "pc ", "ps ", - "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", - "a6 ", "a7 ", "a8 ", "a9 ", "a10 ", "a11 ", - "a12 ", "a13 ", "a14 ", "A15 ", "SAR ", - "exccause", "excvaddr", "lbeg ", "lend ", "lcount " -}; - -void IRAM NORETURN exception_handler (XtExcFrame *frame) -{ - uint32_t excsave1; - uint32_t epc1; - uint32_t epc2; - uint32_t epc3; - uint32_t epc4; - RSR(excsave1, excsave1); - RSR(epc1, epc1); - RSR(epc2, epc2); - RSR(epc3, epc3); - RSR(epc4, epc4); - - #ifdef MODULE_ESP_GDBSTUB - esp_gdbstub_panic_handler(frame); - #endif - - ets_printf("EXCEPTION!! exccause=%d (%s) @%08x excvaddr=%08x\n\n", - frame->exccause, exception_names[frame->exccause], - excsave1, frame->excvaddr); - - #if defined(DEVELHELP) - #if defined(MODULE_PS) - ets_printf("processes:\n"); - ps(); - ets_printf("\n"); - #endif /* MODULE_PS */ - #ifdef MODULE_ESP_IDF_HEAP - heap_caps_print_heap_info(MALLOC_CAP_DEFAULT); - #else - ets_printf("\nheap: %u (free %u) byte\n", &_eheap - &_sheap, get_free_heap_size()); - #endif /* MODULE_ESP_IDF_HEAP */ - - ets_printf("\nregister set\n"); - ets_printf("pc : %08x\t", frame->pc); - ets_printf("ps : %08x\t", frame->ps); - ets_printf("exccause: %08x\t", frame->exccause); - ets_printf("excvaddr: %08x\n", frame->excvaddr); - ets_printf("epc1 : %08x\t", epc1); - ets_printf("epc2 : %08x\t", epc2); - ets_printf("epc3 : %08x\t", epc3); - ets_printf("epc4 : %08x\n", epc4); - ets_printf("a0 : %08x\t", frame->a0); - ets_printf("a1 : %08x\t", frame->a1); - ets_printf("a2 : %08x\t", frame->a2); - ets_printf("a3 : %08x\n", frame->a3); - ets_printf("a4 : %08x\t", frame->a4); - ets_printf("a5 : %08x\t", frame->a5); - ets_printf("a6 : %08x\t", frame->a6); - ets_printf("a7 : %08x\n", frame->a7); - ets_printf("a8 : %08x\t", frame->a8); - ets_printf("a9 : %08x\t", frame->a9); - ets_printf("a10 : %08x\t", frame->a10); - ets_printf("a11 : %08x\n", frame->a11); - ets_printf("a12 : %08x\t", frame->a12); - ets_printf("a13 : %08x\t", frame->a13); - ets_printf("a14 : %08x\t", frame->a14); - ets_printf("a15 : %08x\n", frame->a15); - ets_printf("lbeg : %08x\t", frame->lbeg); - ets_printf("lend : %08x\t", frame->lend); - ets_printf("lcount : %08x\n", frame->lcount); - #endif /* DEVELHELP */ - - /* restart */ - /* TODO: Improvement - Normally, we should try to restart the system. However, this - will not work after some exceptions, e.g., the LoadStoreErrorCause. - Therefore, we break the execution and wait for the WDT reset. Maybe - there is better way. If debugger is active, 'break 0,0' stops - execution in debugger. */ - __asm__ volatile ("break 0,0"); - - UNREACHABLE(); -} - -void init_exceptions (void) -{ - xt_set_exception_handler(EXCCAUSE_UNALIGNED, exception_handler); - xt_set_exception_handler(EXCCAUSE_ILLEGAL, exception_handler); - xt_set_exception_handler(EXCCAUSE_INSTR_ERROR, exception_handler); - xt_set_exception_handler(EXCCAUSE_LOAD_STORE_ERROR, exception_handler); - xt_set_exception_handler(EXCCAUSE_LOAD_PROHIBITED, exception_handler); - xt_set_exception_handler(EXCCAUSE_STORE_PROHIBITED, exception_handler); - xt_set_exception_handler(EXCCAUSE_PRIVILEGED, exception_handler); -} - -void IRAM NORETURN panic_arch(void) -{ - #if defined(DEVELHELP) - - #ifdef MODULE_ESP_IDF_HEAP - heap_caps_print_heap_info(MALLOC_CAP_DEFAULT); - #else - ets_printf("\nheap: %u (free %u) byte\n", &_eheap - &_sheap, get_free_heap_size()); - #endif /* MODULE_ESP_IDF_HEAP */ - - /* break in debugger or reboot after WDT */ - __asm__ volatile ("break 0,0"); - - #else /* DEVELHELP */ - - /* restart */ - software_reset(); - - #endif /* DEVELHELP */ - - UNREACHABLE(); -} - -void _panic_handler(uint32_t addr) -{ - ets_printf("#! _xt_panic called from 0x%08x: powering off\n", addr); - pm_off(); - while (1) { }; -} diff --git a/cpu/esp32/freertos/Makefile b/cpu/esp32/freertos/Makefile index 7b06629ca8dc..94a83b376970 100644 --- a/cpu/esp32/freertos/Makefile +++ b/cpu/esp32/freertos/Makefile @@ -1,3 +1,3 @@ -MODULE=riot_freertos +MODULE=esp_freertos include $(RIOTBASE)/Makefile.base diff --git a/cpu/esp32/freertos/event_groups.c b/cpu/esp32/freertos/event_groups.c deleted file mode 100644 index 8cfdfd741878..000000000000 --- a/cpu/esp32/freertos/event_groups.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * FreeRTOS to RIOT-OS adaption module for source code compatibility - */ - -#ifndef DOXYGEN - -#define ENABLE_DEBUG (0) -#include "debug.h" - -#include - -#include "rom/ets_sys.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/event_groups.h" - -EventGroupHandle_t xEventGroupCreate (void) -{ - ets_printf("%s\n", __func__); - return NULL; -} - -void vEventGroupDelete (EventGroupHandle_t xEventGroup) -{ - ets_printf("%s\n", __func__); - return NULL; -} - -EventBits_t xEventGroupSetBits (EventGroupHandle_t xEventGroup, - const EventBits_t uxBitsToSet) -{ - ets_printf("%s\n", __func__); - return NULL; -} - -EventBits_t xEventGroupClearBits (EventGroupHandle_t xEventGroup, - const EventBits_t uxBitsToClear ) -{ - ets_printf("%s\n", __func__); - return NULL; -} - -EventBits_t xEventGroupWaitBits (const EventGroupHandle_t xEventGroup, - const EventBits_t uxBitsToWaitFor, - const BaseType_t xClearOnExit, - const BaseType_t xWaitForAllBits, - TickType_t xTicksToWait) -{ - ets_printf("%s\n", __func__); - return NULL; -} - -#endif /* DOXYGEN */ diff --git a/cpu/esp32/freertos/queue.c b/cpu/esp32/freertos/queue.c deleted file mode 100644 index 67445f246c4f..000000000000 --- a/cpu/esp32/freertos/queue.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * FreeRTOS to RIOT-OS adaption module for source code compatibility - */ - -#ifndef DOXYGEN - -#define ENABLE_DEBUG (0) -#include "debug.h" - -#include - -#include "esp_common.h" -#include "esp_attr.h" -#include "log.h" -#include "mutex.h" -#include "rmutex.h" -#include "thread.h" - -#include "rom/ets_sys.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/semphr.h" -#include "freertos/task.h" - -#undef portENTER_CRITICAL -#undef portEXIT_CRITICAL -#define portENTER_CRITICAL(mux) vTaskEnterCritical(mux) -#define portEXIT_CRITICAL(mux) vTaskExitCritical(mux) - -/* - * In FreeRTOS different types of semaphores, mutexes and queues are all - * mapped to a single generic queue type. With all these different types, - * single functions for send, receive, give and take are then used. To be - * able to dsitinguish between these different types in RIOT, we need typed - * objects. - */ -typedef struct { - uint8_t type; /* type of the queue, MUST be the first element */ - mutex_t mutex; /* mutex to secure operations on the queue */ - list_node_t sending; /* threads that are waiting to send */ - list_node_t receiving; /* threads that are waiting to receive */ - uint8_t* queue; /* the queue of waiting items */ - uint32_t item_size; /* size of each item in the queue */ - uint32_t item_num; /* num of items that can be stored in queue */ - uint32_t item_front; /* first item in queue */ - uint32_t item_tail; /* last item in queue */ - uint32_t item_level; /* num of items stored in queue */ -} _queue_t; - -QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, - const UBaseType_t uxItemSize, - const uint8_t ucQueueType ) -{ - DEBUG("%s pid=%d len=%u size=%u type=%u ", __func__, - thread_getpid(), uxQueueLength, uxItemSize, ucQueueType); - - uint32_t queue_size = uxQueueLength * uxItemSize; - _queue_t* queue = malloc(sizeof(_queue_t) + queue_size); - - mutex_init(&queue->mutex); - - queue->type = ucQueueType; - queue->receiving.next = NULL; - queue->sending.next = NULL; - queue->queue = (queue_size) ? (uint8_t*)queue + sizeof(_queue_t) : NULL; - queue->item_num = uxQueueLength; - queue->item_size = uxItemSize; - queue->item_front = 0; - queue->item_tail = 0; - queue->item_level = 0; - - DEBUG("queue=%p\n", queue); - - return queue; -} - -#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 ) - -QueueHandle_t xQueueCreateCountingSemaphore (const UBaseType_t uxMaxCount, - const UBaseType_t uxInitialCount) -{ - _queue_t* queue; - - CHECK_PARAM_RET(uxMaxCount != 0, NULL); - CHECK_PARAM_RET(uxInitialCount <= uxMaxCount, NULL); - - queue = xQueueGenericCreate(uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, - queueQUEUE_TYPE_COUNTING_SEMAPHORE); - - DEBUG("%s pid=%d queue=%p\n", __func__, thread_getpid(), queue); - - if (queue != NULL) { - queue->item_level = uxInitialCount; - queue->item_tail = (queue->item_front + queue->item_level) % queue->item_num; - } - - return queue; -} - -void vQueueDelete( QueueHandle_t xQueue ) -{ - DEBUG("%s pid=%d queue=%p\n", __func__, thread_getpid(), xQueue); - - CHECK_PARAM(xQueue != NULL); - free(xQueue); -} - -BaseType_t IRAM_ATTR _queue_generic_send(QueueHandle_t xQueue, - const void * const pvItemToQueue, - const BaseType_t xCopyPosition, - TickType_t xTicksToWait, - BaseType_t * const pxHigherPriorityTaskWoken) -{ - DEBUG("%s pid=%d prio=%d queue=%p pos=%d wait=%u woken=%p\n", __func__, - thread_getpid(), sched_threads[thread_getpid()]->priority, - xQueue, xCopyPosition, xTicksToWait, pxHigherPriorityTaskWoken); - - _queue_t* queue = (_queue_t*)xQueue; - - CHECK_PARAM_RET(queue != NULL, pdFAIL); - - while (1) { - taskENTER_CRITICAL(&queue->mutex); - - /* is there still space in the queue */ - if (queue->item_level < queue->item_num || xCopyPosition == queueOVERWRITE) { - uint32_t write_pos; - /* determine the write position in the queue and update positions */ - if (xCopyPosition == queueSEND_TO_BACK) { - write_pos = queue->item_tail; - queue->item_tail = (queue->item_tail + 1) % queue->item_num; - queue->item_level++; - } - else if (xCopyPosition == queueSEND_TO_FRONT) { - queue->item_front = (queue->item_front - 1) % queue->item_num; - queue->item_level++; - write_pos = queue->item_front; - } - else { /* queueOVERWRITE */ - write_pos = queue->item_front; - if (queue->item_level == 0) { - queue->item_level++; - } - } - - /* if the item has no 0 size, copy it to the according place in queue */ - if (queue->item_size && queue->queue && pvItemToQueue) { - memcpy(queue->queue + write_pos * queue->item_size, - pvItemToQueue, queue->item_size); - } - - /* unlock waiting receiving thread */ - if (queue->receiving.next != NULL) { - list_node_t *next = list_remove_head(&queue->receiving); - thread_t *process = container_of((clist_node_t*)next, thread_t, rq_entry); - uint8_t process_priority = process->priority; - uint8_t my_priority = sched_threads[thread_getpid()]->priority; - - if (pxHigherPriorityTaskWoken) { - *pxHigherPriorityTaskWoken = process_priority < my_priority; - } - - DEBUG("%s pid=%d queue=%p unlock waiting\n", __func__, - thread_getpid(), xQueue); - - sched_set_status(process, STATUS_PENDING); - sched_switch(process_priority); - } - - DEBUG("%s pid=%d queue=%p return pdPASS\n", __func__, - thread_getpid(), xQueue); - taskEXIT_CRITICAL(&queue->mutex); - return pdPASS; - } - else if (xTicksToWait == 0) { - /* if there was no space and timeout = 0, return with error */ - - DEBUG("%s pid=%d queue=%p return errQUEUE_FULL\n", __func__, - thread_getpid(), xQueue); - - taskEXIT_CRITICAL(&queue->mutex); - return errQUEUE_FULL; - } - else { - /* suspend the calling thread to wait for space in the queue */ - thread_t *me = (thread_t*)sched_active_thread; - sched_set_status(me, STATUS_SEND_BLOCKED); - /* waiting list is sorted by priority */ - thread_add_to_list(&queue->sending, me); - - DEBUG("%s pid=%d queue=%p suspended calling thread\n", __func__, - thread_getpid(), xQueue); - - taskEXIT_CRITICAL(&queue->mutex); - thread_yield_higher(); - - /* TODO timeout handling with xTicksToWait */ - DEBUG("%s pid=%d queue=%p continue calling thread\n", __func__, - thread_getpid(), xQueue); - } - } - return errQUEUE_FULL; -} - -BaseType_t IRAM_ATTR _queue_generic_recv (QueueHandle_t xQueue, - void * const pvBuffer, - TickType_t xTicksToWait, - const BaseType_t xJustPeeking, - BaseType_t * const pxHigherPriorityTaskWoken) -{ - DEBUG("%s pid=%d prio=%d queue=%p wait=%u peek=%u woken=%p\n", __func__, - thread_getpid(), sched_threads[thread_getpid()]->priority, - xQueue, xTicksToWait, xJustPeeking, pxHigherPriorityTaskWoken); - - _queue_t* queue = (_queue_t*)xQueue; - - CHECK_PARAM_RET(queue != NULL, pdFAIL); - - while (1) { - taskENTER_CRITICAL(&queue->mutex); - - if (queue->item_level == 0 && xTicksToWait == 0) { - /* if there was no element in queue and timeout = 0, return with error */ - - DEBUG("%s pid=%d queue=%p return errQUEUE_EMPTY\n", __func__, - thread_getpid(), xQueue); - - taskEXIT_CRITICAL(&queue->mutex); - return errQUEUE_EMPTY; - } - - if (queue->item_level > 0) { - /* if the item has no 0 size, copy it from queue to buffer */ - if (queue->item_size && queue->item_num && queue->queue && pvBuffer) { - memcpy(pvBuffer, - queue->queue + queue->item_front * queue->item_size, - queue->item_size); - } - /* when only peeking leave the element in queue */ - if (xJustPeeking == pdFALSE) { - queue->item_front = (queue->item_front + 1) % queue->item_num; - queue->item_level--; - - /* unlock waiting sending thread */ - if (queue->sending.next != NULL) { - list_node_t *next = list_remove_head(&queue->sending); - thread_t *process = container_of((clist_node_t*)next, - thread_t, rq_entry); - uint16_t process_priority = process->priority; - uint8_t my_priority = sched_threads[thread_getpid()]->priority; - - if (pxHigherPriorityTaskWoken) { - *pxHigherPriorityTaskWoken = process_priority < my_priority; - } - - DEBUG("%s pid=%d queue=%p unlock waiting\n", __func__, - thread_getpid(), xQueue); - - sched_set_status(process, STATUS_PENDING); - sched_switch(process_priority); - } - } - - DEBUG("%s pid=%d queue=%p return pdPASS\n", __func__, - thread_getpid(), xQueue); - - taskEXIT_CRITICAL(&queue->mutex); - return pdPASS; - } - else { - /* suspend the calling thread to wait for an item in the queue */ - thread_t *me = (thread_t*)sched_active_thread; - sched_set_status(me, STATUS_RECEIVE_BLOCKED); - /* waiting list is sorted by priority */ - thread_add_to_list(&queue->receiving, me); - - DEBUG("%s pid=%d queue=%p suspended calling thread\n", __func__, - thread_getpid(), xQueue); - - taskEXIT_CRITICAL(&queue->mutex); - thread_yield_higher(); - - /* TODO timeout handling with xTicksToWait */ - DEBUG("%s pid=%d queue=%p continue calling thread\n", __func__, - thread_getpid(), xQueue); - } - } -} - -BaseType_t IRAM_ATTR xQueueGenericSend( QueueHandle_t xQueue, - const void * const pvItemToQueue, - TickType_t xTicksToWait, - const BaseType_t xCopyPosition ) -{ - DEBUG("%s pid=%d prio=%d queue=%p wait=%u pos=%d\n", __func__, - thread_getpid(), sched_threads[thread_getpid()]->priority, - xQueue, xTicksToWait, xCopyPosition); - - return _queue_generic_send(xQueue, pvItemToQueue, xCopyPosition, - xTicksToWait, NULL); -} - -BaseType_t IRAM_ATTR xQueueGenericSendFromISR( QueueHandle_t xQueue, - const void * const pvItemToQueue, - BaseType_t * const pxHigherPriorityTaskWoken, - const BaseType_t xCopyPosition ) -{ - DEBUG("%s pid=%d prio=%d queue=%p pos=%d woken=%p\n", __func__, - thread_getpid(), sched_threads[thread_getpid()]->priority, - xQueue, xCopyPosition, pxHigherPriorityTaskWoken); - - return _queue_generic_send(xQueue, pvItemToQueue, xCopyPosition, - 0, pxHigherPriorityTaskWoken); -} - -BaseType_t IRAM_ATTR xQueueGenericReceive (QueueHandle_t xQueue, - void * const pvBuffer, - TickType_t xTicksToWait, - const BaseType_t xJustPeeking) -{ - DEBUG("%s pid=%d prio=%d queue=%p wait=%u peek=%d\n", __func__, - thread_getpid(), sched_threads[thread_getpid()]->priority, - xQueue, xTicksToWait, xJustPeeking); - - return _queue_generic_recv(xQueue, pvBuffer, xTicksToWait, - xJustPeeking, NULL); -} - -BaseType_t IRAM_ATTR xQueueReceiveFromISR (QueueHandle_t xQueue, - void * const pvBuffer, - BaseType_t * const pxHigherPriorityTaskWoken) -{ - DEBUG("%s pid=%d prio=%d queue=%p woken=%p\n", __func__, - thread_getpid(), sched_threads[thread_getpid()]->priority, - xQueue, pxHigherPriorityTaskWoken); - - return _queue_generic_recv(xQueue, pvBuffer, 0, - 0, pxHigherPriorityTaskWoken); -} - -UBaseType_t uxQueueMessagesWaiting( QueueHandle_t xQueue ) -{ - _queue_t* queue = (_queue_t*)xQueue; - - CHECK_PARAM_RET(queue != NULL, 0); - - return queue->item_level; -} - -BaseType_t xQueueGiveFromISR (QueueHandle_t xQueue, - BaseType_t * const pxHigherPriorityTaskWoken) -{ - ets_printf("%s\n", __func__); - return pdFALSE; -} - -#endif /* DOXYGEN */ diff --git a/cpu/esp32/freertos/semphr.c b/cpu/esp32/freertos/semphr.c deleted file mode 100644 index ded1630e1fa1..000000000000 --- a/cpu/esp32/freertos/semphr.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * FreeRTOS to RIOT-OS adaption module for source code compatibility - */ - -#ifndef DOXYGEN - -#define ENABLE_DEBUG (0) -#include "debug.h" - -#include - -#include "esp_common.h" -#include "irq_arch.h" -#include "log.h" -#include "mutex.h" -#include "rmutex.h" - -#include "freertos/FreeRTOS.h" - -/* - * In FreeRTOS different types of semaphores, mutexes and queues are all - * mapped to a single generic queue type. With all these different types, - * single functions for send, receive, give and take are then used. To be - * able to dsitinguish between these different types in RIOT, we need typed - * objects. - */ -typedef struct { - uint8_t type; /* type of the mutex, MUST be the first element */ - mutex_t mutex; /* the mutex */ -} _mutex_t; - -typedef struct { - uint8_t type; /* type of the mutex, MUST be the first element */ - rmutex_t rmutex; /* the mutex */ -} _rmutex_t; - -SemaphoreHandle_t xSemaphoreCreateMutex(void) -{ - _mutex_t* _tmp = (_mutex_t*)malloc (sizeof(_mutex_t)); - _tmp->type = queueQUEUE_TYPE_MUTEX; - mutex_init(&_tmp->mutex); - - DEBUG("%s mutex=%p\n", __func__, _tmp); - return _tmp; -} - -void vSemaphoreDelete( SemaphoreHandle_t xSemaphore ) -{ - DEBUG("%s mutex=%p\n", __func__, xSemaphore); - - CHECK_PARAM(xSemaphore != NULL); - free(xSemaphore); -} - -BaseType_t xSemaphoreGive (SemaphoreHandle_t xSemaphore) -{ - DEBUG("%s mutex=%p\n", __func__, xSemaphore); - - CHECK_PARAM_RET(xSemaphore != NULL, pdFALSE); - - uint8_t type = ((_mutex_t*)xSemaphore)->type; - mutex_t* mutex= &((_mutex_t*)xSemaphore)->mutex; - - switch (type) { - case queueQUEUE_TYPE_MUTEX: - mutex_unlock(mutex); - break; - case queueQUEUE_TYPE_RECURSIVE_MUTEX: - return xSemaphoreGiveRecursive (xSemaphore); - default: - return xQueueGenericSend(xSemaphore, NULL, 0, queueSEND_TO_BACK); - } - - return pdTRUE; -} - -BaseType_t xSemaphoreTake (SemaphoreHandle_t xSemaphore, - TickType_t xTicksToWait) -{ - DEBUG("%s mutex=%p wait=%u\n", __func__, xSemaphore, xTicksToWait); - - CHECK_PARAM_RET(xSemaphore != NULL, pdFALSE); - - uint8_t type = ((_mutex_t*)xSemaphore)->type; - mutex_t* mutex= &((_mutex_t*)xSemaphore)->mutex; - - switch (type) { - case queueQUEUE_TYPE_MUTEX: - { - if (xTicksToWait == 0) { - return (mutex_trylock(mutex) == 1) ? pdPASS : pdFAIL; - } - else { - mutex_lock(mutex); - /* TODO timeout handling */ - return pdTRUE; - } - break; - } - case queueQUEUE_TYPE_RECURSIVE_MUTEX: - return xSemaphoreTakeRecursive (xSemaphore, xTicksToWait); - - default: - return xQueueGenericReceive(xSemaphore, NULL, xTicksToWait, pdFALSE); - } -} - -SemaphoreHandle_t xSemaphoreCreateRecursiveMutex(void) -{ - _rmutex_t* _tmp = (_rmutex_t*)malloc (sizeof(_rmutex_t)); - _tmp->type = queueQUEUE_TYPE_RECURSIVE_MUTEX; - rmutex_init(&_tmp->rmutex); - - DEBUG("%s rmutex=%p\n", __func__, _tmp); - - return _tmp; -} - -BaseType_t xSemaphoreGiveRecursive (SemaphoreHandle_t xSemaphore) -{ - DEBUG("%s rmutex=%p\n", __func__, xSemaphore); - - CHECK_PARAM_RET(xSemaphore != NULL, pdFALSE); - CHECK_PARAM_RET(((_rmutex_t*)xSemaphore)->type == - queueQUEUE_TYPE_RECURSIVE_MUTEX, pdFALSE); - - rmutex_unlock(&((_rmutex_t*)xSemaphore)->rmutex); - return pdTRUE; -} - -BaseType_t xSemaphoreTakeRecursive (SemaphoreHandle_t xSemaphore, - TickType_t xTicksToWait) -{ - DEBUG("%s rmutex=%p wait=%u\n", __func__, xSemaphore, xTicksToWait); - - CHECK_PARAM_RET(xSemaphore != NULL, pdFALSE); - CHECK_PARAM_RET(((_rmutex_t*)xSemaphore)->type == - queueQUEUE_TYPE_RECURSIVE_MUTEX, pdFALSE); - - BaseType_t ret = pdTRUE; - rmutex_t* rmutex = &((_rmutex_t*)xSemaphore)->rmutex; - - if (xTicksToWait == 0) { - ret = (rmutex_trylock(rmutex) == 1) ? pdPASS : pdFAIL; - } - else { - rmutex_lock(&((_rmutex_t*)xSemaphore)->rmutex); - /* TODO timeout handling */ - } - - return ret; -} - -void vPortCPUAcquireMutex(portMUX_TYPE *mux) -{ - DEBUG("%s pid=%d prio=%d mux=%p\n", __func__, - thread_getpid(), sched_threads[thread_getpid()]->priority, mux); - critical_enter(); - mutex_lock(mux); /* lock the mutex with interrupts disabled */ - critical_exit(); -} - -void vPortCPUReleaseMutex(portMUX_TYPE *mux) -{ - DEBUG("%s pid=%d prio=%d mux=%p\n", __func__, - thread_getpid(), sched_threads[thread_getpid()]->priority, mux); - critical_enter(); - mutex_unlock(mux); /* unlock the mutex with interrupts disabled */ - critical_exit(); -} - -#endif /* DOXYGEN */ diff --git a/cpu/esp32/freertos/task.c b/cpu/esp32/freertos/task.c deleted file mode 100644 index 11f754aee66b..000000000000 --- a/cpu/esp32/freertos/task.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * FreeRTOS to RIOT-OS adaption module for source code compatibility - */ - -#ifndef DOXYGEN - -#define ENABLE_DEBUG (0) -#include "debug.h" - -#include - -#include "esp_common.h" -#include "esp_attr.h" -#include "log.h" -#include "syscalls.h" -#include "thread.h" -#include "xtimer.h" - -#include "soc/soc.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#define MHZ 1000000 - -/** - * @brief Architecture specific data of thread control blocks - */ -typedef struct { - uint32_t saved_int_state; - uint32_t critical_nesting; -} thread_arch_ext_t; - -volatile thread_arch_ext_t threads_arch_exts[KERNEL_PID_LAST + 1] = {}; - -BaseType_t xTaskCreatePinnedToCore (TaskFunction_t pvTaskCode, - const char * const pcName, - const uint32_t usStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - TaskHandle_t * const pvCreatedTask, - const BaseType_t xCoreID) -{ - /* FreeRTOS priority values have to be inverted */ - uxPriority = SCHED_PRIO_LEVELS - uxPriority - 1; - - DEBUG("%s name=%s size=%d prio=%d pvCreatedTask=%p ", - __func__, pcName, usStackDepth, uxPriority, pvCreatedTask); - - char* stack = malloc(usStackDepth + sizeof(thread_t)); - - if (!stack) { - return pdFALSE; - } - kernel_pid_t pid = thread_create(stack, - usStackDepth + sizeof(thread_t), - uxPriority, - THREAD_CREATE_WOUT_YIELD | - THREAD_CREATE_STACKTEST, - (thread_task_func_t)pvTaskCode, - pvParameters, pcName); - DEBUG("pid=%d\n", pid); - - if (pvCreatedTask) { - *pvCreatedTask = (TaskHandle_t)(0L + pid); - } - - return (pid < 0) ? pdFALSE : pdTRUE; -} - -BaseType_t xTaskCreate (TaskFunction_t pvTaskCode, - const char * const pcName, - const uint32_t usStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - TaskHandle_t * const pvCreatedTask) -{ - return xTaskCreatePinnedToCore (pvTaskCode, - pcName, - usStackDepth, - pvParameters, - uxPriority, - pvCreatedTask, - PRO_CPU_NUM); -} - -void vTaskDelete (TaskHandle_t xTaskToDelete) -{ - DEBUG("%s pid=%d task=%p\n", __func__, thread_getpid(), xTaskToDelete); - - CHECK_PARAM(xTaskToDelete != NULL); - - uint32_t pid = (uint32_t)xTaskToDelete; - - /* remove old task from scheduling */ - thread_t* thread = (thread_t*)sched_threads[pid]; - sched_set_status(thread, STATUS_STOPPED); - sched_threads[pid] = NULL; - sched_num_threads--; - sched_active_thread = NULL; - - /* determine the new running task */ - sched_run(); -} - -TaskHandle_t xTaskGetCurrentTaskHandle(void) -{ - DEBUG("%s pid=%d\n", __func__, thread_getpid()); - - uint32_t pid = thread_getpid(); - return (TaskHandle_t)pid; -} - -void vTaskDelay( const TickType_t xTicksToDelay ) -{ - uint64_t us = xTicksToDelay * MHZ / xPortGetTickRateHz(); - xtimer_usleep(us); -} - -TickType_t xTaskGetTickCount (void) -{ - return system_get_time() / USEC_PER_MSEC / portTICK_PERIOD_MS; -} - -void vTaskEnterCritical( portMUX_TYPE *mux ) -{ - /* determine calling thread pid (can't fail) */ - kernel_pid_t my_pid = thread_getpid(); - - DEBUG("%s pid=%d prio=%d mux=%p\n", __func__, - my_pid, sched_threads[my_pid]->priority, mux); - - /* disable interrupts */ - uint32_t state = irq_disable(); - - /* Locking the given mutex does not work here, as this function can also - be called in the interrupt context. Therefore, the given mutex is not - used. Instead, the basic default FreeRTOS mechanism for critical - sections is used by simply disabling interrupts. Since context - switches for the ESP32 are also based on interrupts, there is no - possibility that another thread will enter the critical section - once the interrupts are disabled. */ - /* mutex_lock(mux); */ /* TODO should be only a spin lock */ - - /* increment nesting counter and save old interrupt level */ - threads_arch_exts[my_pid].critical_nesting++; - if (threads_arch_exts[my_pid].critical_nesting == 1) { - threads_arch_exts[my_pid].saved_int_state = state; - } -} - -void vTaskExitCritical( portMUX_TYPE *mux ) -{ - /* determine calling thread pid (can't fail) */ - kernel_pid_t my_pid = thread_getpid(); - - DEBUG("%s pid=%d prio=%d mux=%p\n", __func__, - my_pid, sched_threads[my_pid]->priority, mux); - - /* The given mutex is not used (see vTaskEnterCritical) and has not to - be unlocked here. */ - /* mutex_unlock(mux); */ /* TODO should be only a spin lock */ - - /* decrement nesting counter and restore old interrupt level */ - if (threads_arch_exts[my_pid].critical_nesting) { - threads_arch_exts[my_pid].critical_nesting--; - if (threads_arch_exts[my_pid].critical_nesting == 0) { - irq_restore(threads_arch_exts[my_pid].saved_int_state); - } - } -} - - -#endif /* DOXYGEN */ diff --git a/cpu/esp32/freertos/timers.c b/cpu/esp32/freertos/timers.c deleted file mode 100644 index 8ecf2779e649..000000000000 --- a/cpu/esp32/freertos/timers.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * FreeRTOS to RIOT-OS adaption module for source code compatibility - */ - -#ifndef DOXYGEN - -#ifdef MODULE_XTIMER - -#define ENABLE_DEBUG 0 -#include "debug.h" - -#include - -#include "esp_common.h" -#include "esp_attr.h" -#include "log.h" -#include "xtimer.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/timers.h" - -typedef struct { - xtimer_t xtimer; /* xtimer object */ - const char* name; /* FreeRTOS timer name */ - uint32_t period; /* in us */ - bool autoreload; /* FreeRTOS timer reload indicator */ - const void* timerid; /* FreeRTOS timer id */ - TimerCallbackFunction_t cb; /* FreeRTOS callback function */ -} freertos_xtimer_t; - -static void IRAM_ATTR _xtimer_callback (void *arg) -{ - CHECK_PARAM(arg != NULL); - - freertos_xtimer_t* timer = (freertos_xtimer_t*)arg; - - if (timer->autoreload) { - xtimer_set(&timer->xtimer, timer->period); - } - - if (timer->cb) { - timer->cb(arg); - } -} - -TimerHandle_t xTimerCreate (const char * const pcTimerName, - const TickType_t xTimerPeriod, - const UBaseType_t uxAutoReload, - void * const pvTimerID, - TimerCallbackFunction_t pxCallbackFunction) -{ - freertos_xtimer_t* timer = malloc(sizeof(freertos_xtimer_t)); - if (timer == NULL) { - return NULL; - } - - /* FreeRTOS timer parameter */ - timer->name = pcTimerName; - timer->period = xTimerPeriod * portTICK_PERIOD_MS * USEC_PER_MSEC; - timer->autoreload = uxAutoReload; - timer->timerid = pvTimerID; - timer->cb = pxCallbackFunction; - - /* xtimer parameter */ - timer->xtimer.callback = _xtimer_callback; - timer->xtimer.arg = timer; - - return timer; -} - -BaseType_t xTimerDelete(TimerHandle_t xTimer, TickType_t xBlockTime) -{ - CHECK_PARAM_RET(xTimer != NULL, pdFALSE); - - freertos_xtimer_t* timer = (freertos_xtimer_t*)xTimer; - xtimer_remove(&timer->xtimer); - free(timer); - - return pdTRUE; -} - -BaseType_t xTimerStart (TimerHandle_t xTimer, TickType_t xBlockTime) -{ - CHECK_PARAM_RET(xTimer != NULL, pdFALSE); - - freertos_xtimer_t* timer = (freertos_xtimer_t*)xTimer; - xtimer_set(&timer->xtimer, timer->period); - - return pdTRUE; -} - -BaseType_t xTimerStop (TimerHandle_t xTimer, TickType_t xBlockTime) -{ - CHECK_PARAM_RET(xTimer != NULL, pdFALSE); - - freertos_xtimer_t* timer = (freertos_xtimer_t*)xTimer; - xtimer_remove(&timer->xtimer); - - return pdTRUE; -} - -#endif /* MODULE_XTIMER */ - -#endif /* DOXYGEN */ diff --git a/cpu/esp32/gen_esp32part.py b/cpu/esp32/gen_esp32part.py deleted file mode 100755 index ef16c3bfb6ad..000000000000 --- a/cpu/esp32/gen_esp32part.py +++ /dev/null @@ -1,453 +0,0 @@ -#!/usr/bin/env python -# -# ESP32 partition table generation tool -# -# Converts partition tables to/from CSV and binary formats. -# -# See http://esp-idf.readthedocs.io/en/latest/api-guides/partition-tables.html -# for explanation of partition table structure and uses. -# -# 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. -from __future__ import print_function, division -import argparse -import os -import re -import struct -import sys -import hashlib -import binascii - -MAX_PARTITION_LENGTH = 0xC00 # 3K for partition data (96 entries) leaves 1K in a 4K sector for signature -SHA256_PARTITION_BEGIN = b"\xEB\xEB" + b"\xFF" * 14 # The first 2 bytes are like magic numbers for SHA256 sum - -__version__ = '1.0' - -quiet = False -sha256sum = True - - -def status(msg): - """ Print status message to stderr """ - if not quiet: - critical(msg) - - -def critical(msg): - """ Print critical message to stderr """ - if not quiet: - sys.stderr.write(msg) - sys.stderr.write('\n') - - -class PartitionTable(list): - def __init__(self): - super(PartitionTable, self).__init__(self) - - @classmethod - def from_csv(cls, csv_contents): - res = PartitionTable() - lines = csv_contents.splitlines() - - def expand_vars(f): - f = os.path.expandvars(f) - m = re.match(r'(?= MAX_PARTITION_LENGTH: - raise InputError("Binary partition table length (%d) longer than max" % len(result)) - result += b"\xFF" * (MAX_PARTITION_LENGTH - len(result)) # pad the sector, for signing - return result - - def to_csv(self, simple_formatting=False): - rows = ["# Espressif ESP32 Partition Table", - "# Name, Type, SubType, Offset, Size, Flags"] - rows += [x.to_csv(simple_formatting) for x in self] - return "\n".join(rows) + "\n" - - -class PartitionDefinition(object): - APP_TYPE = 0x00 - DATA_TYPE = 0x01 - TYPES = { - "app": APP_TYPE, - "data": DATA_TYPE, - } - - # Keep this map in sync with esp_partition_subtype_t enum in esp_partition.h - SUBTYPES = { - APP_TYPE: { - "factory": 0x00, - "test": 0x20, - }, - DATA_TYPE: { - "ota": 0x00, - "phy": 0x01, - "nvs": 0x02, - "coredump": 0x03, - "esphttpd": 0x80, - "fat": 0x81, - "spiffs": 0x82, - }, - } - - MAGIC_BYTES = b"\xAA\x50" - - ALIGNMENT = { - APP_TYPE: 0x10000, - DATA_TYPE: 0x04, - } - - # dictionary maps flag name (as used in CSV flags list, property name) - # to bit set in flags words in binary format - FLAGS = { - "encrypted": 0 - } - - # add subtypes for the 16 OTA slot values ("ota_XXX, etc.") - for ota_slot in range(16): - SUBTYPES[TYPES["app"]]["ota_%d" % ota_slot] = 0x10 + ota_slot - - def __init__(self): - self.name = "" - self.type = None - self.subtype = None - self.offset = None - self.size = None - self.encrypted = False - - @classmethod - def from_csv(cls, line): - """ Parse a line from the CSV """ - line_w_defaults = line + ",,,," # lazy way to support default fields - fields = [f.strip() for f in line_w_defaults.split(",")] - - res = PartitionDefinition() - res.name = fields[0] - res.type = res.parse_type(fields[1]) - res.subtype = res.parse_subtype(fields[2]) - res.offset = res.parse_address(fields[3]) - res.size = res.parse_address(fields[4]) - if res.size is None: - raise InputError("Size field can't be empty") - - flags = fields[5].split(":") - for flag in flags: - if flag in cls.FLAGS: - setattr(res, flag, True) - elif len(flag) > 0: - raise InputError("CSV flag column contains unknown flag '%s'" % (flag)) - - return res - - def __eq__(self, other): - return self.name == other.name and self.type == other.type \ - and self.subtype == other.subtype and self.offset == other.offset \ - and self.size == other.size - - def __repr__(self): - def maybe_hex(x): - return "0x%x" % x if x is not None else "None" - return "PartitionDefinition('%s', 0x%x, 0x%x, %s, %s)" % (self.name, self.type, - self.subtype or 0, - maybe_hex(self.offset), - maybe_hex(self.size)) - - def __str__(self): - return "Part '%s' %d/%d @ 0x%x size 0x%x" % (self.name, self.type, - self.subtype, self.offset or -1, - self.size or -1) - - def __cmp__(self, other): - return self.offset - other.offset - - def parse_type(self, strval): - if strval == "": - raise InputError("Field 'type' can't be left empty.") - return parse_int(strval, self.TYPES) - - def parse_subtype(self, strval): - if strval == "": - return 0 # default - return parse_int(strval, self.SUBTYPES.get(self.type, {})) - - @classmethod - def parse_address(cls, strval): - if strval == "": - return None # PartitionTable will fill in default - return parse_int(strval, {}) - - def verify(self): - if self.type is None: - raise ValidationError(self, "Type field is not set") - if self.subtype is None: - raise ValidationError(self, "Subtype field is not set") - if self.offset is None: - raise ValidationError(self, "Offset field is not set") - align = self.ALIGNMENT.get(self.type, 4) - if self.offset % align: - raise ValidationError(self, "Offset 0x%x is not aligned to 0x%x" % (self.offset, align)) - if self.size is None: - raise ValidationError(self, "Size field is not set") - - STRUCT_FORMAT = "<2sBBLL16sL" - - @classmethod - def from_binary(cls, b): - if len(b) != 32: - raise InputError("Partition definition length must be exactly 32 bytes. Got %d bytes." % len(b)) - res = cls() - (magic, res.type, res.subtype, res.offset, - res.size, res.name, flags) = struct.unpack(cls.STRUCT_FORMAT, b) - if b"\x00" in res.name: # strip null byte padding from name string - res.name = res.name[:res.name.index(b"\x00")] - res.name = res.name.decode() - if magic != cls.MAGIC_BYTES: - raise InputError("Invalid magic bytes (%r) for partition definition" % magic) - for flag, bit in cls.FLAGS.items(): - if flags & (1 << bit): - setattr(res, flag, True) - flags &= ~(1 << bit) - if flags != 0: - critical("WARNING: Partition definition had unknown flag(s) 0x%08x. Newer binary format?" % flags) - return res - - def get_flags_list(self): - return [flag for flag in self.FLAGS.keys() if getattr(self, flag)] - - def to_binary(self): - flags = sum((1 << self.FLAGS[flag]) for flag in self.get_flags_list()) - return struct.pack(self.STRUCT_FORMAT, - self.MAGIC_BYTES, - self.type, self.subtype, - self.offset, self.size, - self.name.encode(), - flags) - - def to_csv(self, simple_formatting=False): - def addr_format(a, include_sizes): - if not simple_formatting and include_sizes: - for (val, suffix) in [(0x100000, "M"), (0x400, "K")]: - if a % val == 0: - return "%d%s" % (a // val, suffix) - return "0x%x" % a - - def lookup_keyword(t, keywords): - for k, v in keywords.items(): - if simple_formatting is False and t == v: - return k - return "%d" % t - - def generate_text_flags(): - """ colon-delimited list of flags """ - return ":".join(self.get_flags_list()) - - return ",".join([self.name, - lookup_keyword(self.type, self.TYPES), - lookup_keyword(self.subtype, self.SUBTYPES.get(self.type, {})), - addr_format(self.offset, False), - addr_format(self.size, True), - generate_text_flags()]) - - -def parse_int(v, keywords): - """Generic parser for integer fields - int(x,0) with provision for - k/m/K/M suffixes and 'keyword' value lookup. - """ - try: - for letter, multiplier in [("k", 1024), ("m", 1024*1024)]: - if v.lower().endswith(letter): - return parse_int(v[:-1], keywords) * multiplier - return int(v, 0) - except ValueError: - if len(keywords) == 0: - raise InputError("Invalid field value %s" % v) - try: - return keywords[v.lower()] - except KeyError: - raise InputError("Value '%s' is not valid. Known keywords: %s" % (v, ", ".join(keywords))) - - -def main(): - global quiet - global sha256sum - parser = argparse.ArgumentParser(description='ESP32 partition table utility') - - parser.add_argument('--flash-size', - help='Optional flash size limit, checks partition table fits in flash', - nargs='?', choices=['1MB', '2MB', '4MB', '8MB', '16MB']) - parser.add_argument('--disable-sha256sum', help='Disable sha256 checksum for the partition table', - default=False, action='store_true') - parser.add_argument('--verify', '-v', help='Verify partition table fields', - default=True, action='store_false') - parser.add_argument('--quiet', '-q', help="Don't print status messages to stderr", - action='store_true') - - parser.add_argument('input', - help='Path to CSV or binary file to parse. Will use stdin if omitted.', - type=argparse.FileType('rb'), default=sys.stdin) - parser.add_argument('output', help='Path to output converted binary or CSV file. Will use ' - 'stdout if omitted, unless the --display argument is also passed (in ' - 'which case only the summary is printed.)', - nargs='?', - default='-') - - args = parser.parse_args() - - quiet = args.quiet - sha256sum = not args.disable_sha256sum - input_arg = args.input.read() - input_is_binary = input_arg[0:2] == PartitionDefinition.MAGIC_BYTES - if input_is_binary: - status("Parsing binary partition input...") - table = PartitionTable.from_binary(input_arg) - else: - input_arg = input_arg.decode() - status("Parsing CSV input...") - table = PartitionTable.from_csv(input_arg) - - if args.verify: - status("Verifying table...") - table.verify() - - if args.flash_size: - size_mb = int(args.flash_size.replace("MB", "")) - size = size_mb * 1024 * 1024 # flash memory uses honest megabytes! - table_size = table.flash_size() - if size < table_size: - raise InputError("Partitions defined in '%s' occupy %.1fMB of flash (%d bytes) which " - "does not fit in configured flash size %dMB. Change the flash size " - "in menuconfig under the 'Serial Flasher Config' menu." % - (args.input.name, table_size / 1024.0 / 1024.0, table_size, size_mb)) - - if input_is_binary: - output = table.to_csv() - with sys.stdout if args.output == '-' else open(args.output, 'w') as f: - f.write(output) - else: - output = table.to_binary() - with sys.stdout.buffer if args.output == '-' else open(args.output, 'wb') as f: - f.write(output) - - -class InputError(RuntimeError): - def __init__(self, e): - super(InputError, self).__init__(e) - - -class ValidationError(InputError): - def __init__(self, partition, message): - super(ValidationError, self).__init__( - "Partition %s invalid: %s" % (partition.name, message)) - - -if __name__ == '__main__': - try: - main() - except InputError as e: - print(e, file=sys.stderr) - sys.exit(2) diff --git a/cpu/esp32/include/cpu.h b/cpu/esp32/include/cpu.h deleted file mode 100644 index d28fb890cf15..000000000000 --- a/cpu/esp32/include/cpu.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @{ - * - * @file - * @brief CPU common functions - * - * @author Gunar Schorcht - */ - -#ifndef CPU_H -#define CPU_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "irq.h" - -#define PROVIDES_PM_SET_LOWEST - -/** - * @brief Print the last instruction's address - * - * @todo: Not supported - */ -static inline void cpu_print_last_instruction(void) -{ - /* This function must exist else RIOT won't compile */ -} - -#ifdef __cplusplus -} -#endif - -#endif /* CPU_H */ -/** @} */ diff --git a/cpu/esp32/include/esp_common.h b/cpu/esp32/include/esp_common.h deleted file mode 100644 index de060b8e9f0e..000000000000 --- a/cpu/esp32/include/esp_common.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @{ - * - * @file - * @brief Common helper macros - * - * @author Gunar Schorcht - * - */ - -#ifndef ESP_COMMON_H -#define ESP_COMMON_H - -#ifndef DOXYGEN - -#ifdef __cplusplus -extern "C" { -#endif - -#include "log.h" -#include "esp_common_log.h" - -#define asm __asm__ - -/** string representation of x */ -#ifndef XTSTR -#define _XTSTR(x) # x -#define XTSTR(x) _XTSTR(x) -#endif /* XSTR */ - -#if !defined(ICACHE_FLASH) -#ifndef ICACHE_RAM_ATTR -/** Places the code with this attribute in the IRAM. */ -#define ICACHE_RAM_ATTR __attribute__((section(".iram0.text"))) -#endif -#else /* ICACHE_FLASH */ -#ifndef ICACHE_RAM_ATTR -#define ICACHE_RAM_ATTR -#endif -#endif /* ICACHE_FLASH */ - -/** Print out a message that function is not yet implementd */ -#define NOT_YET_IMPLEMENTED() LOG_INFO("%s not yet implemented\n", __func__) -/** Print out a message that function is not supported */ -#define NOT_SUPPORTED() LOG_INFO("%s not supported\n", __func__) - -#if ENABLE_DEBUG -/** - * @brief Parameter check with return a value. - * - * If ENABLE_DEBUG is true, the macro checks a condition and returns with a value - * if the condition is not fulfilled. - * @param cond the condition - * @param err the return value in the case the condition is not fulfilled. - */ -#define CHECK_PARAM_RET(cond,err) if (!(cond)) \ - { \ - DEBUG("%s parameter condition (" #cond ") " \ - "not fulfilled\n", __func__); \ - return err; \ - } - -/** - * @brief Parameter check without return value. - * - * If ENABLE_DEBUG is true, the macro checks a condition and returns without a - * value if the condition is not fulfilled. - * @param cond the condition - */ -#define CHECK_PARAM(cond) if (!(cond)) \ - { \ - DEBUG("%s parameter condition (" #cond ") " \ - "not fulfilled\n", __func__); \ - return; \ - } - -#else /* ENABLE_DEBUG */ - -#define CHECK_PARAM_RET(cond,err) if (!(cond)) return err; -#define CHECK_PARAM(cond) if (!(cond)) return; - -#endif /* ENABLE_DEBUG */ - -/** gives the minimum of a and b */ -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -/** gives the maximum of a and b */ -#ifndef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#endif - -/** - * @brief function name mappings for source code compatibility with ESP8266 port - * @{ - */ -#define system_get_cpu_freq ets_get_cpu_frequency -#define system_update_cpu_freq ets_update_cpu_frequency -/** @} */ - -/** @} */ - -/** microseconds per millisecond */ -#ifndef USEC_PER_MSEC -#define USEC_PER_MSEC 1000UL -#endif - -#ifndef MSEC_PER_SEC -#define MSEC_PER_SEC 1000UL -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* DOXYGEN */ - -#endif /* ESP_COMMON_H */ diff --git a/cpu/esp32/include/esp_common_log.h b/cpu/esp32/include/esp_common_log.h deleted file mode 100644 index 2fa770f8ccac..000000000000 --- a/cpu/esp32/include/esp_common_log.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @{ - * - * @file - * @brief Common log macros - * - * @author Gunar Schorcht - * - */ - -#ifndef ESP_COMMON_LOG_H -#define ESP_COMMON_LOG_H - -#ifndef DOXYGEN - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#include "log.h" - -extern uint32_t system_get_time_ms (void); -extern int ets_printf(const char *fmt, ...); - -#if MODULE_ESP_LOG_COLORED - -#define LOG_RESET_COLOR "\033[0m" -#define LOG_COLOR_E "\033[1;31m" -#define LOG_COLOR_W "\033[1;33m" -#define LOG_COLOR_I "\033[1m" -#define LOG_COLOR_D "\033[0;32m" -#define LOG_COLOR_V - -#else /* MODULE_ESP_LOG_COLORED */ - -#define LOG_COLOR_E -#define LOG_COLOR_W -#define LOG_COLOR_I -#define LOG_COLOR_D -#define LOG_COLOR_V -#define LOG_RESET_COLOR - -#endif /* MODULE_ESP_LOG_COLORED */ - -#if MODULE_ESP_LOG_TAGGED - -#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%d) [%s] " format LOG_RESET_COLOR - -#define LOG_TAG(level, letter, tag, format, ...) \ - do { \ - if ((unsigned)level <= (unsigned)LOG_LEVEL) { \ - printf(LOG_FORMAT(letter, format), system_get_time_ms(), tag, ##__VA_ARGS__); \ - fflush(stdout); \ - } \ - } while(0) - -#define LOG_TAG_EARLY(level, letter, tag, format, ...) \ - do { \ - if (LOG_LEVEL >= level) { \ - ets_printf(LOG_FORMAT(letter, format), system_get_time_ms(), tag, ##__VA_ARGS__); \ - } \ - } while(0) - -#else /* MODULE_ESP_LOG_TAGGED */ - -#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter format LOG_RESET_COLOR - -#define LOG_TAG(level, letter, tag, format, ...) \ - do { \ - (void)tag; \ - if ((unsigned)level <= (unsigned)LOG_LEVEL) { \ - printf(LOG_FORMAT(letter, format), ##__VA_ARGS__); \ - fflush(stdout); \ - } \ - } while (0U) - -#define LOG_TAG_EARLY(level, letter, tag, format, ...) \ - do { \ - (void)tag; \ - if ((unsigned)level <= (unsigned)LOG_LEVEL) { \ - ets_printf(LOG_FORMAT(letter, format), ##__VA_ARGS__); \ - } \ - } while (0U) - -#endif /* MODULE_ESP_LOG_TAGGED */ - -/** - * Override LOG_* definitions with a tagged version. By default the function - * name is used as tag. - */ -#ifndef MODULE_LOG_PRINTFNOFORMAT -#undef LOG_ERROR -#undef LOG_INFO -#undef LOG_WARNING -#undef LOG_DEBUG -#define LOG_ERROR(format, ...) LOG_TAG(LOG_ERROR , E, __func__, format, ##__VA_ARGS__) -#define LOG_WARNING(format, ...) LOG_TAG(LOG_WARNING, W, __func__, format, ##__VA_ARGS__) -#define LOG_INFO(format, ...) LOG_TAG(LOG_INFO , I, __func__, format, ##__VA_ARGS__) -#define LOG_DEBUG(format, ...) LOG_TAG(LOG_DEBUG , D, __func__, format, ##__VA_ARGS__) -#endif - -/** Tagged LOG_* definitions */ -#define LOG_TAG_ERROR(tag, format, ...) LOG_TAG(LOG_ERROR , E, tag, format, ##__VA_ARGS__) -#define LOG_TAG_WARNING(tag, format, ...) LOG_TAG(LOG_WARNING, W, tag, format, ##__VA_ARGS__) -#define LOG_TAG_INFO(tag, format, ...) LOG_TAG(LOG_INFO , I, tag, format, ##__VA_ARGS__) -#define LOG_TAG_DEBUG(tag, format, ...) LOG_TAG(LOG_DEBUG , D, tag, format, ##__VA_ARGS__) -#define LOG_TAG_ALL(tag, format, ...) LOG_TAG(LOG_ALL , V, tag, format, ##__VA_ARGS__) - -/** definitions for source code compatibility with ESP-IDF */ -#define ESP_EARLY_LOGE(tag, format, ...) LOG_TAG_EARLY(LOG_ERROR , E, tag, format "\n", ##__VA_ARGS__) -#define ESP_EARLY_LOGW(tag, format, ...) LOG_TAG_EARLY(LOG_WARNING, W, tag, format "\n", ##__VA_ARGS__) -#define ESP_EARLY_LOGI(tag, format, ...) LOG_TAG_EARLY(LOG_INFO , I, tag, format "\n", ##__VA_ARGS__) -#define ESP_LOGE(tag, format, ...) LOG_TAG(LOG_ERROR , E, tag, format "\n", ##__VA_ARGS__) -#define ESP_LOGW(tag, format, ...) LOG_TAG(LOG_WARNING, W, tag, format "\n", ##__VA_ARGS__) -#define ESP_LOGI(tag, format, ...) LOG_TAG(LOG_INFO , I, tag, format "\n", ##__VA_ARGS__) - -#if ENABLE_DEBUG - -#define ESP_EARLY_LOGD(tag, format, ...) LOG_TAG_EARLY(LOG_DEBUG, D, tag, format "\n", ##__VA_ARGS__) -#define ESP_EARLY_LOGV(tag, format, ...) LOG_TAG_EARLY(LOG_ALL , V, tag, format "\n", ##__VA_ARGS__) -#define ESP_LOGD(tag, format, ...) LOG_TAG(LOG_DEBUG, D, tag, format "\n", ##__VA_ARGS__) -#define ESP_LOGV(tag, format, ...) LOG_TAG(LOG_ALL , V, tag, format "\n", ##__VA_ARGS__) - -#else /* ENABLE_DEBUG */ - -#define ESP_EARLY_LOGD( tag, format, ... ) (void)tag -#define ESP_EARLY_LOGV( tag, format, ... ) (void)tag -#define ESP_LOGD( tag, format, ... ) (void)tag -#define ESP_LOGV( tag, format, ... ) (void)tag - -#endif /* ENABLE_DEBUG */ - -#ifdef __cplusplus -} -#endif - -#endif /* DOXYGEN */ - -#endif /* ESP_COMMON_LOG_H */ diff --git a/cpu/esp32/include/exceptions.h b/cpu/esp32/include/exceptions.h deleted file mode 100644 index 87229b3132b0..000000000000 --- a/cpu/esp32/include/exceptions.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @{ - * - * @file - * @brief ESP32 exception handling - * - * @author Gunar Schorcht - * @} - */ - -#ifndef EXCEPTIONS_H -#define EXCEPTIONS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** Initialize exception handler */ -extern void init_exceptions(void); - -#ifdef __cplusplus -} -#endif - -#endif /* EXCEPTIONS_H */ diff --git a/cpu/esp32/include/freertos/FreeRTOS.h b/cpu/esp32/include/freertos/FreeRTOS.h deleted file mode 100644 index 95c34b03df2f..000000000000 --- a/cpu/esp32/include/freertos/FreeRTOS.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * FreeRTOS to RIOT-OS adaption module for source code compatibility - */ - -#ifndef FREERTOS_FREERTOS_H -#define FREERTOS_FREERTOS_H - -#ifndef DOXYGEN - -#include "freertos/portmacro.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define configMAX_PRIORITIES SCHED_PRIO_LEVELS - -#ifndef configASSERT -#define configASSERT assert -#endif - -#define portTICK_PERIOD_MS 10 -#define portTickType TickType_t - -typedef int32_t BaseType_t; -typedef uint32_t UBaseType_t; -typedef uint32_t TickType_t; - -uint32_t xPortGetTickRateHz(void); -BaseType_t xPortInIsrContext(void); - -/* - * PLESE NOTE: Following definitions were copied directly from the FreeRTOS - * distribution and are under the following copyright: - * - * FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. - * All rights reserved - * - * FreeRTOS is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License (version 2) as published by the - * Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. - * - * Full license text is available on the following - * link: http://www.freertos.org/a00114.html - */ - -#define pdFALSE ( ( BaseType_t ) 0 ) -#define pdTRUE ( ( BaseType_t ) 1 ) -#define pdPASS ( pdTRUE ) -#define pdFAIL ( pdFALSE ) - -#ifdef __cplusplus -} -#endif - -#include "freertos/semphr.h" -#include "freertos/queue.h" - -#endif /* DOXYGEN */ -#endif /* FREERTOS_FREERTOS_H */ diff --git a/cpu/esp32/include/freertos/event_groups.h b/cpu/esp32/include/freertos/event_groups.h deleted file mode 100644 index 12405cf57437..000000000000 --- a/cpu/esp32/include/freertos/event_groups.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * FreeRTOS to RIOT-OS adaption module for source code compatibility - */ - -#ifndef FREERTOS_EVENT_GROUPS_H -#define FREERTOS_EVENT_GROUPS_H - -#ifndef DOXYGEN - -#include "freertos/FreeRTOS.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void * EventGroupHandle_t; -typedef TickType_t EventBits_t; - -EventGroupHandle_t xEventGroupCreate (void); - -void vEventGroupDelete (EventGroupHandle_t xEventGroup); - -EventBits_t xEventGroupSetBits (EventGroupHandle_t xEventGroup, - const EventBits_t uxBitsToSet); - -EventBits_t xEventGroupClearBits (EventGroupHandle_t xEventGroup, - const EventBits_t uxBitsToClear ); - -EventBits_t xEventGroupWaitBits (const EventGroupHandle_t xEventGroup, - const EventBits_t uxBitsToWaitFor, - const BaseType_t xClearOnExit, - const BaseType_t xWaitForAllBits, - TickType_t xTicksToWait); - -#ifdef __cplusplus -} -#endif - -#endif /* DOXYGEN */ -#endif /* FREERTOS_EVENT_GROUPS_H */ diff --git a/cpu/esp32/include/freertos/portmacro.h b/cpu/esp32/include/freertos/portmacro.h deleted file mode 100644 index f4f6f4b70d82..000000000000 --- a/cpu/esp32/include/freertos/portmacro.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * FreeRTOS to RIOT-OS adaption module for source code compatibility - */ - -#ifndef FREERTOS_PORTMACRO_H -#define FREERTOS_PORTMACRO_H - -#ifndef DOXYGEN - -#include "stdint.h" - -#include "mutex.h" -#include "irq.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define portBASE_TYPE int32_t -#define portUBASE_TYPE uint32_t - -#define portMAX_DELAY 0xFFFFFFFF - -#define portMUX_TYPE mutex_t -#define portMUX_INITIALIZER_UNLOCKED MUTEX_INIT - -#define portENTER_CRITICAL(mux) vTaskEnterCritical(mux) -#define portEXIT_CRITICAL(mux) vTaskExitCritical(mux) -#define portENTER_CRITICAL_NESTED irq_disable -#define portEXIT_CRITICAL_NESTED irq_restore - -#define portENTER_CRITICAL_ISR(mux) vTaskEnterCritical(mux) -#define portEXIT_CRITICAL_ISR(mux) vTaskExitCritical(mux) - -#define taskENTER_CRITICAL(mux) portENTER_CRITICAL(mux) -#define taskENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux) -#define taskEXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) -#define taskEXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux) - -#define portYIELD_FROM_ISR thread_yield_higher -#define portNUM_PROCESSORS 2 - -#define xPortGetCoreID() PRO_CPU_NUM - -extern void vTaskEnterCritical(portMUX_TYPE *mux); -extern void vTaskExitCritical(portMUX_TYPE *mux); - -#ifdef __cplusplus -} -#endif - -#endif /* DOXYGEN */ -#endif /* FREERTOS_PORTMACRO_H */ diff --git a/cpu/esp32/include/freertos/queue.h b/cpu/esp32/include/freertos/queue.h deleted file mode 100644 index 3649e2bd4f77..000000000000 --- a/cpu/esp32/include/freertos/queue.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * FreeRTOS to RIOT-OS adaption module for source code compatibility - */ - -#ifndef FREERTOS_QUEUE_H -#define FREERTOS_QUEUE_H - -#ifndef DOXYGEN - -#include "freertos/FreeRTOS.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define xQueueHandle QueueHandle_t - -typedef void* QueueHandle_t; - -QueueHandle_t xQueueGenericCreate (const UBaseType_t uxQueueLength, - const UBaseType_t uxItemSize, - const uint8_t ucQueueType); - -QueueHandle_t xQueueCreateCountingSemaphore (const UBaseType_t uxMaxCount, - const UBaseType_t uxInitialCount); - -void vQueueDelete (QueueHandle_t xQueue); - -BaseType_t xQueueGenericReset (QueueHandle_t xQueue, BaseType_t xNewQueue); - -BaseType_t xQueueGenericReceive (QueueHandle_t xQueue, - void * const pvBuffer, - TickType_t xTicksToWait, - const BaseType_t xJustPeeking); - -BaseType_t xQueueGenericSend (QueueHandle_t xQueue, - const void * const pvItemToQueue, - TickType_t xTicksToWait, - const BaseType_t xCopyPosition); - -BaseType_t xQueueReceiveFromISR (QueueHandle_t xQueue, void * const pvBuffer, - BaseType_t * const pxHigherPriorityTaskWoken); - -BaseType_t xQueueGenericSendFromISR (QueueHandle_t xQueue, - const void * const pvItemToQueue, - BaseType_t * const pxHigherPriorityTaskWoken, - const BaseType_t xCopyPosition ); - -BaseType_t xQueueGiveFromISR (QueueHandle_t xQueue, - BaseType_t * const pxHigherPriorityTaskWoken); - -UBaseType_t uxQueueMessagesWaiting( QueueHandle_t xQueue ); - -/* - * PLESE NOTE: Following definitions were copied directly from the FreeRTOS - * distribution and are under the following copyright: - * - * FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. - * All rights reserved - * - * FreeRTOS is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License (version 2) as published by the - * Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. - * - * Full license text is available on the following - * link: http://www.freertos.org/a00114.html - */ - -#define queueSEND_TO_BACK ( ( BaseType_t ) 0 ) -#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 ) -#define queueOVERWRITE ( ( BaseType_t ) 2 ) - -#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U ) -#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U ) -#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U ) -#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U ) -#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U ) -#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U ) - -#define errQUEUE_EMPTY ( ( BaseType_t ) 0 ) -#define errQUEUE_FULL ( ( BaseType_t ) 0 ) -#define errQUEUE_BLOCKED ( -4 ) -#define errQUEUE_YIELD ( -5 ) - -#define xQueueCreate( uxQueueLength, uxItemSize ) \ - xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) ) - -#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) \ - xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), \ - pdFALSE ) - -#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) \ - xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), \ - queueSEND_TO_BACK ) - -#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) \ - xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), \ - queueSEND_TO_BACK ) - -#define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \ - xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), \ - ( pxHigherPriorityTaskWoken ), \ - queueSEND_TO_BACK ) - -#define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE ) - -#ifdef __cplusplus -} -#endif - -#endif /* DOXYGEN */ -#endif /* FREERTOS_QUEUE_H */ diff --git a/cpu/esp32/include/freertos/semphr.h b/cpu/esp32/include/freertos/semphr.h deleted file mode 100644 index c1cdec23e056..000000000000 --- a/cpu/esp32/include/freertos/semphr.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * FreeRTOS to RIOT-OS adaption module for source code compatibility - */ - -#ifndef FREERTOS_SEMPHR_H -#define FREERTOS_SEMPHR_H - -#ifndef DOXYGEN - -#include "freertos/FreeRTOS.h" - -#include -#include "mutex.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void* SemaphoreHandle_t; - -SemaphoreHandle_t xSemaphoreCreateMutex(void); -SemaphoreHandle_t xSemaphoreCreateRecursiveMutex(void); - -void vSemaphoreDelete (SemaphoreHandle_t xSemaphore); - -BaseType_t xSemaphoreGive (SemaphoreHandle_t xSemaphore); -BaseType_t xSemaphoreTake (SemaphoreHandle_t xSemaphore, - TickType_t xTicksToWait); -BaseType_t xSemaphoreGiveRecursive (SemaphoreHandle_t xSemaphore); -BaseType_t xSemaphoreTakeRecursive (SemaphoreHandle_t xSemaphore, - TickType_t xTicksToWait); - -#define vPortCPUInitializeMutex(m) mutex_init(m) - -void vPortCPUAcquireMutex (portMUX_TYPE *mux); -void vPortCPUReleaseMutex (portMUX_TYPE *mux); - -/* - * PLESE NOTE: Following definitions were copied directly from the FreeRTOS - * distribution and are under the following copyright: - * - * FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. - * All rights reserved - * - * FreeRTOS is free software; you can redistribute it and/or modify it under - * the terms of the GNU General Public License (version 2) as published by the - * Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. - * - * Full license text is available on the following - * link: http://www.freertos.org/a00114.html - */ - -#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U ) - -#define xSemaphoreCreateBinary() \ - xQueueGenericCreate( ( UBaseType_t ) 1, \ - semSEMAPHORE_QUEUE_ITEM_LENGTH, \ - queueQUEUE_TYPE_BINARY_SEMAPHORE ) -#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) \ - xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) - -#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) \ - xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), \ - NULL, ( pxHigherPriorityTaskWoken ) ) - -#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) \ - xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), \ - ( pxHigherPriorityTaskWoken ) ) - -#ifdef __cplusplus -} -#endif - -#endif /* DOXYGEN */ -#endif /* FREERTOS_SEMPHR_H */ diff --git a/cpu/esp32/include/freertos/task.h b/cpu/esp32/include/freertos/task.h deleted file mode 100644 index fc416ee6a080..000000000000 --- a/cpu/esp32/include/freertos/task.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * FreeRTOS to RIOT-OS adaption module for source code compatibility - */ - -#ifndef FREERTOS_TASK_H -#define FREERTOS_TASK_H - -#ifndef DOXYGEN - -#include "thread.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define xTaskHandle TaskHandle_t -#define tskNO_AFFINITY INT_MAX - -typedef void (*TaskFunction_t)(void *); - -typedef void* TaskHandle_t; - -BaseType_t xTaskCreate (TaskFunction_t pvTaskCode, - const char * const pcName, - const uint32_t usStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - TaskHandle_t * const pvCreatedTask); - -BaseType_t xTaskCreatePinnedToCore (TaskFunction_t pvTaskCode, - const char * const pcName, - const uint32_t usStackDepth, - void * const pvParameters, - UBaseType_t uxPriority, - TaskHandle_t * const pvCreatedTask, - const BaseType_t xCoreID); - -void vTaskDelete (TaskHandle_t xTaskToDelete); -void vTaskDelay (const TickType_t xTicksToDelay); - -TaskHandle_t xTaskGetCurrentTaskHandle (void); - -void vTaskEnterCritical (portMUX_TYPE *mux); -void vTaskExitCritical (portMUX_TYPE *mux); - -TickType_t xTaskGetTickCount (void); - -#ifdef __cplusplus -} -#endif - -#endif /* DOXYGEN */ -#endif /* FREERTOS_TASK_H */ diff --git a/cpu/esp32/include/freertos/timers.h b/cpu/esp32/include/freertos/timers.h deleted file mode 100644 index 388bde399260..000000000000 --- a/cpu/esp32/include/freertos/timers.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * FreeRTOS to RIOT-OS adaption module for source code compatibility - */ - -#ifndef FREERTOS_TIMERS_H -#define FREERTOS_TIMERS_H - -#ifndef DOXYGEN - -#include "freertos/FreeRTOS.h" -#include "xtimer.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void* TimerHandle_t; - -#define TimerCallbackFunction_t xtimer_callback_t - -TimerHandle_t xTimerCreate (const char * const pcTimerName, - const TickType_t xTimerPeriod, - const UBaseType_t uxAutoReload, - void * const pvTimerID, - TimerCallbackFunction_t pxCallbackFunction); -BaseType_t xTimerDelete(TimerHandle_t xTimer, TickType_t xBlockTime); -BaseType_t xTimerStart (TimerHandle_t xTimer, TickType_t xBlockTime); -BaseType_t xTimerStop (TimerHandle_t xTimer, TickType_t xBlockTime); - -#ifdef __cplusplus -} -#endif - -#endif /* DOXYGEN */ -#endif /* FREERTOS_TIMERS_H */ diff --git a/cpu/esp32/include/freertos/xtensa_api.h b/cpu/esp32/include/freertos/xtensa_api.h deleted file mode 100644 index 70db1b55bca7..000000000000 --- a/cpu/esp32/include/freertos/xtensa_api.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - * - * FreeRTOS to RIOT-OS adaption module for source code compatibility - */ - -#ifndef FREERTOS_XTENSA_API_H -#define FREERTOS_XTENSA_API_H - -#include "xtensa/xtensa_api.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* FREERTOS_XTENSA_API_H */ diff --git a/cpu/esp32/include/gpio_arch.h b/cpu/esp32/include/gpio_arch.h index 97df88136136..a773e86caaaf 100644 --- a/cpu/esp32/include/gpio_arch.h +++ b/cpu/esp32/include/gpio_arch.h @@ -20,6 +20,7 @@ #ifndef GPIO_ARCH_H #define GPIO_ARCH_H +#include "gpio_arch_common.h" #include "periph/gpio.h" #include "soc/io_mux_reg.h" #include "soc/gpio_sig_map.h" @@ -30,61 +31,12 @@ extern "C" { #endif -/** - * @brief Definitions for source code compatibility with ESP-IDF - */ -#define GPIO_MODE_INPUT GPIO_IN -#define GPIO_MODE_OUTPUT GPIO_OUT -#define GPIO_MODE_INPUT_OUTPUT GPIO_IN_OUT -/** - * @brief Definition of possible GPIO usage types (for internal use only) - */ -typedef enum -{ - _GPIO = 0, /**< pin used as standard GPIO */ - _ADC, /**< pin used as ADC input */ - _CAN, /**< pin used as CAN signal */ - _DAC, /**< pin used as DAC output */ - _EMAC, /**< pin used as EMAC signal */ - _I2C, /**< pin used as I2C signal */ - _PWM, /**< pin used as PWM output */ - _SPI, /**< pin used as SPI interface */ - _SPIF, /**< pin used as SPI flash interface */ - _UART, /**< pin used as UART interface */ - _NOT_EXIST /**< pin cannot be used at all */ -} gpio_pin_usage_t; - /** * @brief Table of GPIO to IOMUX register mappings */ extern const uint32_t _gpio_to_iomux_reg[]; #define GPIO_PIN_MUX_REG _gpio_to_iomux_reg -/** - * @brief Set the usage type of the pin - * @param pin GPIO pin - * @param usage GPIO pin usage type - * @return 0 on success - * -1 on error - */ -int gpio_set_pin_usage(gpio_t pin, gpio_pin_usage_t usage); - -/** - * @brief Get the usage type of the pin - * @param pin GPIO pin - * @return GPIO pin usage type on success - * _NOT_EXIST on error - */ -gpio_pin_usage_t gpio_get_pin_usage(gpio_t pin); - -/** - * @brief Get the usage type of the pin as string - * @param pin GPIO pin - * @return GPIO pin usage type string on success - * _NOT_EXIST on error - */ -const char* gpio_get_pin_usage_str(gpio_t pin); - /** * @brief Disable the pullup of the pin */ diff --git a/cpu/esp32/include/irq_arch.h b/cpu/esp32/include/irq_arch.h index 20d8caca24a8..ccf014c76e4d 100644 --- a/cpu/esp32/include/irq_arch.h +++ b/cpu/esp32/include/irq_arch.h @@ -21,21 +21,12 @@ #ifndef IRQ_ARCH_H #define IRQ_ARCH_H -#include "irq.h" -#include "sched.h" -#include "thread.h" +#include "irq_arch_common.h" #ifdef __cplusplus extern "C" { #endif -/** - * @brief Indicates the interrupt nesting depth - * - * The variable is increment on entry into and decremented on exit from an ISR. - */ -extern volatile uint32_t irq_interrupt_nesting; - /** * @name CPU interrupt numbers * @@ -56,37 +47,6 @@ extern volatile uint32_t irq_interrupt_nesting; #define CPU_INUM_TIMER 19 /**< Level interrupt with medium priority 2 */ /** @} */ -/** - * @name Macros to enter and exit an ISR - * - * Since all the stuff is done in `_frxt_int_enter` and `_frxt_int_exit`, these - * macros are doing nothing and are kept only for source code compatibility. - * - * @{ - */ -#define irq_isr_enter() -#define irq_isr_exit() -/** @} */ - -/** - * @name Macros to enter and exit a critical region - * - * @note: since they use a local variable they can be used only in same function - * - * @{ - */ -#define critical_enter() int _irq_state = irq_disable() -#define critical_exit() irq_restore(_irq_state) -/** @} */ - -/** - * @name Macros to enter and exit a critical region with state variable - * @{ - */ -#define critical_enter_var(m) m = irq_disable() -#define critical_exit_var(m) irq_restore(m) -/** @} */ - #ifdef __cplusplus } #endif diff --git a/cpu/esp32/include/log_module.h b/cpu/esp32/include/log_module.h deleted file mode 100644 index 7f5bf2e08349..000000000000 --- a/cpu/esp32/include/log_module.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @{ - * - * @file - * @brief Log module to realize consistent log messages - * - * @author Gunar Schorcht - */ - -#ifndef LOG_MODULE_H -#define LOG_MODULE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "esp_common_log.h" - -#ifdef MODULE_LOG_PRINTFNOFORMAT - -static inline void log_write(unsigned level, const char *format, ...) { - (void)level; - puts(format); -} - -#else /* MODULE_LOG_PRINTFNOFORMAT */ - -#define log_write(level, ...) \ - do { \ - if (level == LOG_ERROR) { \ - LOG_TAG(LOG_ERROR, E, __func__, ##__VA_ARGS__); \ - } \ - else if (level == LOG_WARNING) { \ - LOG_TAG(LOG_WARNING, W, __func__, ##__VA_ARGS__); \ - } \ - else if (level == LOG_INFO) { \ - LOG_TAG(LOG_INFO, D, __func__, ##__VA_ARGS__); \ - } \ - else if (level == LOG_DEBUG) { \ - LOG_TAG(LOG_DEBUG, E, __func__, ##__VA_ARGS__); \ - } \ - } while (0U); - -#endif /* MODULE_LOG_PRINTFNOFORMAT */ - -#ifdef __cplusplus -} -#endif -/**@}*/ -#endif /* LOG_MODULE_H */ diff --git a/cpu/esp32/include/periph_cpu.h b/cpu/esp32/include/periph_cpu.h index f4281ff5e18e..48e764f45723 100644 --- a/cpu/esp32/include/periph_cpu.h +++ b/cpu/esp32/include/periph_cpu.h @@ -382,6 +382,17 @@ typedef struct { /** @} */ +/** + * @name RNG configuration + * @{ + */ + +/** + * @brief The address of the register for accessing the hardware RNG. + */ +#define RNG_DATA_REG_ADDR (0x3ff75144) +/** @} */ + /** * @name SPI configuration * @@ -509,6 +520,10 @@ typedef struct { gpio_t rxd; /**< GPIO used as RxD pin */ } uart_conf_t; +/** + * @brief Maximum number of UART interfaces + */ +#define UART_NUMOF_MAX (3) /** @} */ #ifdef __cplusplus diff --git a/cpu/esp32/include/stdio.h b/cpu/esp32/include/stdio.h deleted file mode 100644 index 4fc9320acf48..000000000000 --- a/cpu/esp32/include/stdio.h +++ /dev/null @@ -1,748 +0,0 @@ -/** - * This file is a modification of the original file to overwrite the *putchar* - * and *getchar* macros in the case the *uart_stdio* module is used. If the - * *uart_stdio* module is used, *putchar* and *getchar* are redirections to - * according *uart_stdio_* functions. - */ - -/* - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * @(#)stdio.h 5.3 (Berkeley) 3/15/86 - */ - -/* - * NB: to fit things in six character monocase externals, the - * stdio code uses the prefix `__s' for stdio objects, typically - * followed by a three-character attempt at a mnemonic. - */ - -#ifndef STDIO_H -#define STDIO_H - -#ifndef DOXYGEN - -#ifdef __cplusplus -extern "C" { -#endif - -#include "_ansi.h" - -#define _FSTDIO /* ``function stdio'' */ - -#define __need_size_t -#define __need_NULL -#include -#include - -#define __need___va_list -#include - -/* - * defines __FILE, _fpos_t. - * They must be defined there because struct _reent needs them (and we don't - * want reent.h to include this file. - */ - -#include -#include - -_BEGIN_STD_C - -typedef __FILE FILE; - -#ifdef __CYGWIN__ -typedef _fpos64_t fpos_t; -#else -typedef _fpos_t fpos_t; -#ifdef __LARGE64_FILES -typedef _fpos64_t fpos64_t; -#endif -#endif /* !__CYGWIN__ */ - -#include - -#define __SLBF 0x0001 /* line buffered */ -#define __SNBF 0x0002 /* unbuffered */ -#define __SRD 0x0004 /* OK to read */ -#define __SWR 0x0008 /* OK to write */ - /* RD and WR are never simultaneously asserted */ -#define __SRW 0x0010 /* open for reading & writing */ -#define __SEOF 0x0020 /* found EOF */ -#define __SERR 0x0040 /* found error */ -#define __SMBF 0x0080 /* _buf is from malloc */ -#define __SAPP 0x0100 /* fdopen()ed in append mode - so must write to end */ -#define __SSTR 0x0200 /* this is an sprintf/snprintf string */ -#define __SOPT 0x0400 /* do fseek() optimisation */ -#define __SNPT 0x0800 /* do not do fseek() optimisation */ -#define __SOFF 0x1000 /* set iff _offset is in fact correct */ -#define __SORD 0x2000 /* true => stream orientation (byte/wide) decided */ -#if defined(__CYGWIN__) -#define __SCLE 0x4000 /* convert line endings CR/LF <-> NL */ -#endif -#define __SL64 0x8000 /* is 64-bit offset large file */ - -/* _flags2 flags */ -#define __SNLK 0x0001 /* stdio functions do not lock streams themselves */ -#define __SWID 0x2000 /* true => stream orientation wide, false => byte, only valid if __SORD in _flags is true */ - -/* - * The following three definitions are for ANSI C, which took them - * from System V, which stupidly took internal interface macros and - * made them official arguments to setvbuf(), without renaming them. - * Hence, these ugly _IOxxx names are *supposed* to appear in user code. - * - * Although these happen to match their counterparts above, the - * implementation does not rely on that (so these could be renumbered). - */ -#define _IOFBF 0 /* setvbuf should set fully buffered */ -#define _IOLBF 1 /* setvbuf should set line buffered */ -#define _IONBF 2 /* setvbuf should set unbuffered */ - -#define EOF (-1) - -#ifdef __BUFSIZ__ -#define BUFSIZ __BUFSIZ__ -#else -#define BUFSIZ 1024 -#endif - -#ifdef __FOPEN_MAX__ -#define FOPEN_MAX __FOPEN_MAX__ -#else -#define FOPEN_MAX 20 -#endif - -#ifdef __FILENAME_MAX__ -#define FILENAME_MAX __FILENAME_MAX__ -#else -#define FILENAME_MAX 1024 -#endif - -#ifdef __L_tmpnam__ -#define L_tmpnam __L_tmpnam__ -#else -#define L_tmpnam FILENAME_MAX -#endif - -#ifndef __STRICT_ANSI__ -#define P_tmpdir "/tmp" -#endif - -#ifndef SEEK_SET -#define SEEK_SET 0 /* set file offset to offset */ -#endif -#ifndef SEEK_CUR -#define SEEK_CUR 1 /* set file offset to current plus offset */ -#endif -#ifndef SEEK_END -#define SEEK_END 2 /* set file offset to EOF plus offset */ -#endif - -#define TMP_MAX 26 - -#define stdin (_REENT->_stdin) -#define stdout (_REENT->_stdout) -#define stderr (_REENT->_stderr) - -#define _stdin_r(x) ((x)->_stdin) -#define _stdout_r(x) ((x)->_stdout) -#define _stderr_r(x) ((x)->_stderr) - -/* - * Functions defined in ANSI C standard. - */ - -#ifndef __VALIST -#ifdef __GNUC__ -#define __VALIST __gnuc_va_list -#else -#define __VALIST char* -#endif -#endif - -FILE * _EXFUN(tmpfile, (void)); -char * _EXFUN(tmpnam, (char *)); -#if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112 -char * _EXFUN(tempnam, (const char *, const char *)); -#endif -int _EXFUN(fclose, (FILE *)); -int _EXFUN(fflush, (FILE *)); -FILE * _EXFUN(freopen, (const char *__restrict, const char *__restrict, FILE *__restrict)); -void _EXFUN(setbuf, (FILE *__restrict, char *__restrict)); -int _EXFUN(setvbuf, (FILE *__restrict, char *__restrict, int, size_t)); -int _EXFUN(fprintf, (FILE *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -int _EXFUN(fscanf, (FILE *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); -int _EXFUN(printf, (const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 1, 2)))); -int _EXFUN(scanf, (const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__scanf__, 1, 2)))); -int _EXFUN(sscanf, (const char *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); -int _EXFUN(vfprintf, (FILE *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(vprintf, (const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 1, 0)))); -int _EXFUN(vsprintf, (char *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(fgetc, (FILE *)); -char * _EXFUN(fgets, (char *__restrict, int, FILE *__restrict)); -int _EXFUN(fputc, (int, FILE *)); -int _EXFUN(fputs, (const char *__restrict, FILE *__restrict)); -int _EXFUN(getc, (FILE *)); -int _EXFUN(getchar, (void)); -char * _EXFUN(gets, (char *)); -int _EXFUN(putc, (int, FILE *)); -int _EXFUN(putchar, (int)); -int _EXFUN(puts, (const char *)); -int _EXFUN(ungetc, (int, FILE *)); -size_t _EXFUN(fread, (_PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); -size_t _EXFUN(fwrite, (const _PTR __restrict , size_t _size, size_t _n, FILE *)); -#ifdef _COMPILING_NEWLIB -int _EXFUN(fgetpos, (FILE *, _fpos_t *)); -#else -int _EXFUN(fgetpos, (FILE *__restrict, fpos_t *__restrict)); -#endif -int _EXFUN(fseek, (FILE *, long, int)); -#ifdef _COMPILING_NEWLIB -int _EXFUN(fsetpos, (FILE *, const _fpos_t *)); -#else -int _EXFUN(fsetpos, (FILE *, const fpos_t *)); -#endif -long _EXFUN(ftell, ( FILE *)); -void _EXFUN(rewind, (FILE *)); -void _EXFUN(clearerr, (FILE *)); -int _EXFUN(feof, (FILE *)); -int _EXFUN(ferror, (FILE *)); -void _EXFUN(perror, (const char *)); -#ifndef _REENT_ONLY -FILE * _EXFUN(fopen, (const char *__restrict _name, const char *__restrict _type)); -int _EXFUN(sprintf, (char *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -int _EXFUN(remove, (const char *)); -int _EXFUN(rename, (const char *, const char *)); -#ifdef _COMPILING_NEWLIB -int _EXFUN(_rename, (const char *, const char *)); -#endif -#endif -#if !defined(__STRICT_ANSI__) || defined(__USE_XOPEN2K) -#ifdef _COMPILING_NEWLIB -int _EXFUN(fseeko, (FILE *, _off_t, int)); -_off_t _EXFUN(ftello, ( FILE *)); -#else -int _EXFUN(fseeko, (FILE *, off_t, int)); -off_t _EXFUN(ftello, ( FILE *)); -#endif -#endif -#if __GNU_VISIBLE -int _EXFUN(fcloseall, (_VOID)); -#endif -#if !defined(__STRICT_ANSI__) || (__STDC_VERSION__ >= 199901L) || (__cplusplus >= 201103L) -#ifndef _REENT_ONLY -int _EXFUN(asiprintf, (char **, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -char * _EXFUN(asniprintf, (char *, size_t *, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -char * _EXFUN(asnprintf, (char *__restrict, size_t *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(asprintf, (char **__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -#ifndef diprintf -int _EXFUN(diprintf, (int, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -#endif -int _EXFUN(fiprintf, (FILE *, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -int _EXFUN(fiscanf, (FILE *, const char *, ...) - _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); -int _EXFUN(iprintf, (const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 1, 2)))); -int _EXFUN(iscanf, (const char *, ...) - _ATTRIBUTE ((__format__ (__scanf__, 1, 2)))); -int _EXFUN(siprintf, (char *, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -int _EXFUN(siscanf, (const char *, const char *, ...) - _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); -int _EXFUN(snprintf, (char *__restrict, size_t, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(sniprintf, (char *, size_t, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(vasiprintf, (char **, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -char * _EXFUN(vasniprintf, (char *, size_t *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -char * _EXFUN(vasnprintf, (char *, size_t *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(vasprintf, (char **, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(vdiprintf, (int, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(vfiprintf, (FILE *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(vfiscanf, (FILE *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); -int _EXFUN(vfscanf, (FILE *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); -int _EXFUN(viprintf, (const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 1, 0)))); -int _EXFUN(viscanf, (const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 1, 0)))); -int _EXFUN(vscanf, (const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 1, 0)))); -int _EXFUN(vsiprintf, (char *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(vsiscanf, (const char *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); -int _EXFUN(vsniprintf, (char *, size_t, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(vsnprintf, (char *__restrict, size_t, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(vsscanf, (const char *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); -#endif /* !_REENT_ONLY */ -#endif /* !__STRICT_ANSI__ */ - -/* - * Routines in POSIX 1003.1:2001. - */ - -#ifndef __STRICT_ANSI__ -#ifndef _REENT_ONLY -FILE * _EXFUN(fdopen, (int, const char *)); -#endif -int _EXFUN(fileno, (FILE *)); -int _EXFUN(getw, (FILE *)); -int _EXFUN(pclose, (FILE *)); -FILE * _EXFUN(popen, (const char *, const char *)); -int _EXFUN(putw, (int, FILE *)); -void _EXFUN(setbuffer, (FILE *, char *, int)); -int _EXFUN(setlinebuf, (FILE *)); -int _EXFUN(getc_unlocked, (FILE *)); -int _EXFUN(getchar_unlocked, (void)); -void _EXFUN(flockfile, (FILE *)); -int _EXFUN(ftrylockfile, (FILE *)); -void _EXFUN(funlockfile, (FILE *)); -int _EXFUN(putc_unlocked, (int, FILE *)); -int _EXFUN(putchar_unlocked, (int)); -#endif /* ! __STRICT_ANSI__ */ - -/* - * Routines in POSIX 1003.1:200x. - */ - -#ifndef __STRICT_ANSI__ -# ifndef _REENT_ONLY -# ifndef dprintf -int _EXFUN(dprintf, (int, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -# endif -FILE * _EXFUN(fmemopen, (void *__restrict, size_t, const char *__restrict)); -/* getdelim - see __getdelim for now */ -/* getline - see __getline for now */ -FILE * _EXFUN(open_memstream, (char **, size_t *)); -#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 -int _EXFUN(renameat, (int, const char *, int, const char *)); -#endif -int _EXFUN(vdprintf, (int, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -# endif -#endif - -/* - * Recursive versions of the above. - */ - -int _EXFUN(_asiprintf_r, (struct _reent *, char **, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -char * _EXFUN(_asniprintf_r, (struct _reent *, char *, size_t *, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 4, 5)))); -char * _EXFUN(_asnprintf_r, (struct _reent *, char *__restrict, size_t *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 4, 5)))); -int _EXFUN(_asprintf_r, (struct _reent *, char **__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(_diprintf_r, (struct _reent *, int, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(_dprintf_r, (struct _reent *, int, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(_fclose_r, (struct _reent *, FILE *)); -int _EXFUN(_fcloseall_r, (struct _reent *)); -FILE * _EXFUN(_fdopen_r, (struct _reent *, int, const char *)); -int _EXFUN(_fflush_r, (struct _reent *, FILE *)); -int _EXFUN(_fgetc_r, (struct _reent *, FILE *)); -int _EXFUN(_fgetc_unlocked_r, (struct _reent *, FILE *)); -char * _EXFUN(_fgets_r, (struct _reent *, char *__restrict, int, FILE *__restrict)); -char * _EXFUN(_fgets_unlocked_r, (struct _reent *, char *__restrict, int, FILE *__restrict)); -#ifdef _COMPILING_NEWLIB -int _EXFUN(_fgetpos_r, (struct _reent *, FILE *__restrict, _fpos_t *__restrict)); -int _EXFUN(_fsetpos_r, (struct _reent *, FILE *, const _fpos_t *)); -#else -int _EXFUN(_fgetpos_r, (struct _reent *, FILE *, fpos_t *)); -int _EXFUN(_fsetpos_r, (struct _reent *, FILE *, const fpos_t *)); -#endif -int _EXFUN(_fiprintf_r, (struct _reent *, FILE *, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(_fiscanf_r, (struct _reent *, FILE *, const char *, ...) - _ATTRIBUTE ((__format__ (__scanf__, 3, 4)))); -FILE * _EXFUN(_fmemopen_r, (struct _reent *, void *__restrict, size_t, const char *__restrict)); -FILE * _EXFUN(_fopen_r, (struct _reent *, const char *__restrict, const char *__restrict)); -FILE * _EXFUN(_freopen_r, (struct _reent *, const char *__restrict, const char *__restrict, FILE *__restrict)); -int _EXFUN(_fprintf_r, (struct _reent *, FILE *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(_fpurge_r, (struct _reent *, FILE *)); -int _EXFUN(_fputc_r, (struct _reent *, int, FILE *)); -int _EXFUN(_fputc_unlocked_r, (struct _reent *, int, FILE *)); -int _EXFUN(_fputs_r, (struct _reent *, const char *__restrict, FILE *__restrict)); -int _EXFUN(_fputs_unlocked_r, (struct _reent *, const char *__restrict, FILE *__restrict)); -size_t _EXFUN(_fread_r, (struct _reent *, _PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); -size_t _EXFUN(_fread_unlocked_r, (struct _reent *, _PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); -int _EXFUN(_fscanf_r, (struct _reent *, FILE *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__scanf__, 3, 4)))); -int _EXFUN(_fseek_r, (struct _reent *, FILE *, long, int)); -int _EXFUN(_fseeko_r,(struct _reent *, FILE *, _off_t, int)); -long _EXFUN(_ftell_r, (struct _reent *, FILE *)); -_off_t _EXFUN(_ftello_r,(struct _reent *, FILE *)); -void _EXFUN(_rewind_r, (struct _reent *, FILE *)); -size_t _EXFUN(_fwrite_r, (struct _reent *, const _PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); -size_t _EXFUN(_fwrite_unlocked_r, (struct _reent *, const _PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); -int _EXFUN(_getc_r, (struct _reent *, FILE *)); -int _EXFUN(_getc_unlocked_r, (struct _reent *, FILE *)); -int _EXFUN(_getchar_r, (struct _reent *)); -int _EXFUN(_getchar_unlocked_r, (struct _reent *)); -char * _EXFUN(_gets_r, (struct _reent *, char *)); -int _EXFUN(_iprintf_r, (struct _reent *, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -int _EXFUN(_iscanf_r, (struct _reent *, const char *, ...) - _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); -FILE * _EXFUN(_open_memstream_r, (struct _reent *, char **, size_t *)); -void _EXFUN(_perror_r, (struct _reent *, const char *)); -int _EXFUN(_printf_r, (struct _reent *, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -int _EXFUN(_putc_r, (struct _reent *, int, FILE *)); -int _EXFUN(_putc_unlocked_r, (struct _reent *, int, FILE *)); -int _EXFUN(_putchar_unlocked_r, (struct _reent *, int)); -int _EXFUN(_putchar_r, (struct _reent *, int)); -int _EXFUN(_puts_r, (struct _reent *, const char *)); -int _EXFUN(_remove_r, (struct _reent *, const char *)); -int _EXFUN(_rename_r, (struct _reent *, - const char *_old, const char *_new)); -int _EXFUN(_scanf_r, (struct _reent *, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); -int _EXFUN(_siprintf_r, (struct _reent *, char *, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(_siscanf_r, (struct _reent *, const char *, const char *, ...) - _ATTRIBUTE ((__format__ (__scanf__, 3, 4)))); -int _EXFUN(_sniprintf_r, (struct _reent *, char *, size_t, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 4, 5)))); -int _EXFUN(_snprintf_r, (struct _reent *, char *__restrict, size_t, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 4, 5)))); -int _EXFUN(_sprintf_r, (struct _reent *, char *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(_sscanf_r, (struct _reent *, const char *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__scanf__, 3, 4)))); -char * _EXFUN(_tempnam_r, (struct _reent *, const char *, const char *)); -FILE * _EXFUN(_tmpfile_r, (struct _reent *)); -char * _EXFUN(_tmpnam_r, (struct _reent *, char *)); -int _EXFUN(_ungetc_r, (struct _reent *, int, FILE *)); -int _EXFUN(_vasiprintf_r, (struct _reent *, char **, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -char * _EXFUN(_vasniprintf_r, (struct _reent*, char *, size_t *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 4, 0)))); -char * _EXFUN(_vasnprintf_r, (struct _reent*, char *, size_t *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 4, 0)))); -int _EXFUN(_vasprintf_r, (struct _reent *, char **, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(_vdiprintf_r, (struct _reent *, int, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(_vdprintf_r, (struct _reent *, int, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(_vfiprintf_r, (struct _reent *, FILE *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(_vfiscanf_r, (struct _reent *, FILE *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 3, 0)))); -int _EXFUN(_vfprintf_r, (struct _reent *, FILE *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(_vfscanf_r, (struct _reent *, FILE *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 3, 0)))); -int _EXFUN(_viprintf_r, (struct _reent *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(_viscanf_r, (struct _reent *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); -int _EXFUN(_vprintf_r, (struct _reent *, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(_vscanf_r, (struct _reent *, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); -int _EXFUN(_vsiprintf_r, (struct _reent *, char *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(_vsiscanf_r, (struct _reent *, const char *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 3, 0)))); -int _EXFUN(_vsniprintf_r, (struct _reent *, char *, size_t, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 4, 0)))); -int _EXFUN(_vsnprintf_r, (struct _reent *, char *__restrict, size_t, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 4, 0)))); -int _EXFUN(_vsprintf_r, (struct _reent *, char *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(_vsscanf_r, (struct _reent *, const char *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 3, 0)))); - -/* Other extensions. */ - -int _EXFUN(fpurge, (FILE *)); -ssize_t _EXFUN(__getdelim, (char **, size_t *, int, FILE *)); -ssize_t _EXFUN(__getline, (char **, size_t *, FILE *)); - -#if __BSD_VISIBLE -void _EXFUN(clearerr_unlocked, (FILE *)); -int _EXFUN(feof_unlocked, (FILE *)); -int _EXFUN(ferror_unlocked, (FILE *)); -int _EXFUN(fileno_unlocked, (FILE *)); -int _EXFUN(fflush_unlocked, (FILE *)); -int _EXFUN(fgetc_unlocked, (FILE *)); -int _EXFUN(fputc_unlocked, (int, FILE *)); -size_t _EXFUN(fread_unlocked, (_PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); -size_t _EXFUN(fwrite_unlocked, (const _PTR __restrict , size_t _size, size_t _n, FILE *)); -#endif - -#if __GNU_VISIBLE -char * _EXFUN(fgets_unlocked, (char *__restrict, int, FILE *__restrict)); -int _EXFUN(fputs_unlocked, (const char *__restrict, FILE *__restrict)); -#endif - -#ifdef __LARGE64_FILES -#if !defined(__CYGWIN__) || defined(_COMPILING_NEWLIB) -FILE * _EXFUN(fdopen64, (int, const char *)); -FILE * _EXFUN(fopen64, (const char *, const char *)); -FILE * _EXFUN(freopen64, (_CONST char *, _CONST char *, FILE *)); -_off64_t _EXFUN(ftello64, (FILE *)); -_off64_t _EXFUN(fseeko64, (FILE *, _off64_t, int)); -int _EXFUN(fgetpos64, (FILE *, _fpos64_t *)); -int _EXFUN(fsetpos64, (FILE *, const _fpos64_t *)); -FILE * _EXFUN(tmpfile64, (void)); - -FILE * _EXFUN(_fdopen64_r, (struct _reent *, int, const char *)); -FILE * _EXFUN(_fopen64_r, (struct _reent *,const char *, const char *)); -FILE * _EXFUN(_freopen64_r, (struct _reent *, _CONST char *, _CONST char *, FILE *)); -_off64_t _EXFUN(_ftello64_r, (struct _reent *, FILE *)); -_off64_t _EXFUN(_fseeko64_r, (struct _reent *, FILE *, _off64_t, int)); -int _EXFUN(_fgetpos64_r, (struct _reent *, FILE *, _fpos64_t *)); -int _EXFUN(_fsetpos64_r, (struct _reent *, FILE *, const _fpos64_t *)); -FILE * _EXFUN(_tmpfile64_r, (struct _reent *)); -#endif /* !__CYGWIN__ */ -#endif /* __LARGE64_FILES */ - -/* - * Routines internal to the implementation. - */ - -int _EXFUN(__srget_r, (struct _reent *, FILE *)); -int _EXFUN(__swbuf_r, (struct _reent *, int, FILE *)); - -/* - * Stdio function-access interface. - */ - -#ifndef __STRICT_ANSI__ -# ifdef __LARGE64_FILES -FILE *_EXFUN(funopen,(const _PTR __cookie, - int (*__readfn)(_PTR __c, char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - int (*__writefn)(_PTR __c, const char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - _fpos64_t (*__seekfn)(_PTR __c, _fpos64_t __off, int __whence), - int (*__closefn)(_PTR __c))); -FILE *_EXFUN(_funopen_r,(struct _reent *, const _PTR __cookie, - int (*__readfn)(_PTR __c, char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - int (*__writefn)(_PTR __c, const char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - _fpos64_t (*__seekfn)(_PTR __c, _fpos64_t __off, int __whence), - int (*__closefn)(_PTR __c))); -# else -FILE *_EXFUN(funopen,(const _PTR __cookie, - int (*__readfn)(_PTR __cookie, char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - int (*__writefn)(_PTR __cookie, const char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - fpos_t (*__seekfn)(_PTR __cookie, fpos_t __off, int __whence), - int (*__closefn)(_PTR __cookie))); -FILE *_EXFUN(_funopen_r,(struct _reent *, const _PTR __cookie, - int (*__readfn)(_PTR __cookie, char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - int (*__writefn)(_PTR __cookie, const char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - fpos_t (*__seekfn)(_PTR __cookie, fpos_t __off, int __whence), - int (*__closefn)(_PTR __cookie))); -# endif /* !__LARGE64_FILES */ - -# define fropen(__cookie, __fn) funopen(__cookie, __fn, (int (*)())0, \ - (fpos_t (*)())0, (int (*)())0) -# define fwopen(__cookie, __fn) funopen(__cookie, (int (*)())0, __fn, \ - (fpos_t (*)())0, (int (*)())0) - -typedef ssize_t cookie_read_function_t(void *__cookie, char *__buf, size_t __n); -typedef ssize_t cookie_write_function_t(void *__cookie, const char *__buf, - size_t __n); -# ifdef __LARGE64_FILES -typedef int cookie_seek_function_t(void *__cookie, _off64_t *__off, - int __whence); -# else -typedef int cookie_seek_function_t(void *__cookie, off_t *__off, int __whence); -# endif /* !__LARGE64_FILES */ -typedef int cookie_close_function_t(void *__cookie); -typedef struct -{ - /* These four struct member names are dictated by Linux; hopefully, - they don't conflict with any macros. */ - cookie_read_function_t *read; - cookie_write_function_t *write; - cookie_seek_function_t *seek; - cookie_close_function_t *close; -} cookie_io_functions_t; -FILE *_EXFUN(fopencookie,(void *__cookie, - const char *__mode, cookie_io_functions_t __functions)); -FILE *_EXFUN(_fopencookie_r,(struct _reent *, void *__cookie, - const char *__mode, cookie_io_functions_t __functions)); -#endif /* ! __STRICT_ANSI__ */ - -#ifndef __CUSTOM_FILE_IO__ -/* - * The __sfoo macros are here so that we can - * define function versions in the C library. - */ -#define __sgetc_raw_r(__ptr, __f) (--(__f)->_r < 0 ? __srget_r(__ptr, __f) : (int)(*(__f)->_p++)) - -#ifdef __SCLE -/* For a platform with CR/LF, additional logic is required by - __sgetc_r which would otherwise simply be a macro; therefore we - use an inlined function. The function is only meant to be inlined - in place as used and the function body should never be emitted. - - There are two possible means to this end when compiling with GCC, - one when compiling with a standard C99 compiler, and for other - compilers we're just stuck. At the moment, this issue only - affects the Cygwin target, so we'll most likely be using GCC. */ - -_ELIDABLE_INLINE int __sgetc_r(struct _reent *__ptr, FILE *__p); - -_ELIDABLE_INLINE int __sgetc_r(struct _reent *__ptr, FILE *__p) - { - int __c = __sgetc_raw_r(__ptr, __p); - if ((__p->_flags & __SCLE) && (__c == '\r')) - { - int __c2 = __sgetc_raw_r(__ptr, __p); - if (__c2 == '\n') - __c = __c2; - else - ungetc(__c2, __p); - } - return __c; - } -#else -#define __sgetc_r(__ptr, __p) __sgetc_raw_r(__ptr, __p) -#endif - -#ifdef _never /* __GNUC__ */ -/* If this inline is actually used, then systems using coff debugging - info get hopelessly confused. 21sept93 rich@cygnus.com. */ -_ELIDABLE_INLINE int __sputc_r(struct _reent *_ptr, int _c, FILE *_p) { - if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n')) - return (*_p->_p++ = _c); - else - return (__swbuf_r(_ptr, _c, _p)); -} -#else -/* - * This has been tuned to generate reasonable code on the vax using pcc - */ -#define __sputc_raw_r(__ptr, __c, __p) \ - (--(__p)->_w < 0 ? \ - (__p)->_w >= (__p)->_lbfsize ? \ - (*(__p)->_p = (__c)), *(__p)->_p != '\n' ? \ - (int)*(__p)->_p++ : \ - __swbuf_r(__ptr, '\n', __p) : \ - __swbuf_r(__ptr, (int)(__c), __p) : \ - (*(__p)->_p = (__c), (int)*(__p)->_p++)) -#ifdef __SCLE -#define __sputc_r(__ptr, __c, __p) \ - ((((__p)->_flags & __SCLE) && ((__c) == '\n')) \ - ? __sputc_raw_r(__ptr, '\r', (__p)) : 0 , \ - __sputc_raw_r((__ptr), (__c), (__p))) -#else -#define __sputc_r(__ptr, __c, __p) __sputc_raw_r(__ptr, __c, __p) -#endif -#endif - -#define __sfeof(p) ((int)(((p)->_flags & __SEOF) != 0)) -#define __sferror(p) ((int)(((p)->_flags & __SERR) != 0)) -#define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF))) -#define __sfileno(p) ((p)->_file) - -#ifndef _REENT_SMALL -#define feof(p) __sfeof(p) -#define ferror(p) __sferror(p) -#define clearerr(p) __sclearerr(p) - -#if __BSD_VISIBLE -#define feof_unlocked(p) __sfeof(p) -#define ferror_unlocked(p) __sferror(p) -#define clearerr_unlocked(p) __sclearerr(p) -#endif /* __BSD_VISIBLE */ -#endif /* _REENT_SMALL */ - -#if 0 /*ndef __STRICT_ANSI__ - FIXME: must initialize stdio first, use fn */ -#define fileno(p) __sfileno(p) -#endif - -#ifndef __CYGWIN__ -#ifndef lint -#define getc(fp) __sgetc_r(_REENT, fp) -#define putc(x, fp) __sputc_r(_REENT, x, fp) -#endif /* lint */ -#endif /* __CYGWIN__ */ - -#ifndef __STRICT_ANSI__ -/* fast always-buffered version, true iff error */ -#define fast_putc(x,p) (--(p)->_w < 0 ? \ - __swbuf_r(_REENT, (int)(x), p) == EOF : (*(p)->_p = (x), (p)->_p++, 0)) - -#define L_cuserid 9 /* posix says it goes in stdio.h :( */ -#ifdef __CYGWIN__ -#define L_ctermid 16 -#endif -#endif - -#endif /* !__CUSTOM_FILE_IO__ */ - -#define getchar() getc(stdin) -#define putchar(x) putc(x, stdout) - -#ifndef __STRICT_ANSI__ -#define getchar_unlocked() getc_unlocked(stdin) -#define putchar_unlocked(x) putc_unlocked(x, stdout) -#endif - -_END_STD_C - -#undef putchar -#undef getchar - -#ifdef __cplusplus -} -#endif - -#endif /* DOXYGEN */ -#endif /* STDIO_H */ diff --git a/cpu/esp32/include/sys/types.h b/cpu/esp32/include/sys/types.h deleted file mode 100644 index 385c16aa1d55..000000000000 --- a/cpu/esp32/include/sys/types.h +++ /dev/null @@ -1,336 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @{ - * - * @file - * @brief This file is a modification of original sys/types.h - * - * @author Gunar Schorcht - * - * This file is just a wrapper around sys/types.h to fix missing types - * fsblkcnt_t and fsfilcnt_t needed in statvfs.h - */ - - -/* unified sys/types.h: - start with sef's sysvi386 version. - merge go32 version -- a few ifdefs. - h8300hms, h8300xray, and sysvnecv70 disagree on the following types: - - typedef int gid_t; - typedef int uid_t; - typedef int dev_t; - typedef int ino_t; - typedef int mode_t; - typedef int caddr_t; - - however, these aren't "reasonable" values, the sysvi386 ones make far - more sense, and should work sufficiently well (in particular, h8300 - doesn't have a stat, and the necv70 doesn't matter.) -- eichin - */ - -#ifndef SYS_TYPES_H -#define SYS_TYPES_H - -#ifndef DOXYGEN - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _FSBLKCNT_T_DECLARED -#include -typedef uint32_t fsblkcnt_t; -typedef uint32_t fsfilcnt_t; -#define _FSBLKCNT_T_DECLARED -#endif - -#ifndef _SYS_TYPES_H - -#include <_ansi.h> - -#ifndef __INTTYPES_DEFINED__ -#define __INTTYPES_DEFINED__ - -#include - -#if defined(__rtems__) || defined(__XMK__) -/* - * The following section is RTEMS specific and is needed to more - * closely match the types defined in the BSD sys/types.h. - * This is needed to let the RTEMS/BSD TCP/IP stack compile. - */ - -/* deprecated */ -#if ___int8_t_defined -typedef __uint8_t u_int8_t; -#endif -#if ___int16_t_defined -typedef __uint16_t u_int16_t; -#endif -#if ___int32_t_defined -typedef __uint32_t u_int32_t; -#endif - -#if ___int64_t_defined -typedef __uint64_t u_int64_t; - -/* deprecated */ -typedef __uint64_t u_quad_t; -typedef __int64_t quad_t; -typedef quad_t * qaddr_t; -#endif - -#endif - -#endif /* ! __INTTYPES_DEFINED */ - -#ifndef __need_inttypes - -#define _SYS_TYPES_H -#include - -#ifdef __i386__ -#if defined (GO32) || defined (__MSDOS__) -#define __MS_types__ -#endif -#endif - -# include -# include - -/* To ensure the stat struct's layout doesn't change when sizeof(int), etc. - changes, we assume sizeof short and long never change and have all types - used to define struct stat use them and not int where possible. - Where not possible, _ST_INTxx are used. It would be preferable to not have - such assumptions, but until the extra fluff is necessary, it's avoided. - No 64 bit targets use stat yet. What to do about them is postponed - until necessary. */ -#ifdef __GNUC__ -#define _ST_INT32 __attribute__ ((__mode__ (__SI__))) -#else -#define _ST_INT32 -#endif - -# ifndef _POSIX_SOURCE - -# define physadr physadr_t -# define quad quad_t - -#ifndef _BSDTYPES_DEFINED -/* also defined in mingw/gmon.h and in w32api/winsock[2].h */ -#ifndef __u_char_defined -typedef unsigned char u_char; -#define __u_char_defined -#endif -#ifndef __u_short_defined -typedef unsigned short u_short; -#define __u_short_defined -#endif -#ifndef __u_int_defined -typedef unsigned int u_int; -#define __u_int_defined -#endif -#ifndef __u_long_defined -typedef unsigned long u_long; -#define __u_long_defined -#endif -#define _BSDTYPES_DEFINED -#endif - -typedef unsigned short ushort; /* System V compatibility */ -typedef unsigned int uint; /* System V compatibility */ -typedef unsigned long ulong; /* System V compatibility */ -# endif /*!_POSIX_SOURCE */ - -#ifndef __clock_t_defined -typedef _CLOCK_T_ clock_t; -#define __clock_t_defined -#endif - -#ifndef __time_t_defined -typedef _TIME_T_ time_t; -#define __time_t_defined -#endif - -#ifndef __timespec_defined -#define __timespec_defined -/* Time Value Specification Structures, P1003.1b-1993, p. 261 */ - -struct timespec { - time_t tv_sec; /* Seconds */ - long tv_nsec; /* Nanoseconds */ -}; -#endif - -struct itimerspec { - struct timespec it_interval; /* Timer period */ - struct timespec it_value; /* Timer expiration */ -}; - -#ifndef __daddr_t_defined -typedef long daddr_t; -#define __daddr_t_defined -#endif -#ifndef __caddr_t_defined -typedef char * caddr_t; -#define __caddr_t_defined -#endif - -#ifndef __CYGWIN__ -#if defined(__MS_types__) || defined(__rtems__) || \ - defined(__sparc__) || defined(__SPU__) -typedef unsigned long ino_t; -#else -typedef unsigned short ino_t; -#endif -#endif /*__CYGWIN__*/ - -#ifdef __MS_types__ -typedef unsigned long vm_offset_t; -typedef unsigned long vm_size_t; - -#define __BIT_TYPES_DEFINED__ - -typedef signed char int8_t; -typedef unsigned char u_int8_t; -typedef short int16_t; -typedef unsigned short u_int16_t; -typedef int int32_t; -typedef unsigned int u_int32_t; -typedef long long int64_t; -typedef unsigned long long u_int64_t; -typedef int32_t register_t; -#endif /* __MS_types__ */ - -/* - * All these should be machine specific - right now they are all broken. - * However, for all of Cygnus' embedded targets, we want them to all be - * the same. Otherwise things like sizeof (struct stat) might depend on - * how the file was compiled (e.g. -mint16 vs -mint32, etc.). - */ - -#ifndef __CYGWIN__ /* which defines these types in it's own types.h. */ -typedef _off_t off_t; -typedef __dev_t dev_t; -typedef __uid_t uid_t; -typedef __gid_t gid_t; -#endif - -#if defined(__XMK__) -typedef signed char pid_t; -#else -typedef int pid_t; -#endif - -#if defined(__rtems__) -typedef _mode_t mode_t; -#endif - -#ifndef __CYGWIN__ -typedef long key_t; -#endif -typedef _ssize_t ssize_t; - -#if !defined(__CYGWIN__) && !defined(__rtems__) -#ifdef __MS_types__ -typedef char * addr_t; -typedef int mode_t; -#else -#if defined (__sparc__) && !defined (__sparc_v9__) -#ifdef __svr4__ -typedef unsigned long mode_t; -#else -typedef unsigned short mode_t; -#endif -#else -typedef unsigned int mode_t _ST_INT32; -#endif -#endif /* ! __MS_types__ */ -#endif /*__CYGWIN__*/ - -typedef unsigned short nlink_t; - -/* We don't define fd_set and friends if we are compiling POSIX - source, or if we have included (or may include as indicated - by __USE_W32_SOCKETS) the W32api winsock[2].h header which - defines Windows versions of them. Note that a program which - includes the W32api winsock[2].h header must know what it is doing; - it must not call the cygwin32 select function. -*/ -# if !(defined (_POSIX_SOURCE) || defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS)) -# define _SYS_TYPES_FD_SET -# define NBBY 8 /* number of bits in a byte */ -/* - * Select uses bit masks of file descriptors in longs. - * These macros manipulate such bit fields (the filesystem macros use chars). - * FD_SETSIZE may be defined by the user, but the default here - * should be >= NOFILE (param.h). - */ -# ifndef FD_SETSIZE -# define FD_SETSIZE 64 -# endif - -typedef long fd_mask; -# define NFDBITS (sizeof (fd_mask) * NBBY) /* bits per mask */ -# ifndef howmany -# define howmany(x,y) (((x)+((y)-1))/(y)) -# endif - -/* We use a macro for fd_set so that including Sockets.h afterwards - can work. */ -typedef struct _types_fd_set { - fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)]; -} _types_fd_set; - -#define fd_set _types_fd_set - -# define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1L << ((n) % NFDBITS))) -# define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1L << ((n) % NFDBITS))) -# define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1L << ((n) % NFDBITS))) -# define FD_ZERO(p) (__extension__ (void)({ \ - size_t __i; \ - char *__tmp = (char *)p; \ - for (__i = 0; __i < sizeof (*(p)); ++__i) \ - *__tmp++ = 0; \ -})) - -# endif /* !(defined (_POSIX_SOURCE) || defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS)) */ - -#undef __MS_types__ -#undef _ST_INT32 - - -#ifndef __clockid_t_defined -typedef _CLOCKID_T_ clockid_t; -#define __clockid_t_defined -#endif - -#ifndef __timer_t_defined -typedef _TIMER_T_ timer_t; -#define __timer_t_defined -#endif - -typedef unsigned long useconds_t; -typedef long suseconds_t; - -#endif /* !__need_inttypes */ - -#undef __need_inttypes - -#endif /* _SYS_TYPES_H */ - -#ifdef __cplusplus -} -#endif - -#endif /* DOXYGEN */ -#endif /* SYS_TYPES_H */ diff --git a/cpu/esp32/include/syscalls.h b/cpu/esp32/include/syscalls.h index a9f7af02427c..4b0243751dc6 100644 --- a/cpu/esp32/include/syscalls.h +++ b/cpu/esp32/include/syscalls.h @@ -21,32 +21,15 @@ #ifndef SYSCALLS_H #define SYSCALLS_H -#include -#include -#include -#include - -#include "esp_common.h" +#include "syscalls_common.h" #ifdef __cplusplus extern "C" { #endif -/** Necessary initializations of system call functions */ -void syscalls_init (void); - -/** Determine free heap size */ -unsigned int get_free_heap_size (void); - -/** Time since boot in us (32bit version) */ -uint32_t system_get_time (void); - /** Time since boot in us (64bit version) */ uint64_t system_get_time_64 (void); -/** Time since boot in ms (32bit version) */ -uint32_t system_get_time_ms (void); - /** initialize system watchdog timer and start it */ void system_wdt_init (void); @@ -59,9 +42,6 @@ void system_wdt_stop (void); /** reset the system watchdog timer */ void system_wdt_feed (void); -/** memset version that the compiler should not be allowed to optimize this */ -void *system_secure_memset(void *s, int c, size_t n); - #ifdef __cplusplus } #endif diff --git a/cpu/esp32/include/thread_arch.h b/cpu/esp32/include/thread_arch.h deleted file mode 100644 index b454472e8989..000000000000 --- a/cpu/esp32/include/thread_arch.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @{ - * - * @file - * @brief Implementation of the kernel's architecture dependent thread interface - * - * @author Gunar Schorcht - * - * @} - */ - -#ifndef THREAD_ARCH_H -#define THREAD_ARCH_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Initializes the ISR stack - * Initializes the ISR stack with predefined values (address value) to be able to - * measure used ISR stack size. - */ -extern void thread_isr_stack_init(void); - -#ifdef __cplusplus -} -#endif - -#endif /* THREAD_ARCH_H */ diff --git a/cpu/esp32/include/xtensa_conf.h b/cpu/esp32/include/xtensa_conf.h deleted file mode 100644 index 32ad0ac6eb82..000000000000 --- a/cpu/esp32/include/xtensa_conf.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @{ - * - * @file - * @brief Xtensa ASM code specific configuration options - * - * @author Gunar Schorcht - */ - -#ifndef XTENSA_CONF_H -#define XTENSA_CONF_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Xtensa ASM code specific default stack sizes - * @{ - */ -#define ISR_STACKSIZE (2048) -/** @} */ - -#ifdef __cplusplus -} -#endif -#endif /* XTENSA_CONF_H */ -/** @} */ diff --git a/cpu/esp32/irq_arch.c b/cpu/esp32/irq_arch.c index 12b2beabb993..fd52da69d18c 100644 --- a/cpu/esp32/irq_arch.c +++ b/cpu/esp32/irq_arch.c @@ -21,89 +21,13 @@ #define ENABLE_DEBUG 0 #include "debug.h" -#include -#include - -#include "irq.h" #include "irq_arch.h" -#include "cpu.h" -#include "esp_common.h" #include "esp_err.h" -#include "esp/common_macros.h" -#include "esp/xtensa_ops.h" #include "rom/ets_sys.h" #include "soc/dport_reg.h" -#include "xtensa/xtensa_context.h" #include "xtensa/xtensa_api.h" -extern unsigned _xtos_set_intlevel(unsigned intlevel); - -/** - * @brief Set on entry into and reset on exit from an ISR - */ -volatile uint32_t irq_interrupt_nesting = 0; - -/** - * @brief Disable all maskable interrupts - */ -unsigned int IRAM irq_disable(void) -{ - uint32_t _saved_intlevel; - - /* read and set interrupt level with one asm instruction (RSIL) */ - __asm__ volatile ("rsil %0, " XTSTR(XCHAL_NUM_INTLEVELS+1) : "=a" (_saved_intlevel)); - /* mask out everything else of the PS register that do not belong to - interrupt level (bits 3..0) */ - _saved_intlevel &= 0xf; - - DEBUG ("%s new %08x (old %08x)\n", __func__, - XCHAL_NUM_INTLEVELS + 1, _saved_intlevel); - return _saved_intlevel; -} - -/** - * @brief Enable all maskable interrupts - */ -unsigned int IRAM irq_enable(void) -{ - uint32_t _saved_intlevel; - - /* read and set interrupt level with one asm instruction (RSIL) */ - __asm__ volatile ("rsil %0, 0" : "=a" (_saved_intlevel)); - /* mask out everything else of the PS register that do not belong to - interrupt level (bits 3..0) */ - _saved_intlevel &= 0xf; - - DEBUG ("%s new %08x (old %08x)\n", __func__, 0, _saved_intlevel); - return _saved_intlevel; -} - -/** - * @brief Restore the state of the IRQ flags - */ -void IRAM irq_restore(unsigned int state) -{ - /* restore the interrupt level using a rom function, performance is not - important here */ - #if 0 - __asm__ volatile ("wsr %0, ps; rsync" :: "a" (state)); - DEBUG ("%s %02x\n", __func__, state); - #else - unsigned _saved_intlevel = _xtos_set_intlevel(state); - DEBUG ("%s new %08x (old %08x)\n", __func__, state, _saved_intlevel); - #endif -} - -/** - * @brief See if the current context is inside an ISR - */ -int IRAM irq_is_in(void) -{ - DEBUG("irq_interrupt_nesting = %d\n", irq_interrupt_nesting); - return irq_interrupt_nesting; -} - struct _irq_alloc_table_t { int src; /* peripheral interrupt source */ uint32_t intr; /* interrupt number */ diff --git a/cpu/esp32/ld/esp32.common.ld b/cpu/esp32/ld/esp32.common.ld index 9fafb736eff5..5959333557c3 100644 --- a/cpu/esp32/ld/esp32.common.ld +++ b/cpu/esp32/ld/esp32.common.ld @@ -101,11 +101,13 @@ SECTIONS *esp_idf_spi_flash.a:*(.literal .text .literal.* .text.*) /* parts of RIOT that should to run in IRAM */ *core.a:*(.literal .text .literal.* .text.*) + *littlefs.a:*(.literal .text .literal.* .text.*) + *littlefs2.a:*(.literal .text .literal.* .text.*) *spiffs_fs.a:*(.literal .text .literal.* .text.*) *spiffs.a:*(.literal .text .literal.* .text.*) *vfs.a:*(.literal .text .literal.* .text.*) - /* part of RIOT ports that should run in IRAM */ + /* part of the RIOT port that should run in IRAM */ *cpu.a:*(.literal .text .literal.* .text.*) *periph.a:*(.literal .text .literal.* .text.*) *mtd.a:**(.literal .text .literal.* .text.*) diff --git a/cpu/esp32/periph/flash.c b/cpu/esp32/periph/flash.c deleted file mode 100644 index f0aab8980740..000000000000 --- a/cpu/esp32/periph/flash.c +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @{ - * - * @file - * @brief Low-level SPI flash and MTD drive implementation - * - * @author Gunar Schorcht - * - * @} - */ - -#if MODULE_MTD - -#include -#include -#include - -#include "esp_common.h" -#include "irq_arch.h" -#include "mtd.h" - -#include "rom/cache.h" -#include "rom/spi_flash.h" -#include "esp_flash_data_types.h" -#include "esp_partition.h" -#include "esp_spi_flash.h" - -#define ENABLE_DEBUG (0) -#include "debug.h" - -#define ESP_PART_TABLE_ADDR 0x8000 /* TODO configurable as used in Makefile.include */ -#define ESP_PART_TABLE_SIZE 0xC00 -#define ESP_PART_ENTRY_SIZE 0x20 -#define ESP_PART_ENTRY_MAGIC ESP_PARTITION_MAGIC - -/* the external pointer to the system MTD device */ -mtd_dev_t* mtd0 = 0; - -mtd_dev_t _flash_dev; -mtd_desc_t _flash_driver; - -/* forward declaration of mtd functions */ -static int _flash_init (mtd_dev_t *dev); -static int _flash_read (mtd_dev_t *dev, void *buff, uint32_t addr, uint32_t size); -static int _flash_write (mtd_dev_t *dev, const void *buff, uint32_t addr, uint32_t size); -static int _flash_erase (mtd_dev_t *dev, uint32_t addr, uint32_t size); -static int _flash_power (mtd_dev_t *dev, enum mtd_power_state power); - -static uint32_t _flash_beg; /* first byte addr of the flash drive in SPI flash */ -static uint32_t _flash_end; /* first byte addr after the flash drive in SPI flash */ -static uint32_t _flash_size; /* resulting size of the flash drive in SPI flash */ - -static esp_rom_spiflash_chip_t* _flashchip = NULL; - -void spi_flash_drive_init (void) -{ - DEBUG("%s\n", __func__); - - _flashchip = &g_rom_flashchip; - - _flash_driver.init = &_flash_init; - _flash_driver.read = &_flash_read; - _flash_driver.write = &_flash_write; - _flash_driver.erase = &_flash_erase; - _flash_driver.power = &_flash_power; - - /* first, set the beginning of flash to 0x0 to read partition table */ - _flash_beg = 0x0; - _flash_end = _flashchip->chip_size - 5 * _flashchip->sector_size; - _flash_size = _flash_end - _flash_beg; - - /* read in partition table an determine the top of all partitions */ - uint32_t part_addr = ESP_PART_TABLE_ADDR; - uint8_t part_buf[ESP_PART_ENTRY_SIZE]; - bool part_read = true; - uint32_t part_top = 0; - esp_partition_info_t* part = (esp_partition_info_t*)part_buf; - - while (part_read && part_addr < ESP_PART_TABLE_ADDR + ESP_PART_TABLE_SIZE) { - spi_flash_read (part_addr, (void*)part_buf, ESP_PART_ENTRY_SIZE); - - if (part->magic == ESP_PART_ENTRY_MAGIC) { - DEBUG("%s partition @%08x size=%08x label=%s\n", __func__, - part->pos.offset, part->pos.size, part->label); - if (part->pos.offset + part->pos.size > part_top) { - part_top = part->pos.offset + part->pos.size; - } - part_addr += ESP_PART_ENTRY_SIZE; - } - else { - part_read = false; - } - } - - /* map the partition top address to next higher multiple of 0x100000 */ - part_top = (part_top + 0x100000) & ~0xfffff; - - /* - * if flash drive start address is not configured, use the determined - * one otherwise check the configured one and use it - */ - #if SPI_FLASH_DRIVE_START - if (part_top > SPI_FLASH_DRIVE_START) { - LOG_ERROR("configured MTD start address in SPI Flash is to less\n"); - } - else if (SPI_FLASH_DRIVE_START % _flashchip->sector_size) { - LOG_ERROR("configured start address has to be a " - "multiple of %d byte\n", _flashchip->sector_size); - part_top = ((SPI_FLASH_DRIVE_START + - _flashchip->sector_size)) & ~(_flashchip->sector_size-1); - } - else { - part_top = SPI_FLASH_DRIVE_START; - } - #endif - - LOG_DEBUG("MTD in SPI flash starts at address 0x%08x\n", part_top); - - /* second, change flash parameters according to partition table */ - _flash_beg = part_top; - _flash_end = _flashchip->chip_size - 5 * _flashchip->sector_size; - _flash_size = _flash_end - _flash_beg; /* MUST be at least 3 sectors (0x3000) */ - - _flash_dev.driver = &_flash_driver; - _flash_dev.sector_count = _flash_size / _flashchip->sector_size; - - mtd0 = &_flash_dev; - - _flash_dev.pages_per_sector = _flashchip->sector_size / _flashchip->page_size; - _flash_dev.page_size = _flashchip->page_size; - - DEBUG("%s flashchip chip_size=%d block_size=%d sector_size=%d page_size=%d\n", __func__, - _flashchip->chip_size, _flashchip->block_size, - _flashchip->sector_size, _flashchip->page_size); - DEBUG("%s flash_dev sector_count=%d pages_per_sector=%d page_size=%d\n", __func__, - _flash_dev.sector_count, _flash_dev.pages_per_sector, _flash_dev.page_size); - DEBUG("\n"); -} - - -#define RETURN_WITH_ESP_ERR_CODE(err) do { \ - switch (err) { \ - case ESP_ROM_SPIFLASH_RESULT_OK : return ESP_OK; \ - case ESP_ROM_SPIFLASH_RESULT_ERR : return ESP_ERR_FLASH_OP_FAIL; \ - case ESP_ROM_SPIFLASH_RESULT_TIMEOUT: return ESP_ERR_FLASH_OP_TIMEOUT; \ - } \ - return ESP_FAIL; \ -} while(0) - -uint8_t _flash_buf[ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM]; - -esp_err_t IRAM_ATTR spi_flash_read(size_t addr, void *buff, size_t size) -{ - DEBUG("%s addr=%08x size=%u buf=%p\n", __func__, addr, size, buff); - - CHECK_PARAM_RET (buff != NULL, -ENOTSUP); - - /* size must be within the flash address space */ - CHECK_PARAM_RET (addr + size <= _flash_end, -EOVERFLOW); - - int result = ESP_ROM_SPIFLASH_RESULT_OK; - uint32_t len = size; - - /* if addr is not 4 byte aligned, we need to read the first full word */ - if (addr & 0x3) { - uint32_t word_addr = addr & ~0x3; - uint32_t pos_in_word = addr & 0x3; - uint32_t len_in_word = 4 - pos_in_word; - len_in_word = (len_in_word < len) ? len_in_word : len; - - /* disable interrupts and the cache */ - critical_enter(); - Cache_Read_Disable(PRO_CPU_NUM); - - result = esp_rom_spiflash_read (word_addr, (uint32_t*)_flash_buf, 4); - memcpy(buff, _flash_buf + pos_in_word, len_in_word); - - /* enable interrupts and the cache */ - Cache_Read_Enable(PRO_CPU_NUM); - critical_exit(); - - buff = (uint8_t*)buff + len_in_word; - addr += len_in_word; - len -= len_in_word; - } - - /* read all full words, maximum ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM - in one read operation */ - while (len > 4 && result == ESP_ROM_SPIFLASH_RESULT_OK) { - uint32_t len_full_words = len & ~0x3; - if (len_full_words > ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM) { - len_full_words = ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM; - } - - /* disable interrupts and the cache */ - critical_enter(); - Cache_Read_Disable(PRO_CPU_NUM); - - result |= esp_rom_spiflash_read (addr, (uint32_t*)_flash_buf, len_full_words); - memcpy(buff, _flash_buf, len_full_words); - - /* enable interrupts and the cache */ - Cache_Read_Enable(PRO_CPU_NUM); - critical_exit(); - - buff = (uint8_t*)buff + len_full_words; - addr += len_full_words; - len -= len_full_words; - } - - /* if there is some remaining, we need to prepare last word */ - if (len && result == ESP_ROM_SPIFLASH_RESULT_OK) { - /* disable interrupts and the cache */ - critical_enter(); - Cache_Read_Disable(PRO_CPU_NUM); - - result |= esp_rom_spiflash_read (addr, (uint32_t*)_flash_buf, 4); - memcpy(buff, _flash_buf, len); - - /* enable interrupts and the cache */ - Cache_Read_Enable(PRO_CPU_NUM); - critical_exit(); - } - - /* return with the ESP-IDF error code that is mapped from ROM error code */ - RETURN_WITH_ESP_ERR_CODE(result); -} - -esp_err_t IRAM_ATTR spi_flash_write(size_t addr, const void *buff, size_t size) -{ - DEBUG("%s addr=%08x size=%u buf=%p\n", __func__, addr, size, buff); - - CHECK_PARAM_RET (buff != NULL, -ENOTSUP); - - /* size must be within the flash address space */ - CHECK_PARAM_RET (addr + size <= _flash_end, -EOVERFLOW); - - /* prepare for write access */ - int result = esp_rom_spiflash_unlock(); - uint32_t len = size; - - /* if addr is not 4 byte aligned, we need to prepare first full word */ - if (addr & 0x3 && result == ESP_ROM_SPIFLASH_RESULT_OK) { - uint32_t word_addr = addr & ~0x3; - uint32_t pos_in_word = addr & 0x3; - uint32_t len_in_word = 4 - pos_in_word; - len_in_word = (len_in_word < len) ? len_in_word : len; - - /* disable interrupts and the cache */ - critical_enter(); - Cache_Read_Disable(PRO_CPU_NUM); - - result |= esp_rom_spiflash_read (word_addr, (uint32_t*)_flash_buf, 4); - memcpy(_flash_buf + pos_in_word, buff, len_in_word); - result |= esp_rom_spiflash_write (word_addr, (uint32_t*)_flash_buf, 4); - - /* enable interrupts and the cache */ - Cache_Read_Enable(PRO_CPU_NUM); - critical_exit(); - - buff = (uint8_t*)buff + len_in_word; - addr += len_in_word; - len -= len_in_word; - } - - /* write all full words, maximum ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM - in one write operation */ - while (len > 4 && result == ESP_ROM_SPIFLASH_RESULT_OK) { - uint32_t len_full_words = len & ~0x3; - if (len_full_words > ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM) { - len_full_words = ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM; - } - - /* disable interrupts and the cache */ - critical_enter(); - Cache_Read_Disable(PRO_CPU_NUM); - - memcpy(_flash_buf, buff, len_full_words); - result |= esp_rom_spiflash_write (addr, (uint32_t*)_flash_buf, len_full_words); - - /* enable interrupts and the cache */ - Cache_Read_Enable(PRO_CPU_NUM); - critical_exit(); - - buff = (uint8_t*)buff + len_full_words; - addr += len_full_words; - len -= len_full_words; - } - - /* if there is some remaining, we need to prepare last word */ - if (len && result == ESP_ROM_SPIFLASH_RESULT_OK) { - /* disable interrupts and the cache */ - critical_enter(); - Cache_Read_Disable(PRO_CPU_NUM); - - result |= esp_rom_spiflash_read (addr, (uint32_t*)_flash_buf, 4); - memcpy(_flash_buf, buff, len); - result |= esp_rom_spiflash_write (addr, (uint32_t*)_flash_buf, 4); - - /* enable interrupts and the cache */ - Cache_Read_Enable(PRO_CPU_NUM); - critical_exit(); - } - - /* reset write access */ - esp_rom_spiflash_lock(); - - /* return with the ESP-IDF error code that is mapped from ROM error code */ - RETURN_WITH_ESP_ERR_CODE(result); -} - -esp_err_t IRAM_ATTR spi_flash_erase_sector(size_t sector) -{ - return spi_flash_erase_range(sector * _flashchip->sector_size, 1); -} - -esp_err_t IRAM_ATTR spi_flash_erase_range(size_t addr, size_t size) -{ - /* size must be within the flash address space */ - CHECK_PARAM_RET (addr + size <= _flash_end, -EOVERFLOW); - - /* size must be a multiple of sector_size && at least one sector */ - CHECK_PARAM_RET (size >= _flashchip->sector_size, -ENOTSUP); - CHECK_PARAM_RET (size % _flashchip->sector_size == 0, -ENOTSUP) - - /* prepare for write access */ - uint32_t result = esp_rom_spiflash_unlock(); - - /* erase as many sectors as necessary */ - uint32_t sec = addr / _flashchip->sector_size; - uint32_t cnt = size / _flashchip->sector_size; - uint32_t sec_per_block = _flashchip->block_size / _flashchip->sector_size; - - while (cnt && result == ESP_ROM_SPIFLASH_RESULT_OK) { - /* disable interrupts and the cache */ - critical_enter(); - Cache_Read_Disable(PRO_CPU_NUM); - - /* erase block-wise (64 kByte) if cnt is at least sec_per_block */ - if (cnt >= sec_per_block) { - result = esp_rom_spiflash_erase_block (sec / sec_per_block); - sec += sec_per_block; - cnt -= sec_per_block; - } - else { - result = esp_rom_spiflash_erase_sector (sec++); - cnt--; - } - - /* enable interrupts and the cache */ - Cache_Read_Enable(PRO_CPU_NUM); - critical_exit(); - } - - /* reset write access */ - esp_rom_spiflash_lock(); - - /* return with the ESP-IDF error code that is mapped from ROM error code */ - RETURN_WITH_ESP_ERR_CODE(result); -} - -const esp_partition_t* esp_partition_find_first(esp_partition_type_t type, - esp_partition_subtype_t subtype, - const char* label) -{ - uint32_t info_addr = ESP_PART_TABLE_ADDR; - uint8_t info_buf[ESP_PART_ENTRY_SIZE]; - bool info_read = true; - - esp_partition_info_t* info = (esp_partition_info_t*)info_buf; - esp_partition_t* part; - - while (info_read && info_addr < ESP_PART_TABLE_ADDR + ESP_PART_TABLE_SIZE) { - spi_flash_read (info_addr, (void*)info_buf, ESP_PART_ENTRY_SIZE); - - if (info->magic == ESP_PART_ENTRY_MAGIC) { - DEBUG("%s partition @%08x size=%08x label=%s\n", __func__, - info->pos.offset, info->pos.size, info->label); - if ((info->type == type) && - (info->subtype == subtype || subtype == ESP_PARTITION_SUBTYPE_ANY) && - (label == NULL || strcmp((const char*)info->label, label) == 0)) { - part = malloc(sizeof(esp_partition_t)); - part->type = info->type; - part->subtype = info->subtype; - part->address = info->pos.offset; - part->size = info->pos.size; - part->encrypted = info->flags & PART_FLAG_ENCRYPTED; - strncpy(part->label, (const char*)info->label, sizeof(info->label)); - part->label[sizeof(part->label) - 1] = 0x0; - - return part; - } - info_addr += ESP_PART_ENTRY_SIZE; - } - else { - info_read = false; - } - } - return NULL; -} - -esp_err_t esp_partition_erase_range(const esp_partition_t* part, - size_t addr, size_t size) -{ - CHECK_PARAM_RET(part != NULL, ESP_ERR_INVALID_ARG); - - /* start addr and size must be inside the partition */ - CHECK_PARAM_RET(addr <= part->size, ESP_ERR_INVALID_ARG); - CHECK_PARAM_RET(addr + size <= part->size, ESP_ERR_INVALID_SIZE); - /* start addr and size must be a multiple of sector size */ - CHECK_PARAM_RET(addr % SPI_FLASH_SEC_SIZE == 0, ESP_ERR_INVALID_ARG); - CHECK_PARAM_RET(size % SPI_FLASH_SEC_SIZE == 0, ESP_ERR_INVALID_SIZE); - - return spi_flash_erase_range(part->address + addr, size); -} - - -static int _flash_init (mtd_dev_t *dev) -{ - DEBUG("%s dev=%p driver=%p\n", __func__, dev, &_flash_driver); - - CHECK_PARAM_RET (dev == &_flash_dev, -ENODEV); - - return 0; -} - -static int _flash_read (mtd_dev_t *dev, void *buff, uint32_t addr, uint32_t size) -{ - DEBUG("%s dev=%p addr=%08x size=%u buf=%p\n", __func__, dev, addr, size, buff); - - CHECK_PARAM_RET (dev == &_flash_dev, -ENODEV); - CHECK_PARAM_RET (buff != NULL, -ENOTSUP); - - /* size must be within the flash address space */ - CHECK_PARAM_RET (_flash_beg + addr + size <= _flash_end, -EOVERFLOW); - - return (spi_flash_read(_flash_beg + addr, buff, size) == ESP_OK) ?(int)size : -EIO; -} - -static int _flash_write (mtd_dev_t *dev, const void *buff, uint32_t addr, uint32_t size) -{ - DEBUG("%s dev=%p addr=%08x size=%u buf=%p\n", __func__, dev, addr, size, buff); - - CHECK_PARAM_RET (dev == &_flash_dev, -ENODEV); - CHECK_PARAM_RET (buff != NULL, -ENOTSUP); - - /* size must be within the flash address space */ - CHECK_PARAM_RET (_flash_beg + addr + size <= _flash_end, -EOVERFLOW); - - /* addr + size must be within a page */ - CHECK_PARAM_RET (size <= _flashchip->page_size, -EOVERFLOW); - CHECK_PARAM_RET ((addr % _flashchip->page_size) + size <= _flashchip->page_size, -EOVERFLOW); - - return (spi_flash_write(_flash_beg + addr, buff, size) == ESP_OK) ? (int)size : -EIO; -} - -static int _flash_erase (mtd_dev_t *dev, uint32_t addr, uint32_t size) -{ - DEBUG("%s dev=%p addr=%08x size=%u\n", __func__, dev, addr, size); - - CHECK_PARAM_RET (dev == &_flash_dev, -ENODEV); - - /* size must be within the flash address space */ - CHECK_PARAM_RET (_flash_beg + addr + size <= _flash_end, -EOVERFLOW); - - /* size must be a multiple of sector_size && at least one sector */ - CHECK_PARAM_RET (size >= _flashchip->sector_size, -EOVERFLOW); - CHECK_PARAM_RET (size % _flashchip->sector_size == 0, -EOVERFLOW) - - return (spi_flash_erase_range(_flash_beg + addr, size) == ESP_OK) ? 0 : -EIO; -} - -static int _flash_power (mtd_dev_t *dev, enum mtd_power_state power) -{ - DEBUG("%s\n", __func__); - - return -ENOTSUP; -} - -#endif /* MODULE_MTD */ diff --git a/cpu/esp32/periph/i2c_sw.c b/cpu/esp32/periph/i2c_sw.c deleted file mode 100644 index 8cc9e09ede86..000000000000 --- a/cpu/esp32/periph/i2c_sw.c +++ /dev/null @@ -1,717 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @ingroup drivers_periph_i2c - * @{ - * - * @file - * @brief Low-level I2C driver implementation for ESP32 SDK - * - * @author Gunar Schorcht - * - * @} - */ - -/* - PLEASE NOTE: - - Some parts of the implementation bases on the bit-banging implementation as - described in [wikipedia](https://en.wikipedia.org/wiki/I%C2%B2C) as well as - its implementation in [esp-open-rtos](https://github.com/SuperHouse/esp-open-rtos.git). - These parts are under the copyright of their respective owners. -*/ - -#if defined(MODULE_ESP_I2C_SW) /* software implementation used */ - -#define ENABLE_DEBUG (0) -#include "debug.h" - -#include -#include -#include - -#include "cpu.h" -#include "log.h" -#include "mutex.h" -#include "periph_conf.h" -#include "periph/gpio.h" -#include "periph/i2c.h" - -#include "esp_common.h" -#include "gpio_arch.h" -#include "rom/ets_sys.h" -#include "soc/gpio_reg.h" -#include "soc/gpio_struct.h" - -/* only include the code if one of the IC2 interface bus speeds are defined */ -#if defined(I2C0_SPEED) || defined(I2C1_SPEED) - -/* max clock stretching counter */ -#define I2C_CLOCK_STRETCH 200 - -/* gpio access macros */ -#define GPIO_SET(l,h,b) if (b < 32) GPIO.l = BIT(b); else GPIO.h.val = BIT(32-b) -#define GPIO_GET(l,h,b) ((b < 32) ? GPIO.l & BIT(b) : GPIO.h.val & BIT(32-b)) - -typedef struct -{ - i2c_speed_t speed; - i2c_t dev; - - bool started; - - gpio_t scl; - gpio_t sda; - - uint32_t scl_bit; /* gpio bit mask for faster access */ - uint32_t sda_bit; /* gpio bit mask for faster access */ - - uint32_t delay; - mutex_t lock; - -} _i2c_bus_t; - -static _i2c_bus_t _i2c_bus[I2C_NUMOF] = {}; - -/* to ensure that I2C is always optimized with -O2 to use the defined delays */ -#pragma GCC optimize ("O2") - -static const uint32_t _i2c_delays[][3] = -{ - /* values specify one half-period and are only valid for -O2 option */ - /* value = [period - 0.25 us (240 MHz) / 0.5us(160MHz) / 1.0us(80MHz)] */ - /* * cycles per second / 2 */ - /* 1 us = 48 cycles (240) / 32 cycles (160 MHz) / 16 cycles (80 MHz) */ - /* values for 240, 160, 80 MHz */ - [I2C_SPEED_LOW] = {2390, 1590, 790}, /* 10 kbps (period 100 us) */ - [I2C_SPEED_NORMAL] = { 230, 150, 70}, /* 100 kbps (period 10 us) */ - [I2C_SPEED_FAST] = { 51, 31, 11}, /* 400 kbps (period 2.5 us) */ - [I2C_SPEED_FAST_PLUS] = { 15, 7, 0}, /* 1 Mbps (period 1 us) */ - [I2C_SPEED_HIGH] = { 0, 0, 0} /* 3.4 Mbps (period 0.3 us) not working */ -}; - -/* forward declaration of internal functions */ - -static inline void _i2c_delay (_i2c_bus_t* bus); -static inline bool _i2c_scl_read (_i2c_bus_t* bus); -static inline bool _i2c_sda_read (_i2c_bus_t* bus); -static inline void _i2c_scl_high (_i2c_bus_t* bus); -static inline void _i2c_scl_low (_i2c_bus_t* bus); -static inline void _i2c_sda_high (_i2c_bus_t* bus); -static inline void _i2c_sda_low (_i2c_bus_t* bus); -static int _i2c_start_cond (_i2c_bus_t* bus); -static int _i2c_stop_cond (_i2c_bus_t* bus); -static int _i2c_write_bit (_i2c_bus_t* bus, bool bit); -static int _i2c_read_bit (_i2c_bus_t* bus, bool* bit); -static int _i2c_write_byte (_i2c_bus_t* bus, uint8_t byte); -static int _i2c_read_byte (_i2c_bus_t* bus, uint8_t* byte, bool ack); -static int _i2c_arbitration_lost (_i2c_bus_t* bus, const char* func); -static void _i2c_abort (_i2c_bus_t* bus, const char* func); -static void _i2c_clear (_i2c_bus_t* bus); - -/* implementation of i2c interface */ - -void i2c_init(i2c_t dev) -{ - CHECK_PARAM (dev < I2C_NUMOF) - - if (i2c_config[dev].speed == I2C_SPEED_HIGH) { - LOG_TAG_INFO("i2c", "I2C_SPEED_HIGH is not supported\n"); - return; - } - - mutex_init(&_i2c_bus[dev].lock); - - _i2c_bus[dev].scl = i2c_config[dev].scl; - _i2c_bus[dev].sda = i2c_config[dev].sda; - _i2c_bus[dev].speed = i2c_config[dev].speed; - - _i2c_bus[dev].dev = dev; - _i2c_bus[dev].scl_bit = BIT(_i2c_bus[dev].scl); /* store bit mask for faster access */ - _i2c_bus[dev].sda_bit = BIT(_i2c_bus[dev].sda); /* store bit mask for faster access */ - _i2c_bus[dev].started = false; /* for handling of repeated start condition */ - - switch (ets_get_cpu_frequency()) { - case 240: _i2c_bus[dev].delay = _i2c_delays[_i2c_bus[dev].speed][0]; break; - case 160: _i2c_bus[dev].delay = _i2c_delays[_i2c_bus[dev].speed][1]; break; - case 80: _i2c_bus[dev].delay = _i2c_delays[_i2c_bus[dev].speed][2]; break; - default : LOG_TAG_INFO("i2c", "I2C software implementation is not " - "supported for this CPU frequency: %d MHz\n", - ets_get_cpu_frequency()); - return; - } - - DEBUG ("%s scl=%d sda=%d speed=%d\n", __func__, - _i2c_bus[dev].scl, _i2c_bus[dev].sda, _i2c_bus[dev].speed); - - /* reset the GPIO usage if the pins were used for I2C before */ - if (gpio_get_pin_usage(_i2c_bus[dev].scl) == _I2C) { - gpio_set_pin_usage(_i2c_bus[dev].scl, _GPIO); - } - if (gpio_get_pin_usage(_i2c_bus[dev].sda) == _I2C) { - gpio_set_pin_usage(_i2c_bus[dev].sda, _GPIO); - } - - /* try to configure SDA and SCL pin as GPIO in open-drain mode with enabled pull-ups */ - if (gpio_init (_i2c_bus[dev].scl, GPIO_IN_OD_PU) || - gpio_init (_i2c_bus[dev].sda, GPIO_IN_OD_PU)) { - return; - } - - /* store the usage type in GPIO table */ - gpio_set_pin_usage(_i2c_bus[dev].scl, _I2C); - gpio_set_pin_usage(_i2c_bus[dev].sda, _I2C); - - /* set SDA and SCL to be floating and pulled-up to high */ - _i2c_sda_high (&_i2c_bus[dev]); - _i2c_scl_high (&_i2c_bus[dev]); - - /* clear the bus if necessary (SDA is driven permanently low) */ - _i2c_clear (&_i2c_bus[dev]); - - return; -} - -int i2c_acquire(i2c_t dev) -{ - CHECK_PARAM_RET (dev < I2C_NUMOF, -1) - - mutex_lock(&_i2c_bus[dev].lock); - return 0; -} - -void i2c_release(i2c_t dev) -{ - assert(dev < I2C_NUMOF); - - mutex_unlock(&_i2c_bus[dev].lock); -} - -int /* IRAM */ i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len, uint8_t flags) -{ - DEBUG ("%s: dev=%u addr=%02x data=%p len=%d flags=%01x\n", - __func__, dev, addr, data, len, flags); - - CHECK_PARAM_RET (dev < I2C_NUMOF, -EINVAL); - CHECK_PARAM_RET (len > 0, -EINVAL); - CHECK_PARAM_RET (data != NULL, -EINVAL); - - _i2c_bus_t* bus = &_i2c_bus[dev]; - - int res = 0; - - /* send START condition and address if I2C_NOSTART is not set */ - if (!(flags & I2C_NOSTART)) { - - /* START condition */ - if ((res = _i2c_start_cond (bus)) != 0) { - return res; - } - - /* send 10 bit or 7 bit address */ - if (flags & I2C_ADDR10) { - /* prepare 10 bit address bytes */ - uint8_t addr1 = 0xf0 | (addr & 0x0300) >> 7 | I2C_READ; - uint8_t addr2 = addr & 0xff; - /* send address bytes with read flag */ - if ((res = _i2c_write_byte (bus, addr1)) != 0 || - (res = _i2c_write_byte (bus, addr2)) != 0) { - /* abort transfer */ - _i2c_abort (bus, __func__); - return -ENXIO; - } - } - else { - /* send address byte with read flag */ - if ((res = _i2c_write_byte (bus, (addr << 1 | I2C_READ))) != 0) { - /* abort transfer */ - _i2c_abort (bus, __func__); - return -ENXIO; - } - } - } - - /* receive bytes if send address was successful */ - for (unsigned int i = 0; i < len; i++) { - if ((res = _i2c_read_byte (bus, &(((uint8_t*)data)[i]), i < len-1)) != 0) { - /* abort transfer */ - _i2c_abort (bus, __func__); - return res; - } - } - - /* send STOP condition if I2C_NOSTOP flag is not set */ - if (!(flags & I2C_NOSTOP)) { - _i2c_stop_cond (bus); - } - - return res; -} - -int /* IRAM */ i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_t len, uint8_t flags) -{ - DEBUG ("%s: dev=%u addr=%02x data=%p len=%d flags=%01x\n", - __func__, dev, addr, data, len, flags); - - CHECK_PARAM_RET (dev < I2C_NUMOF, -EINVAL); - CHECK_PARAM_RET (len > 0, -EINVAL); - CHECK_PARAM_RET (data != NULL, -EINVAL); - - _i2c_bus_t* bus = &_i2c_bus[dev]; - - int res = 0; - - /* if I2C_NOSTART is not set, send START condition and ADDR */ - if (!(flags & I2C_NOSTART)) { - - /* START condition */ - if ((res = _i2c_start_cond (bus)) != 0) { - return res; - } - - /* send 10 bit or 7 bit address */ - if (flags & I2C_ADDR10) { - /* prepare 10 bit address bytes */ - uint8_t addr1 = 0xf0 | (addr & 0x0300) >> 7; - uint8_t addr2 = addr & 0xff; - /* send address bytes without read flag */ - if ((res = _i2c_write_byte (bus, addr1)) != 0 || - (res = _i2c_write_byte (bus, addr2)) != 0) { - /* abort transfer */ - _i2c_abort (bus, __func__); - return -ENXIO; - } - } - else { - /* send address byte without read flag */ - if ((res = _i2c_write_byte (bus, addr << 1)) != 0) { - /* abort transfer */ - _i2c_abort (bus, __func__); - return -ENXIO; - } - } - } - - /* send bytes if send address was successful */ - for (unsigned int i = 0; i < len; i++) { - if ((res = _i2c_write_byte (bus, ((uint8_t*)data)[i])) != 0) { - /* abort transfer */ - _i2c_abort (bus, __func__); - return res; - } - } - - /* send STOP condition if I2C_NOSTOP flag is not set */ - if (!(flags & I2C_NOSTOP)) { - return _i2c_stop_cond (bus); - } - - return res; -} - -void i2c_poweron(i2c_t dev) -{ - /* since I2C is realized in software there is no device to power on */ - /* just return */ -} - -void i2c_poweroff(i2c_t dev) -{ - /* since I2C is realized in software there is no device to power off */ - /* just return */ -} - -/* --- internal functions --- */ - -static inline void _i2c_delay (_i2c_bus_t* bus) -{ - /* produces a delay */ - /* ca. 16 cycles = 1 us (80 MHz) or ca. 32 cycles = 1 us (160 MHz) */ - - uint32_t cycles = bus->delay; - if (cycles) { - __asm__ volatile ("1: _addi.n %0, %0, -1 \n" - " bnez %0, 1b \n" : "=r" (cycles) : "0" (cycles)); - } -} - -/* - * Please note: SDA and SDL pins are used in GPIO_OD_PU mode - * (open-drain with pull-ups). - * - * Setting a pin which is in open-drain mode leaves the pin floating and - * the signal is pulled up to high. The signal can then be actively driven - * to low by a slave. A read operation returns the current signal at the pin. - * - * Clearing a pin which is in open-drain mode actively drives the signal to - * low. - */ - -static inline bool _i2c_scl_read(_i2c_bus_t* bus) -{ - /* read SCL status (pin is in open-drain mode and set) */ - return GPIO_GET(in, in1, bus->scl); -} - -static inline bool _i2c_sda_read(_i2c_bus_t* bus) -{ - /* read SDA status (pin is in open-drain mode and set) */ - return GPIO_GET(in, in1, bus->sda); -} - -static inline void _i2c_scl_high(_i2c_bus_t* bus) -{ - /* set SCL signal high (pin is in open-drain mode and pulled-up) */ - GPIO_SET(out_w1ts, out1_w1ts, bus->scl); -} - -static inline void _i2c_scl_low(_i2c_bus_t* bus) -{ - /* set SCL signal low (actively driven to low) */ - GPIO_SET(out_w1tc, out1_w1tc, bus->scl); -} - -static inline void _i2c_sda_high(_i2c_bus_t* bus) -{ - /* set SDA signal high (pin is in open-drain mode and pulled-up) */ - GPIO_SET(out_w1ts, out1_w1ts, bus->sda); -} - -static inline void _i2c_sda_low(_i2c_bus_t* bus) -{ - /* set SDA signal low (actively driven to low) */ - GPIO_SET(out_w1tc, out1_w1tc, bus->sda); -} - -static void _i2c_clear(_i2c_bus_t* bus) -{ - DEBUG("%s: dev=%u\n", __func__, bus->dev); - - /** - * Sometimes a slave blocks and drives the SDA line permanently low. - * Send some clock pulses in that case (10 at maximum) - */ - - /* - * If SDA is low while SCL is high for 10 half cycles, it is not an - * arbitration lost but a bus lock. - */ - int count = 10; - while (!_i2c_sda_read (bus) && _i2c_scl_read (bus) && count) { - count--; - _i2c_delay (bus); - } - - if (count) { - /* was not a bus lock */ - return; - } - - /* send 10 clock pulses in case of bus lock */ - count = 10; - while (!_i2c_sda_read (bus) && count--) { - _i2c_scl_low (bus); - _i2c_delay (bus); - _i2c_scl_high (bus); - _i2c_delay (bus); - } -} - -static void _i2c_abort(_i2c_bus_t* bus, const char* func) -{ - DEBUG("%s: dev=%u\n", func, bus->dev); - - /* reset SCL and SDA to passive HIGH (floating and pulled-up) */ - _i2c_sda_high (bus); - _i2c_scl_high (bus); - - /* reset repeated start indicator */ - bus->started = false; - - /* clear the bus if necessary (SDA is driven permanently low) */ - _i2c_clear(bus); -} - -static /* IRAM */ int _i2c_arbitration_lost (_i2c_bus_t* bus, const char* func) -{ - DEBUG("%s: arbitration lost dev=%u\n", func, bus->dev); - - /* reset SCL and SDA to passive HIGH (floating and pulled-up) */ - _i2c_sda_high (bus); - _i2c_scl_high (bus); - - /* reset repeated start indicator */ - bus->started = false; - - /* clear the bus if necessary (SDA is driven permanently low) */ - _i2c_clear(bus); - - return -EAGAIN; -} - -static /* IRAM */ int _i2c_start_cond(_i2c_bus_t* bus) -{ - /* - * send start condition - * on entry: SDA and SCL are set to be floating and pulled-up to high - * on exit : SDA and SCL are actively driven to low - */ - - int res = 0; - - if (bus->started) { - /* prepare the repeated start condition */ - - /* SDA = passive HIGH (floating and pulled-up) */ - _i2c_sda_high (bus); - - /* t_VD;DAT not necessary */ - /* _i2c_delay (bus); */ - - /* SCL = passive HIGH (floating and pulled-up) */ - _i2c_scl_high (bus); - - /* clock stretching, wait as long as clock is driven to low by the slave */ - uint32_t stretch = I2C_CLOCK_STRETCH; - while (!_i2c_scl_read (bus) && stretch--) {} - if (stretch == 0) { - DEBUG("%s: clock stretching timeout dev=%u\n", __func__, bus->dev); - res = -ETIMEDOUT; - } - - /* wait t_SU;STA - set-up time for a repeated START condition */ - /* min. in us: 4.7 (SM), 0.6 (FM), 0.26 (FPM), 0.16 (HSM); no max. */ - _i2c_delay (bus); - } - - /* if SDA is low, arbitration is lost and someone else is driving the bus */ - if (!_i2c_sda_read (bus)) { - return _i2c_arbitration_lost (bus, __func__); - } - - /* begin the START condition: SDA = active LOW */ - _i2c_sda_low (bus); - - /* wait t_HD;STA - hold time (repeated) START condition, */ - /* max none */ - /* min 4.0 us (SM), 0.6 us (FM), 0.26 us (FPM), 0.16 us (HSM) */ - _i2c_delay (bus); - - /* complete the START condition: SCL = active LOW */ - _i2c_scl_low (bus); - - /* needed for repeated start condition */ - bus->started = true; - - return res; -} - -static /* IRAM */ int _i2c_stop_cond(_i2c_bus_t* bus) -{ - /* - * send stop condition - * on entry: SCL is active low and SDA can be changed - * on exit : SCL and SDA are set to be floating and pulled-up to high - */ - - int res = 0; - - /* begin the STOP condition: SDA = active LOW */ - _i2c_sda_low (bus); - - /* wait t_LOW - LOW period of SCL clock */ - /* min. in us: 4.7 (SM), 1.3 (FM), 0.5 (FPM), 0.16 (HSM); no max. */ - _i2c_delay (bus); - - /* SCL = passive HIGH (floating and pulled up) while SDA = active LOW */ - _i2c_scl_high (bus); - - /* clock stretching, wait as long as clock is driven to low by the slave */ - uint32_t stretch = I2C_CLOCK_STRETCH; - while (!_i2c_scl_read (bus) && stretch--) {} - if (stretch == 0) { - DEBUG("%s: clock stretching timeout dev=%u\n", __func__, bus->dev); - res = -ETIMEDOUT; - } - - /* wait t_SU;STO - hold time START condition, */ - /* min. in us: 4.0 (SM), 0.6 (FM), 0.26 (FPM), 0.16 (HSM); no max. */ - _i2c_delay (bus); - - /* complete the STOP condition: SDA = passive HIGH (floating and pulled up) */ - _i2c_sda_high (bus); - - /* reset repeated start indicator */ - bus->started = false; - - /* wait t_BUF - bus free time between a STOP and a START condition */ - /* min. in us: 4.7 (SM), 1.3 (FM), 0.5 (FPM), 0.16 (HSM); no max. */ - _i2c_delay (bus); - /* one additional delay */ - _i2c_delay (bus); - - /* if SDA is low, arbitration is lost and someone else is driving the bus */ - if (_i2c_sda_read (bus) == 0) { - return _i2c_arbitration_lost (bus, __func__); - } - - return res; -} - -static /* IRAM */ int _i2c_write_bit (_i2c_bus_t* bus, bool bit) -{ - /* - * send one bit - * on entry: SCL is active low, SDA can be changed - * on exit : SCL is active low, SDA can be changed - */ - - int res = 0; - - /* SDA = bit */ - if (bit) { - _i2c_sda_high (bus); - } - else { - _i2c_sda_low (bus); - } - - /* wait t_VD;DAT - data valid time (time until data are valid) */ - /* max. in us: 3.45 (SM), 0.9 (FM), 0.45 (FPM); no min */ - _i2c_delay (bus); - - /* SCL = passive HIGH (floating and pulled-up), SDA value is available */ - _i2c_scl_high (bus); - - /* wait t_HIGH - time for the slave to read SDA */ - /* min. in us: 4 (SM), 0.6 (FM), 0.26 (FPM), 0.09 (HSM); no max. */ - _i2c_delay (bus); - - /* clock stretching, wait as long as clock is driven low by the slave */ - uint32_t stretch = I2C_CLOCK_STRETCH; - while (!_i2c_scl_read (bus) && stretch--) {} - if (stretch == 0) { - DEBUG("%s: clock stretching timeout dev=%u\n", __func__, bus->dev); - res = -ETIMEDOUT; - } - - /* if SCL is high, now data is valid */ - /* if SDA is high, check that nobody else is driving SDA low */ - if (bit && !_i2c_sda_read(bus)) { - return _i2c_arbitration_lost (bus, __func__); - } - - /* SCL = active LOW to allow next SDA change */ - _i2c_scl_low(bus); - - return res; -} - -static /* IRAM */ int _i2c_read_bit (_i2c_bus_t* bus, bool* bit) -{ - /* read one bit - * on entry: SCL is active low, SDA can be changed - * on exit : SCL is active low, SDA can be changed - */ - - int res = 0; - - /* SDA = passive HIGH (floating and pulled-up) to let the slave drive data */ - _i2c_sda_high (bus); - - /* wait t_VD;DAT - data valid time (time until data are valid) */ - /* max. in us: 3.45 (SM), 0.9 (FM), 0.45 (FPM); no min */ - _i2c_delay (bus); - - /* SCL = passive HIGH (floating and pulled-up), SDA value is available */ - _i2c_scl_high (bus); - - /* clock stretching, wait as long as clock is driven to low by the slave */ - uint32_t stretch = I2C_CLOCK_STRETCH; - while (!_i2c_scl_read (bus) && stretch--) {} - if (stretch == 0) { - DEBUG("%s: clock stretching timeout dev=%u\n", __func__, bus->dev); - res = -ETIMEDOUT; - } - - /* wait t_HIGH - time for the slave to read SDA */ - /* min. in us: 4 (SM), 0.6 (FM), 0.26 (FPM), 0.09 (HSM); no max. */ - _i2c_delay (bus); - - /* SCL is high, read out bit */ - *bit = _i2c_sda_read (bus); - - /* SCL = active LOW to allow next SDA change */ - _i2c_scl_low(bus); - - return res; -} - -static /* IRAM */ int _i2c_write_byte (_i2c_bus_t* bus, uint8_t byte) -{ - /* send one byte and returns 0 in case of ACK from slave */ - - /* send the byte from MSB to LSB */ - for (unsigned i = 0; i < 8; i++) { - int res = _i2c_write_bit(bus, (byte & 0x80) != 0); - if (res != 0) { - return res; - } - byte = byte << 1; - } - - /* read acknowledge bit (low) from slave */ - bool bit; - int res = _i2c_read_bit (bus, &bit); - if (res != 0) { - return res; - } - - return !bit ? 0 : -EIO; -} - - -static /* IRAM */ int _i2c_read_byte(_i2c_bus_t* bus, uint8_t *byte, bool ack) -{ - bool bit; - - /* read the byte */ - for (unsigned i = 0; i < 8; i++) { - int res = _i2c_read_bit (bus, &bit); - if (res != 0) { - return res; - } - *byte = (*byte << 1) | (bit ? 1 : 0); - } - - /* write acknowledgement flag */ - _i2c_write_bit(bus, !ack); - - return 0; -} - -void i2c_print_config(void) -{ - for (unsigned dev = 0; dev < I2C_NUMOF; dev++) { - printf("\tI2C_DEV(%u)\tscl=%d sda=%d\n", - dev, i2c_config[dev].scl, i2c_config[dev].sda); - } -} - -#else /* defined(I2C0_SPEED) || defined(I2C1_SPEED) */ - -void i2c_print_config(void) -{ - LOG_TAG_INFO("i2c", "no I2C devices\n"); -} - -#endif /* defined(I2C0_SPEED) || defined(I2C1_SPEED) */ - -#endif /* MODULE_ESP_I2C_SW */ diff --git a/cpu/esp32/periph/spi.c b/cpu/esp32/periph/spi.c deleted file mode 100644 index 85d3b753711e..000000000000 --- a/cpu/esp32/periph/spi.c +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @ingroup drivers_periph_spi - * @{ - * - * @file - * @brief Low-level SPI driver implementation - * - * @author Gunar Schorcht - * - * @} - */ -#define ENABLE_DEBUG (0) -#include "debug.h" -#include "esp_common.h" -#include "log.h" - -#include - -#include "cpu.h" -#include "mutex.h" -#include "periph/spi.h" - -#include "driver/periph_ctrl.h" -#include "rom/ets_sys.h" -#include "soc/gpio_reg.h" -#include "soc/gpio_sig_map.h" -#include "soc/gpio_struct.h" -#include "soc/io_mux_reg.h" -#include "soc/spi_reg.h" -#include "soc/spi_struct.h" - -#include "gpio_arch.h" - -#if defined(SPI0_CTRL) || defined(SPI1_CTRL) - -#define SPI_BLOCK_SIZE 64 /* number of bytes per SPI transfer */ - -/* pins of FSI are fixed */ -#define FSPI_SCK GPIO6 -#define FSPI_MISO GPIO7 -#define FSPI_MOSI GPIO8 - -/** structure which describes all properties of one SPI bus */ -struct _spi_bus_t { - spi_dev_t* regs; /* pointer to register data struct of the SPI device */ - uint8_t mod; /* peripheral hardware module of the SPI interface */ - uint8_t int_src; /* peripheral interrupt source used by the SPI device */ - uint8_t signal_sck; /* SCK signal from the controller */ - uint8_t signal_mosi; /* MOSI signal from the controller */ - uint8_t signal_miso; /* MISO signal to the controller */ - mutex_t lock; /* mutex for each possible SPI interface */ - bool initialized; /* interface already initialized */ - bool pins_initialized; /* pins interface initialized */ -}; - -static struct _spi_bus_t _spi[] = { - #ifdef SPI0_CTRL - { - .initialized = false, - .pins_initialized = false, - .lock = MUTEX_INIT - }, - #endif - #ifdef SPI1_CTRL - { - .initialized = false, - .pins_initialized = false, - .lock = MUTEX_INIT - }, - #endif -}; - -#define CHECK_SPI_DEV(bus) { \ - CHECK_PARAM(bus < SPI_NUMOF); \ - if (_spi[bus].regs == NULL) { \ - LOG_TAG_ERROR("spi", "SPI_DEV(%d) is not available\n", bus); \ - return; \ - } \ -} - -#define CHECK_SPI_DEV_RET(bus,error) { \ - CHECK_PARAM_RET(bus < SPI_NUMOF, error); \ - if (_spi[bus].regs == NULL) { \ - LOG_TAG_ERROR("spi", "SPI_DEV(%d) is not available\n", bus); \ - return error; \ - } \ -} - -/* - * GPIOs that were once initialized as SPI interface pins can not be used - * afterwards for anything else. Therefore, SPI interfaces are not initialized - * until they are used for the first time. The *spi_init* function is just a - * dummy for source code compatibility. The initialization of an SPI interface - * is performed by the *_spi_init_internal* function, which is called either by - * the *spi_init_cs* function or the *spi_acquire* function when the interface - * is used for the first time. - */ - -void IRAM_ATTR spi_init (spi_t bus) -{ - CHECK_PARAM(bus < SPI_NUMOF); - - switch (spi_config[bus].ctrl) { - case HSPI: _spi[bus].regs = &SPI2; - _spi[bus].mod = PERIPH_HSPI_MODULE; - _spi[bus].int_src = ETS_SPI2_INTR_SOURCE; - _spi[bus].signal_sck = HSPICLK_OUT_IDX; - _spi[bus].signal_mosi = HSPID_OUT_IDX; - _spi[bus].signal_miso = HSPIQ_IN_IDX; - break; - case VSPI: _spi[bus].regs = &SPI3; - _spi[bus].mod = PERIPH_VSPI_MODULE; - _spi[bus].int_src = ETS_SPI3_INTR_SOURCE; - _spi[bus].signal_sck = VSPICLK_OUT_IDX; - _spi[bus].signal_mosi = VSPID_OUT_IDX; - _spi[bus].signal_miso = VSPIQ_IN_IDX; - break; - default: LOG_TAG_ERROR("spi", "invalid SPI interface controller " - "used for SPI_DEV(%d)\n", bus); - break; - } - return; -} - -/* Internal initialization function when the interface is used the first time */ -static void _spi_init_internal (spi_t bus) -{ - CHECK_SPI_DEV(bus); - - /* avoid multiple initializations */ - if (_spi[bus].initialized) { - return; - } - _spi[bus].initialized = true; - - DEBUG("%s bus=%u\n", __func__, bus); - - /* initialize pins */ - spi_init_pins(bus); - - /* check whether pins could be initialized, otherwise return */ - if (gpio_get_pin_usage(spi_config[bus].sck) != _SPI && - gpio_get_pin_usage(spi_config[bus].miso) != _SPI && - gpio_get_pin_usage(spi_config[bus].mosi) != _SPI && - gpio_get_pin_usage(spi_config[bus].cs) != _SPI) { - return; - } - - /* enable (power on) the according SPI module */ - periph_module_enable(_spi[bus].mod); - - /* bring the bus into a defined state */ - _spi[bus].regs->user.val = SPI_USR_MOSI | SPI_CK_I_EDGE | SPI_DOUTDIN | - SPI_CS_SETUP | SPI_CS_HOLD; - - /* set byte order to little endian for read and write operations */ - _spi[bus].regs->user.wr_byte_order = 0; - _spi[bus].regs->user.rd_byte_order = 0; - - /* set bit order to most significant first for read and write operations */ - _spi[bus].regs->ctrl.wr_bit_order = 0; - _spi[bus].regs->ctrl.rd_bit_order = 0; - - /* reset all DIO or QIO flags */ - _spi[bus].regs->ctrl.fread_qio = 0; - _spi[bus].regs->ctrl.fread_dio = 0; - _spi[bus].regs->ctrl.fread_quad = 0; - _spi[bus].regs->ctrl.fread_dual = 0; - - /* disable fast read mode and write protection */ - _spi[bus].regs->ctrl.fastrd_mode = 0; - _spi[bus].regs->ctrl.wp = 0; - - /* acquire and release to set default parameters */ - spi_acquire(bus, GPIO_UNDEF, SPI_MODE_0, SPI_CLK_1MHZ); - spi_release(bus); -} - -void spi_init_pins(spi_t bus) -{ - CHECK_SPI_DEV(bus); - - /* call initialization of the SPI interface if it is not initialized yet */ - if (!_spi[bus].initialized) { - _spi_init_internal(bus); - } - - /* avoid multiple pin initializations */ - if (_spi[bus].pins_initialized) { - return; - } - _spi[bus].pins_initialized = true; - - DEBUG("%s bus=%u\n", __func__, bus); - - /* in case of SPI_DEV(2) all pins are already initialized - as SPI pins */ - if (bus != SPI_DEV(2)) { - /* if not already initialized as SPI, try to initialize the pins */ - if (gpio_init (spi_config[bus].sck, GPIO_OUT) || - gpio_init (spi_config[bus].mosi, GPIO_OUT) || - gpio_init (spi_config[bus].miso, GPIO_IN)) { - LOG_TAG_ERROR("spi", - "SPI_DEV(%d) pins could not be initialized\n", bus); - return; - } - if (spi_init_cs(bus, spi_config[bus].cs) != SPI_OK) { - LOG_TAG_ERROR("spi", - "SPI_DEV(%d) CS signal could not be initialized\n", - bus); - return; - } - /* store the usage type in GPIO table */ - gpio_set_pin_usage(spi_config[bus].sck, _SPI); - gpio_set_pin_usage(spi_config[bus].mosi, _SPI); - gpio_set_pin_usage(spi_config[bus].miso, _SPI); - - /* connect SCK and MOSI pins to the output signal through the GPIO matrix */ - GPIO.func_out_sel_cfg[spi_config[bus].sck].func_sel = _spi[bus].signal_sck; - GPIO.func_out_sel_cfg[spi_config[bus].mosi].func_sel = _spi[bus].signal_mosi; - /* connect MISO input signal to the MISO pin through the GPIO matrix */ - GPIO.func_in_sel_cfg[_spi[bus].signal_miso].sig_in_sel = 1; - GPIO.func_in_sel_cfg[_spi[bus].signal_miso].sig_in_inv = 0; - GPIO.func_in_sel_cfg[_spi[bus].signal_miso].func_sel = spi_config[bus].miso; - } - else { - LOG_TAG_WARNING("spi", "Using SPI_DEV(2) is dangerous\n"); - } -} - -int spi_init_cs(spi_t bus, spi_cs_t cs) -{ - DEBUG("%s bus=%u cs=%u\n", __func__, bus, cs); - - CHECK_SPI_DEV_RET(bus, SPI_NODEV); - - /* call initialization of the SPI interface if it is not initialized yet */ - if (!_spi[bus].initialized) { - _spi_init_internal(bus); - } - - /* return if pin is already initialized as SPI CS signal */ - if (gpio_get_pin_usage(cs) == _SPI) { - return SPI_OK; - } - - /* check whether CS pin is used otherwise */ - if (gpio_get_pin_usage(cs) != _GPIO) { - return SPI_NOCS; - } - - /* initialize the pin */ - gpio_init(cs, GPIO_OUT); - gpio_set (cs); - - /* pin cannot be used for anything else */ - gpio_set_pin_usage(cs, _SPI); - - return SPI_OK; -} - -int IRAM_ATTR spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk) -{ - DEBUG("%s bus=%u cs=%u mode=%u clk=%u\n", __func__, bus, cs, mode, clk); - - CHECK_SPI_DEV_RET(bus, SPI_NODEV); - - /* call initialization of the SPI interface if it is not initialized yet */ - if (!_spi[bus].initialized) { - _spi_init_internal(bus); - } - - /* if parameter cs is GPIO_UNDEF, the default CS pin is used */ - cs = (cs == GPIO_UNDEF) ? spi_config[bus].cs : cs; - - /* if the CS pin used is not yet initialized, we do it now */ - if (gpio_get_pin_usage(cs) != _SPI && spi_init_cs(bus, cs) != SPI_OK) { - LOG_TAG_ERROR("spi", - "SPI_DEV(%d) CS signal could not be initialized\n", - bus); - return SPI_NOCS; - } - - /* lock the bus */ - mutex_lock(&_spi[bus].lock); - - /* set SPI mode, see Table 25 and Section 7.4.2 in Technical Reference */ - _spi[bus].regs->pin.ck_idle_edge = (mode == SPI_MODE_2 || mode == SPI_MODE_3); - _spi[bus].regs->user.ck_out_edge = (mode == SPI_MODE_1 || mode == SPI_MODE_2); - _spi[bus].regs->ctrl2.miso_delay_mode = (mode == SPI_MODE_0 || mode == SPI_MODE_3) ? 2 : 1; - _spi[bus].regs->ctrl2.miso_delay_num = 0; - _spi[bus].regs->ctrl2.mosi_delay_mode = 0; - _spi[bus].regs->ctrl2.mosi_delay_num = 0; - - /* set SPI clock, see Technical Reference */ - - uint32_t spi_clkdiv_pre; - uint32_t spi_clkcnt_N; - - switch (clk) { - case SPI_CLK_10MHZ: spi_clkdiv_pre = 2; /* predivides 80 MHz to 40 MHz */ - spi_clkcnt_N = 4; /* 4 cycles results into 10 MHz */ - break; - case SPI_CLK_5MHZ: spi_clkdiv_pre = 2; /* predivides 80 MHz to 40 MHz */ - spi_clkcnt_N = 8; /* 8 cycles results into 5 MHz */ - break; - case SPI_CLK_1MHZ: spi_clkdiv_pre = 2; /* predivides 80 MHz to 40 MHz */ - spi_clkcnt_N = 40; /* 40 cycles results into 1 MHz */ - break; - case SPI_CLK_400KHZ: spi_clkdiv_pre = 20; /* predivides 80 MHz to 4 MHz */ - spi_clkcnt_N = 10; /* 10 cycles results into 400 kHz */ - break; - case SPI_CLK_100KHZ: spi_clkdiv_pre = 20; /* predivides 80 MHz to 4 MHz */ - spi_clkcnt_N = 40; /* 20 cycles results into 100 kHz */ - break; - default: spi_clkdiv_pre = 20; /* predivides 80 MHz to 4 MHz */ - spi_clkcnt_N = 40; /* 20 cycles results into 100 kHz */ - } - - /* register values are set to deviders-1 */ - spi_clkdiv_pre--; - spi_clkcnt_N--; - - DEBUG("%s spi_clkdiv_prev=%u spi_clkcnt_N=%u\n", - __func__, spi_clkdiv_pre, spi_clkcnt_N); - - /* SPI clock is derived from APB clock by dividers */ - _spi[bus].regs->clock.clk_equ_sysclk = 0; - - /* set SPI clock dividers */ - _spi[bus].regs->clock.clkdiv_pre = spi_clkdiv_pre; - _spi[bus].regs->clock.clkcnt_n = spi_clkcnt_N; - _spi[bus].regs->clock.clkcnt_h = (spi_clkcnt_N+1)/2-1; - _spi[bus].regs->clock.clkcnt_l = spi_clkcnt_N; - - DEBUG("%s bus %d: SPI_CLOCK_REG=%08x\n", - __func__, bus, _spi[bus].regs->clock.val); - - return SPI_OK; -} - -void IRAM_ATTR spi_release(spi_t bus) -{ - CHECK_SPI_DEV(bus); - - /* release the bus */ - mutex_unlock(&_spi[bus].lock); -} - -static const char* _spi_names[] = { "CSPI", "FSPI", "HSPI", "VSPI" }; - -void spi_print_config(void) -{ - for (unsigned bus = 0; bus < SPI_NUMOF; bus++) { - printf("\tSPI_DEV(%u)\t%s ", bus, _spi_names[spi_config[bus].ctrl]); - printf("sck=%d " , spi_config[bus].sck); - printf("miso=%d ", spi_config[bus].miso); - printf("mosi=%d ", spi_config[bus].mosi); - printf("cs=%d\n" , spi_config[bus].cs); - } -} - -/* - * Following functions are from the hardware SPI driver of the esp-open-rtos - * project. - * - * Copyright (c) Ruslan V. Uss, 2016 - * BSD Licensed as described in the file LICENSE - * https://github.com/SuperHouse/esp-open-rtos/blob/master/LICENSE - */ - -inline static void IRAM_ATTR _set_size(uint8_t bus, uint8_t bytes) -{ - uint32_t bits = ((uint32_t)bytes << 3) - 1; - - _spi[bus].regs->mosi_dlen.val = bits; - _spi[bus].regs->miso_dlen.val = bits; -} - -inline static void IRAM_ATTR _wait(uint8_t bus) -{ - /* SPI_CMD_REG.SPI_USR is cleared when operation has been finished */ - while (_spi[bus].regs->cmd.usr) {} -} - -inline static void IRAM_ATTR _start(uint8_t bus) -{ - /* set SPI_CMD_REG.SPI_USR to start an operation */ - _spi[bus].regs->cmd.usr = 1; -} - -inline static void IRAM_ATTR _store_data(uint8_t bus, const void *data, size_t len) -{ - uint8_t words = len / 4; - uint8_t tail = len % 4; - - memcpy((void *)_spi[bus].regs->data_buf, data, len - tail); - - if (!tail) { - return; - } - - uint32_t last = 0; - uint8_t *offs = (uint8_t *)data + len - tail; - for (uint8_t i = 0; i < tail; i++) { - last = last | (offs[i] << (i * 8)); - } - _spi[bus].regs->data_buf[words] = last; -} - -static const uint8_t spi_empty_out[SPI_BLOCK_SIZE] = { 0 }; - -static void IRAM_ATTR _spi_buf_transfer(uint8_t bus, const void *out, void *in, size_t len) -{ - DEBUG("%s bus=%u out=%p in=%p len=%u\n", __func__, bus, out, in, len); - - /* transfer one block data */ - _wait(bus); - _set_size(bus, len); - _store_data(bus, out ? out : spi_empty_out, len); - _start(bus); - _wait(bus); - if (in) { - memcpy(in, (void *)_spi[bus].regs->data_buf, len); - } -} - -void IRAM_ATTR spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont, - const void *out, void *in, size_t len) -{ - CHECK_SPI_DEV(bus); - - DEBUG("%s bus=%u cs=%u cont=%d out=%p in=%p len=%u\n", - __func__, bus, cs, cont, out, in, len); - - if (!len) { - return; - } - - #if ENABLE_DEBUG - if (out) { - DEBUG("out = "); - for (size_t i = 0; i < len; i++) { - DEBUG("%02x ", ((const uint8_t *)out)[i]); - } - DEBUG("\n"); - } - #endif - - if (cs != SPI_CS_UNDEF) { - gpio_clear(cs); - } - - size_t blocks = len / SPI_BLOCK_SIZE; - uint8_t tail = len % SPI_BLOCK_SIZE; - - DEBUG("%s bus=%u cs=%u blocks=%d tail=%d\n", - __func__, bus, cs, blocks, tail); - - for (size_t i = 0; i < blocks; i++) { - _spi_buf_transfer(bus, - out ? (const uint8_t *)out + i * SPI_BLOCK_SIZE : NULL, - in ? (uint8_t *)in + i * SPI_BLOCK_SIZE : NULL, SPI_BLOCK_SIZE); - } - if (tail) { - _spi_buf_transfer(bus, - out ? (const uint8_t *)out + blocks * SPI_BLOCK_SIZE : 0, - in ? (uint8_t *)in + blocks * SPI_BLOCK_SIZE : NULL, tail); - } - - if (!cont && (cs != SPI_CS_UNDEF)) { - gpio_set (cs); - } - - #if ENABLE_DEBUG - if (in) { - DEBUG("in = "); - for (size_t i = 0; i < len; i++) { - DEBUG("%02x ", ((const uint8_t *)in)[i]); - } - DEBUG("\n"); - } - #endif -} - -#endif /* defined(SPI0_CTRL) || defined(SPI1_CTRL) */ diff --git a/cpu/esp32/periph/timer.c b/cpu/esp32/periph/timer.c index 082dd84fd74f..756150e08159 100644 --- a/cpu/esp32/periph/timer.c +++ b/cpu/esp32/periph/timer.c @@ -111,8 +111,8 @@ struct hw_timer_t { }; struct hw_timer_hw_t { - struct hw_timer_regs_t* regs; /* timer configuration regs */ - struct hw_timer_ints_t* int_regs; /* timer interrupt regs */ + volatile struct hw_timer_regs_t* regs; /* timer configuration regs */ + volatile struct hw_timer_ints_t* int_regs; /* timer interrupt regs */ uint8_t int_mask; /* timer interrupt bit mask in interrupt regs */ uint8_t int_src; /* timer interrupt source */ }; @@ -144,10 +144,8 @@ static const struct hw_timer_hw_t timers_hw[HW_TIMER_NUMOF] = /** Latches the current counter value and return only the low part */ static inline uint32_t timer_get_counter_lo(tim_t dev) { - /* we have to latch the current timer value */ + /* latch the current timer value by writing any value to the update reg */ timers_hw[dev].regs->UPDATE_REG = 0; - /* wait until instructions have been finished */ - __asm__ volatile ("isync"); /* read high and low part of counter */ return timers_hw[dev].regs->LO_REG; } @@ -159,10 +157,8 @@ static inline void timer_get_counter(tim_t dev, uint32_t* hi, uint32_t* lo) if (!hi || !lo) { return; } - /* we have to latch the current timer value */ + /* latch the current timer value by writing any value to the update reg */ timers_hw[dev].regs->UPDATE_REG = 0; - /* wait until instructions have been finished */ - __asm__ volatile ("isync"); /* read high and low part of counter */ *hi = timers_hw[dev].regs->HI_REG; *lo = timers_hw[dev].regs->LO_REG; @@ -278,7 +274,6 @@ int IRAM timer_set(tim_t dev, int chn, unsigned int delta) /* wait until instructions have been finished */ timers_hw[dev].regs->CONFIG_REG.EN = 1; - __asm__ volatile ("isync"); /* clear the bit in status and set the bit in interrupt enable */ timers_hw[dev].int_regs->INT_CLR_REG |= timers_hw[dev].int_mask; diff --git a/cpu/esp32/periph/uart.c b/cpu/esp32/periph/uart.c deleted file mode 100644 index 5e3d7c200b1e..000000000000 --- a/cpu/esp32/periph/uart.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @ingroup drivers_periph_uart - * @{ - * - * @file - * @brief Low-level UART driver implementation - * - * @author Gunar Schorcht - * - * @} - */ - -#define ENABLE_DEBUG (0) -#include "debug.h" - -#include "esp_common.h" - -#include "cpu.h" -#include "irq_arch.h" -#include "log.h" -#include "sched.h" -#include "thread.h" - -#include "periph/gpio.h" -#include "periph/uart.h" - -#include "gpio_arch.h" -#include "driver/periph_ctrl.h" -#include "esp/common_macros.h" -#include "rom/ets_sys.h" -#include "soc/gpio_reg.h" -#include "soc/gpio_sig_map.h" -#include "soc/gpio_struct.h" -#include "soc/rtc.h" -#include "soc/uart_reg.h" -#include "soc/uart_struct.h" -#include "xtensa/xtensa_api.h" - -#undef UART_CLK_FREQ -#define UART_CLK_FREQ rtc_clk_apb_freq_get() /* APB_CLK is used */ - -struct uart_hw_t { - uart_dev_t* regs; /* pointer to register data struct of the UART device */ - uint8_t mod; /* peripheral hardware module of the UART interface */ - bool used; /* indicates whether UART is used */ - uint32_t baudrate; /* used baudrate */ - uart_data_bits_t data; /* used data bits */ - uart_stop_bits_t stop; /* used stop bits */ - uart_parity_t parity; /* used parity bits */ - uart_isr_ctx_t isr_ctx; /* callback functions */ - uint8_t signal_txd; /* TxD signal from the controller */ - uint8_t signal_rxd; /* RxD signal to the controller */ - uint8_t int_src; /* peripheral interrupt source used by the UART device */ -}; - -/* hardware resources */ -static struct uart_hw_t _uarts[] = { - { - .regs = &UART0, - .mod = PERIPH_UART0_MODULE, - .used = false, - .baudrate = STDIO_UART_BAUDRATE, - .data = UART_DATA_BITS_8, - .stop = UART_STOP_BITS_1, - .parity = UART_PARITY_NONE, - .signal_txd = U0TXD_OUT_IDX, - .signal_rxd = U0RXD_IN_IDX, - .int_src = ETS_UART0_INTR_SOURCE - }, - { - .regs = &UART1, - .mod = PERIPH_UART1_MODULE, - .used = false, - .baudrate = STDIO_UART_BAUDRATE, - .data = UART_DATA_BITS_8, - .stop = UART_STOP_BITS_1, - .parity = UART_PARITY_NONE, - .signal_txd = U1TXD_OUT_IDX, - .signal_rxd = U1RXD_IN_IDX, - .int_src = ETS_UART1_INTR_SOURCE - }, - { - .regs = &UART2, - .mod = PERIPH_UART2_MODULE, - .used = false, - .baudrate = STDIO_UART_BAUDRATE, - .data = UART_DATA_BITS_8, - .stop = UART_STOP_BITS_1, - .parity = UART_PARITY_NONE, - .signal_txd = U2TXD_OUT_IDX, - .signal_rxd = U2RXD_IN_IDX, - .int_src = ETS_UART2_INTR_SOURCE - } -}; - -/* declaration of external functions */ -extern void uart_div_modify(uint8_t uart_no, uint32_t div); - -/* forward declaration of internal functions */ -static int _uart_set_baudrate(uart_t uart, uint32_t baudrate); -static int _uart_set_mode(uart_t uart, uart_data_bits_t data_bits, - uart_parity_t parity, uart_stop_bits_t stop_bits); -static uint8_t IRAM _uart_rx_one_char (uart_t uart); -static void _uart_tx_one_char(uart_t uart, uint8_t data); -static void _uart_intr_enable (uart_t uart); -static void _uart_config (uart_t uart); -static void IRAM _uart_intr_handler (void *para); - -int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) -{ - DEBUG("%s uart=%d, rate=%d, rx_cb=%p, arg=%p\n", __func__, uart, baudrate, rx_cb, arg); - - CHECK_PARAM_RET (uart < UART_NUMOF, -1); - - /* UART1 and UART2 have configurable pins */ - if (uart == UART_DEV(1) || uart == UART_DEV(2)) { - - /* reset the pins when they were already used as UART pins */ - if (gpio_get_pin_usage(uart_config[uart].txd) == _UART) { - gpio_set_pin_usage(uart_config[uart].txd, _GPIO); - } - if (gpio_get_pin_usage(uart_config[uart].rxd) == _UART) { - gpio_set_pin_usage(uart_config[uart].rxd, _GPIO); - } - - /* try to initialize the pins as GPIOs first */ - if (gpio_init (uart_config[uart].rxd, GPIO_IN) || - gpio_init (uart_config[uart].txd, GPIO_OUT)) { - return -1; - } - - /* store the usage type in GPIO table */ - gpio_set_pin_usage(uart_config[uart].txd, _UART); - gpio_set_pin_usage(uart_config[uart].rxd, _UART); - - /* connect TxD pin to the TxD output signal through the GPIO matrix */ - GPIO.func_out_sel_cfg[uart_config[uart].txd].func_sel = _uarts[uart].signal_txd; - /* connect RxD input signal to the RxD pin through the GPIO matrix */ - GPIO.func_in_sel_cfg[_uarts[uart].signal_rxd].sig_in_sel = 1; - GPIO.func_in_sel_cfg[_uarts[uart].signal_rxd].sig_in_inv = 0; - GPIO.func_in_sel_cfg[_uarts[uart].signal_rxd].func_sel = uart_config[uart].rxd; - } - _uarts[uart].baudrate = baudrate; - - /* register interrupt context */ - _uarts[uart].isr_ctx.rx_cb = rx_cb; - _uarts[uart].isr_ctx.arg = arg; - - /* enable and configure the according UART module */ - uart_poweron(uart); - - return UART_OK; -} - -#if MODULE_PERIPH_UART_MODECFG -int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity, - uart_stop_bits_t stop_bits) -{ - return _uart_set_mode(uart, data_bits, parity, stop_bits); -} -#endif - -void uart_write(uart_t uart, const uint8_t *data, size_t len) -{ - CHECK_PARAM (uart < UART_NUMOF); - - for (size_t i = 0; i < len; i++) { - _uart_tx_one_char(uart, data[i]); - } -} - -void uart_poweron (uart_t uart) -{ - CHECK_PARAM (uart < UART_NUMOF); - - periph_module_enable(_uarts[uart].mod); - _uart_config(uart); -} - -void uart_poweroff (uart_t uart) -{ - CHECK_PARAM (uart < UART_NUMOF); - - periph_module_disable(_uarts[uart].mod); -} - -/* systemwide UART initializations */ -void uart_system_init (void) -{ - for (unsigned uart = 0; uart < UART_NUMOF; uart++) { - /* reset all UART interrupt status registers */ - _uarts[uart].regs->int_clr.val = ~0; - } -} - -void uart_print_config(void) -{ - for (unsigned uart = 0; uart < UART_NUMOF; uart++) { - printf("\tUART_DEV(%u)\ttxd=%d rxd=%d\n", uart, - uart_config[uart].txd, uart_config[uart].rxd); - } -} - -static void IRAM _uart_intr_handler (void *arg) -{ - /* to satisfy the compiler */ - (void)arg; - - irq_isr_enter (); - - /* UART0, UART1, UART2 peripheral interrupt sources are routed to the same - interrupt, so we have to use the status to distinguish interruptees */ - for (unsigned uart = 0; uart < UART_NUMOF; uart++) { - if (_uarts[uart].used) { - DEBUG("%s uart=%d int_st=%08x\n", __func__, - uart, _uarts[uart].regs->int_st.val); - - if (_uarts[uart].used && _uarts[uart].regs->int_st.rxfifo_full) { - /* read one byte of data */ - uint8_t data = _uart_rx_one_char (uart); - /* if registered, call the RX callback function */ - if (_uarts[uart].isr_ctx.rx_cb) { - _uarts[uart].isr_ctx.rx_cb(_uarts[uart].isr_ctx.arg, data); - } - /* clear interrupt flag */ - _uarts[uart].regs->int_clr.rxfifo_full = 1; - } - - /* TODO handle other types of interrupts, for the moment just clear them */ - _uarts[uart].regs->int_clr.val = ~0x0; - } - } - - irq_isr_exit (); -} - -/* RX/TX FIFO capacity is 128 byte */ -#define UART_FIFO_MAX 127 - -/* receive one data byte with wait */ -static uint8_t IRAM _uart_rx_one_char (uart_t uart) -{ - /* wait until at least von byte is in RX FIFO */ - while (!_uarts[uart].regs->status.rxfifo_cnt) {} - - /* read the lowest byte from RX FIFO register */ - return _uarts[uart].regs->fifo.rw_byte; -} - -/* send one data byte with wait */ -static void _uart_tx_one_char(uart_t uart, uint8_t data) -{ - /* wait until at least one byte is available in the TX FIFO */ - while (_uarts[uart].regs->status.txfifo_cnt >= UART_FIFO_MAX) {} - - /* send the byte by placing it in the TX FIFO using MPU */ - WRITE_PERI_REG(UART_FIFO_AHB_REG(uart), data); -} - -static void _uart_intr_enable(uart_t uart) -{ - _uarts[uart].regs->int_ena.rxfifo_full = 1; - _uarts[uart].regs->int_clr.rxfifo_full = 1; - _uarts[uart].used = true; - - DEBUG("%s %08x\n", __func__, _uarts[uart].regs->int_ena.val); -} - -static void _uart_config (uart_t uart) -{ - CHECK_PARAM (uart < UART_NUMOF); - - /* setup the baudrate */ - if (uart == UART_DEV(0) || uart == UART_DEV(1)) { - /* wait until TX FIFO is empty */ - while (_uarts[uart].regs->status.txfifo_cnt) { } - /* for UART0 and UART1, we can us the ROM function */ - uart_div_modify(uart, (UART_CLK_FREQ << 4) / _uarts[uart].baudrate); - } - else if (_uart_set_baudrate(uart, _uarts[uart].baudrate) != UART_OK) { - return; - } - - /* set number of data bits, stop bits and parity mode */ - if (_uart_set_mode(uart, _uarts[uart].data, _uarts[uart].stop, - _uarts[uart].parity) != UART_OK) { - return; - } - - /* reset the FIFOs */ - _uarts[uart].regs->conf0.rxfifo_rst = 1; - _uarts[uart].regs->conf0.rxfifo_rst = 0; - _uarts[uart].regs->conf0.txfifo_rst = 1; - _uarts[uart].regs->conf0.txfifo_rst = 0; - - if (_uarts[uart].isr_ctx.rx_cb) { - /* since reading can only be done byte by byte, we set - UART_RXFIFO_FULL_THRHD interrupt level to 1 byte */ - _uarts[uart].regs->conf1.rxfifo_full_thrhd = 1; - - /* enable the RX FIFO FULL interrupt */ - _uart_intr_enable (uart); - - /* route all UART interrupt sources to same the CPU interrupt */ - intr_matrix_set(PRO_CPU_NUM, _uarts[uart].int_src, CPU_INUM_UART); - - /* we have to enable therefore the CPU interrupt here */ - xt_set_interrupt_handler(CPU_INUM_UART, _uart_intr_handler, NULL); - xt_ints_on(BIT(CPU_INUM_UART)); - } -} - -static int _uart_set_baudrate(uart_t uart, uint32_t baudrate) -{ - DEBUG("%s uart=%d, rate=%d\n", __func__, uart, baudrate); - - CHECK_PARAM_RET (uart < UART_NUMOF, -1); - - /* wait until TX FIFO is empty */ - while (_uarts[uart].regs->status.txfifo_cnt != 0) { } - - critical_enter(); - - _uarts[uart].baudrate = baudrate; - - /* use APB_CLK */ - _uarts[uart].regs->conf0.tick_ref_always_on = 1; - /* compute and set the integral and the decimal part */ - uint32_t clk = (UART_CLK_FREQ << 4) / baudrate; - _uarts[uart].regs->clk_div.div_int = clk >> 4; - _uarts[uart].regs->clk_div.div_frag = clk & 0xf; - - critical_exit(); - return UART_OK; -} - -static int _uart_set_mode(uart_t uart, uart_data_bits_t data_bits, - uart_parity_t parity, uart_stop_bits_t stop_bits) -{ - DEBUG("%s uart=%d, data_bits=%d parity=%d stop_bits=%d\n", __func__, - uart, data_bits, parity, stop_bits); - - CHECK_PARAM_RET (uart < UART_NUMOF, UART_NODEV); - - critical_enter(); - - /* set number of data bits */ - switch (data_bits) { - case UART_DATA_BITS_5: _uarts[uart].regs->conf0.bit_num = 0; break; - case UART_DATA_BITS_6: _uarts[uart].regs->conf0.bit_num = 1; break; - case UART_DATA_BITS_7: _uarts[uart].regs->conf0.bit_num = 2; break; - case UART_DATA_BITS_8: _uarts[uart].regs->conf0.bit_num = 3; break; - default: LOG_TAG_ERROR("uart", "invalid number of data bits\n"); - critical_exit(); - return UART_NOMODE; - } - /* store changed number of data bits in configuration */ - _uarts[uart].data = data_bits; - - /* set number of stop bits */ - #ifdef MCU_ESP32 - /* workaround for hardware bug when stop bits are set to 2-bit mode. */ - switch (stop_bits) { - case UART_STOP_BITS_1: _uarts[uart].regs->conf0.stop_bit_num = 1; - _uarts[uart].regs->rs485_conf.dl1_en = 0; - break; - case UART_STOP_BITS_2: _uarts[uart].regs->conf0.stop_bit_num = 1; - _uarts[uart].regs->rs485_conf.dl1_en = 1; - break; - default: LOG_TAG_ERROR("uart", "invalid number of stop bits\n"); - critical_exit(); - return UART_NOMODE; - } - #else - switch (stop_bits) { - case UART_STOP_BITS_1: _uarts[uart].regs->conf0.stop_bit_num = 1; break; - case UART_STOP_BITS_2: _uarts[uart].regs->conf0.stop_bit_num = 3; break; - default: LOG_TAG_ERROR("uart", "invalid number of stop bits\n"); - critical_exit(); - return UART_NOMODE; - } - #endif - - /* store changed number of stop bits in configuration */ - _uarts[uart].stop = stop_bits; - - /* set parity mode */ - switch (parity) { - case UART_PARITY_NONE: _uarts[uart].regs->conf0.parity_en = 0; - break; - case UART_PARITY_EVEN: _uarts[uart].regs->conf0.parity = 0; - _uarts[uart].regs->conf0.parity_en = 1; - break; - case UART_PARITY_ODD: _uarts[uart].regs->conf0.parity = 1; - _uarts[uart].regs->conf0.parity_en = 1; - break; - default: LOG_TAG_ERROR("uart", "invalid or unsupported parity mode\n"); - critical_exit(); - return UART_NOMODE; - } - /* store changed parity in configuration */ - _uarts[uart].parity = parity; - - critical_exit(); - return UART_OK; -} diff --git a/cpu/esp32/periph_cpu.c b/cpu/esp32/periph_cpu.c deleted file mode 100644 index 30c3c3088bee..000000000000 --- a/cpu/esp32/periph_cpu.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @{ - * - * @file - * @brief CPU specific definitions and functions for peripheral handling - * - * @author Gunar Schorcht - */ - -#define ENABLE_DEBUG 0 -#include "debug.h" - -#include "periph_cpu.h" diff --git a/cpu/esp32/startup.c b/cpu/esp32/startup.c index 95624152efb3..3eef6393d95c 100644 --- a/cpu/esp32/startup.c +++ b/cpu/esp32/startup.c @@ -293,13 +293,6 @@ static NORETURN void IRAM system_init (void) /* Disable the hold flag of all RTC GPIO pins */ RTCCNTL.hold_force.val = 0; - /* - * initialization of newlib, includes the ctors initialization and - * and the execution of stdio_init in _init of newlib_syscalls_default - */ - extern void __libc_init_array(void); - __libc_init_array(); - /* set log levels for SDK library outputs */ extern void esp_log_level_set(const char* tag, esp_log_level_t level); esp_log_level_set("wifi", LOG_DEBUG); diff --git a/cpu/esp32/syscalls.c b/cpu/esp32/syscalls.c index 267707e9ca84..fcbe69df1670 100644 --- a/cpu/esp32/syscalls.c +++ b/cpu/esp32/syscalls.c @@ -18,35 +18,15 @@ * @} */ -#define ENABLE_DEBUG (0) -#include "debug.h" - -#include -#include -#include -#include -#include -#include -#include -#include #include -#include "esp_common.h" -#include "cpu_conf.h" -#include "irq.h" +#include "esp/common_macros.h" #include "irq_arch.h" -#include "kernel_defines.h" -#include "log.h" -#include "mutex.h" -#include "rmutex.h" -#include "sched.h" +#include "periph_cpu.h" #include "periph/pm.h" - +#include "syscalls.h" #include "timex.h" -#include "esp_attr.h" -#include "esp/xtensa_ops.h" -#include "esp/common_macros.h" #include "rom/ets_sys.h" #include "rom/libc_stubs.h" #include "soc/rtc.h" @@ -55,231 +35,45 @@ #include "soc/timer_group_struct.h" #include "xtensa/xtensa_api.h" -#include "periph_cpu.h" -#include "syscalls.h" - #ifdef MODULE_ESP_IDF_HEAP -#include "heap/esp_heap_caps.h" -#include "heap/include/multi_heap.h" -#else -#include "malloc.h" +#include "esp_heap_caps.h" #endif -#define MHZ 1000000UL - -#ifndef MODULE_PTHREAD - -#define PTHREAD_CANCEL_DISABLE 1 -/* - * This is a dummy function to avoid undefined references when linking - * against newlib and module pthread is not used. - */ -int pthread_setcancelstate(int state, int *oldstate) -{ - if (oldstate) { - *oldstate = PTHREAD_CANCEL_DISABLE; - } - return 0; -} -#endif /* MODULE_PTHREAD*/ - -/** - * @name Locking functions - * - * Following function implements the lock mechanism in newlib. The only static - * mutex defined here is the _malloc_rmtx to avoid that memory management - * functions try to lock before RIOT's threads are running. All other mutexes - * are allocated dynamically. - */ - -static rmutex_t _malloc_rmtx = RMUTEX_INIT; - -void IRAM _lock_init(_lock_t *lock) -{ - CHECK_PARAM (sched_active_thread != 0); - CHECK_PARAM (lock != NULL); - CHECK_PARAM (*lock != ((_lock_t)&_malloc_rmtx)); - - mutex_t* mtx = malloc (sizeof(mutex_t)); - - if (mtx) { - memset (mtx, 0, sizeof(mutex_t)); - *lock = (_lock_t)mtx; - } -} - -void IRAM _lock_init_recursive(_lock_t *lock) -{ - CHECK_PARAM (sched_active_thread != 0); - CHECK_PARAM (lock != NULL); - CHECK_PARAM (*lock != ((_lock_t)&_malloc_rmtx)); - - rmutex_t* rmtx = malloc (sizeof(rmutex_t)); - - if (rmtx) { - memset (rmtx, 0, sizeof(rmutex_t)); - *lock = (_lock_t)rmtx; - } -} - -void IRAM _lock_close(_lock_t *lock) -{ - CHECK_PARAM (lock != NULL); - CHECK_PARAM (*lock != ((_lock_t)&_malloc_rmtx)); - - free ((void*)*lock); - *lock = 0; -} - -void IRAM _lock_close_recursive(_lock_t *lock) -{ - CHECK_PARAM (lock != NULL); - CHECK_PARAM (*lock != ((_lock_t)&_malloc_rmtx)); - - free ((void*)*lock); - *lock = 0; -} - -void IRAM _lock_acquire(_lock_t *lock) -{ - CHECK_PARAM (sched_active_thread != 0); - CHECK_PARAM (lock != NULL && *lock != 0); - - mutex_lock ((mutex_t*)*lock); -} - -void IRAM _lock_acquire_recursive(_lock_t *lock) -{ - CHECK_PARAM (sched_active_thread != 0); - CHECK_PARAM (lock != NULL && *lock != 0); - - rmutex_lock ((rmutex_t*)*lock); -} - -int IRAM _lock_try_acquire(_lock_t *lock) -{ - CHECK_PARAM_RET (sched_active_thread != 0, 0); - CHECK_PARAM_RET (lock != NULL && *lock != 0, 0); - - return rmutex_trylock ((rmutex_t*)*lock); -} - -int IRAM _lock_try_acquire_recursive(_lock_t *lock) -{ - CHECK_PARAM_RET (sched_active_thread != 0, 0); - CHECK_PARAM_RET (lock != NULL && *lock != 0, 0); - - return mutex_trylock ((mutex_t*)*lock); -} - -void IRAM _lock_release(_lock_t *lock) -{ - CHECK_PARAM (sched_active_thread != 0); - CHECK_PARAM (lock != NULL && *lock != 0); - - mutex_unlock ((mutex_t*)*lock); -} - -void IRAM _lock_release_recursive(_lock_t *lock) -{ - CHECK_PARAM (sched_active_thread != 0); - CHECK_PARAM (lock != NULL && *lock != 0); - - rmutex_unlock ((rmutex_t*)*lock); -} +#define ENABLE_DEBUG (0) +#include "debug.h" -/** - * @name Memory allocation functions - */ +#define MHZ 1000000UL #ifdef MODULE_ESP_IDF_HEAP -extern void *heap_caps_malloc_default( size_t size ); -extern void *heap_caps_realloc_default( void *ptr, size_t size ); - -void* IRAM_ATTR __wrap__malloc_r(struct _reent *r, size_t size) -{ - return heap_caps_malloc_default( size ); -} - -void IRAM_ATTR __wrap__free_r(struct _reent *r, void* ptr) -{ - heap_caps_free( ptr ); -} - -void* IRAM_ATTR __wrap__realloc_r(struct _reent *r, void* ptr, size_t size) -{ - return heap_caps_realloc_default( ptr, size ); -} - -void* IRAM_ATTR __wrap__calloc_r(struct _reent *r, size_t count, size_t size) +/* if module esp_idf_heap is used, this function has to be defined for ESP32 */ +unsigned int get_free_heap_size(void) { - void* result = heap_caps_malloc_default(count * size); - if (result) { - bzero(result, count * size); - } - return result; + return heap_caps_get_free_size(MALLOC_CAP_DEFAULT); } -unsigned int IRAM get_free_heap_size (void) -{ - return heap_caps_get_free_size( MALLOC_CAP_DEFAULT ); -} +/* alias for compatibility with espressif/wifi_libs */ +uint32_t esp_get_free_heap_size( void ) __attribute__((alias("get_free_heap_size"))); +/* this function is platform specific if module esp_idf_heap is used */ void heap_stats(void) { + size_t _free = 0; + size_t _alloc = 0; + multi_heap_info_t hinfo; heap_caps_get_info(&hinfo, MALLOC_CAP_DEFAULT); - size_t _free = hinfo.total_free_bytes; - size_t _alloc = hinfo.total_allocated_bytes; + _free = hinfo.total_free_bytes; + _alloc = hinfo.total_allocated_bytes; - printf("heap: %u (used %u free %u) [bytes]\n", - (unsigned)(_free + _alloc), (unsigned)_alloc, (unsigned)_free); -} - -#else /* MODULE_ESP_IDF_HEAP */ - -/* for compatibility with ESP-IDF heap functions */ -void* IRAM heap_caps_malloc( size_t size, uint32_t caps ) -{ - (void)caps; - return malloc(size); -} - -void* IRAM heap_caps_calloc( size_t n, size_t size, uint32_t caps) -{ - (void)caps; - return calloc(n, size); -} - -void* IRAM heap_caps_realloc( void *ptr, size_t size ) -{ - return realloc(ptr, size); -} - -extern uint8_t _eheap; /* end of heap (defined in esp32.common.ld) */ -extern uint8_t _sheap; /* start of heap (defined in esp32.common.ld) */ -extern uint8_t *heap_top; /* current top of heap as defined in newlib_syscalls_default */ - -unsigned int IRAM get_free_heap_size (void) -{ - struct mallinfo minfo = mallinfo(); - return &_eheap - &_sheap - minfo.uordblks; -} - -void heap_stats(void) -{ - printf("heap: %u (used %u, free %u) [bytes]\n", (unsigned)(&_eheap - &_sheap), - &_eheap - &_sheap - get_free_heap_size(), get_free_heap_size()); + ets_printf("heap: %u (used %u, free %u) [bytes]\n", + _alloc + _free, _alloc, _free); } #endif /* MODULE_ESP_IDF_HEAP */ -/* alias for compatibility with espressif/wifi_libs */ -uint32_t esp_get_free_heap_size( void ) __attribute__((alias("get_free_heap_size"))); - /** * @name Other system functions */ @@ -288,7 +82,7 @@ void _abort(void) { ets_printf("#! abort called: powering off\n"); pm_off(); - while(1); + while (1) { }; } void _exit_r(struct _reent *r, int status) @@ -296,19 +90,13 @@ void _exit_r(struct _reent *r, int status) _exit(status); } -struct _reent* __getreent(void) { - return _GLOBAL_REENT; -} - -static int _no_sys_func (struct _reent *r) +static int _no_sys_func(struct _reent *r) { DEBUG("%s: system function does not exist\n", __func__); r->_errno = ENOSYS; return -1; } -static struct _reent s_reent; - static struct syscall_stub_table s_stub_table = { .__getreent = &__getreent, @@ -360,42 +148,35 @@ static struct syscall_stub_table s_stub_table = #endif /* CONFIG_NEWLIB_NANO_FORMAT */ }; -void IRAM syscalls_init (void) +void IRAM syscalls_init_arch(void) { /* enable the system timer in us (TMG0 is enabled by default) */ TIMER_SYSTEM.config.divider = rtc_clk_apb_freq_get()/MHZ; TIMER_SYSTEM.config.autoreload = 0; TIMER_SYSTEM.config.enable = 1; + syscall_table_ptr_pro = &s_stub_table; syscall_table_ptr_app = &s_stub_table; - - _GLOBAL_REENT = &s_reent; - - environ = malloc(sizeof(char*)); - environ[0] = NULL; } -uint32_t system_get_time (void) +uint32_t system_get_time(void) { /* latch 64 bit timer value before read */ TIMER_SYSTEM.update = 0; - /* wait until instructions have been finished */ - __asm__ volatile ("isync"); + /* read the current timer value */ return TIMER_SYSTEM.cnt_low; } -uint32_t system_get_time_ms (void) +uint32_t system_get_time_ms(void) { return system_get_time_64() / USEC_PER_MSEC; } -uint64_t system_get_time_64 (void) +uint64_t system_get_time_64(void) { uint64_t ret; /* latch 64 bit timer value before read */ TIMER_SYSTEM.update = 0; - /* wait until instructions have been finished */ - __asm__ volatile ("isync"); /* read the current timer value */ ret = TIMER_SYSTEM.cnt_low; ret += ((uint64_t)TIMER_SYSTEM.cnt_high) << 32; @@ -411,7 +192,7 @@ static IRAM void system_wdt_int_handler(void *arg) system_wdt_feed(); } -void IRAM system_wdt_feed (void) +void IRAM system_wdt_feed(void) { DEBUG("%s\n", __func__); TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; /* disable write protection */ @@ -419,7 +200,7 @@ void IRAM system_wdt_feed (void) TIMERG0.wdt_wprotect=0; /* enable write protection */ } -void system_wdt_init (void) +void system_wdt_init(void) { /* disable boot watchdogs */ TIMERG0.wdt_config0.flashboot_mod_en = 0; @@ -456,7 +237,7 @@ void system_wdt_init (void) xt_ints_on(BIT(CPU_INUM_WDT)); } -void system_wdt_stop (void) +void system_wdt_stop(void) { xt_ints_off(BIT(CPU_INUM_WDT)); TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; /* disable write protection */ @@ -465,7 +246,7 @@ void system_wdt_stop (void) TIMERG0.wdt_wprotect = 0; /* enable write protection */ } -void system_wdt_start (void) +void system_wdt_start(void) { TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; /* disable write protection */ TIMERG0.wdt_config0.en = 1; /* disable MWDT */ @@ -473,18 +254,3 @@ void system_wdt_start (void) TIMERG0.wdt_wprotect = 0; /* enable write protection */ xt_ints_on(BIT(CPU_INUM_WDT)); } - -__attribute__((weak)) void -_system_prevent_memset_lto(void *const s, int c, const size_t n) -{ - (void) s; - (void) c; - (void) n; -} - -void *system_secure_memset(void *s, int c, size_t n) -{ - memset(s, c, n); - _system_prevent_memset_lto(s, c, n); - return s; -} diff --git a/cpu/esp32/thread_arch.c b/cpu/esp32/thread_arch.c deleted file mode 100644 index 517e208b8372..000000000000 --- a/cpu/esp32/thread_arch.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright (C) 2018 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp32 - * @{ - * - * @file - * @brief Implementation of the kernel's architecture dependent thread interface - * - * @author Gunar Schorcht - * - * @} - */ - -/* - * PLEASE NOTE: Some parts of the code are taken from the FreeRTOS port for - * Xtensa processors from Cadence Design Systems. These parts are marked - * accordingly. For these parts, the following license is valid: - * - * Copyright (c) 2003-2015 Cadence Design Systems, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#define ENABLE_DEBUG (0) -#include "debug.h" - -#include -#include - -#include "board.h" -#include "cpu.h" -#include "irq.h" -#include "log.h" -#include "thread.h" -#include "sched.h" - -#include "esp_common.h" -#include "irq_arch.h" -#include "syscalls.h" -#include "tools.h" - -#include "esp/xtensa_ops.h" -#include "rom/ets_sys.h" -#include "soc/dport_reg.h" -#include "xtensa/xtensa_context.h" - -/* User exception dispatcher when exiting */ -extern void _xt_user_exit(void); - -/* Switch context to the highest priority ready task without context save */ -extern void _frxt_dispatch(void); - -/* Set an flag indicating that a task switch is required on return from interrupt */ -extern void _frxt_setup_switch(void); - -/* Switch context to the highest priority ready task with context save */ -extern void vPortYield(void); -extern void vPortYieldFromInt(void); - -/* forward declarations */ -NORETURN void task_exit(void); - -char* thread_stack_init(thread_task_func_t task_func, void *arg, void *stack_start, int stack_size) -{ - /* Stack layout after task stack initialization - * - * +------------------------+ - * | | TOP - * | thread_control_block | - * stack_start + stack_size ==> | | top_of_stack+1 - * +------------------------+ - * top_of_stack ==> | | - * | XT_CP_SA | - * | (optional) | - * | ... | ... - * | cpstored | XT_CPSTORED - * top_of_stack + 1 - XT_CP_SIZE ==> | cpenable | XT_CPENABLE - * (cp_state) +------------------------+ - * | | - * | XT_STK_FRAME | - * | | XT_STK_... - * | a2 = arg | XT_STK_A2 - * | a1 = sp + XT_STK_FRMSZ | XT_STK_A1 - * | a0 = sched_task_exit | XT_STK_A0 - * | ps = PS_UM | PS_EXCM | XT_STK_PS - * | pc = task_func | XT_STK_PC - * sp = top_of_stack + 1 - XT_CP_SIZE ==> | exit = _xt_user_exit | XT_STK_EXIT - * - XT_STK_FRMSZ +------------------------+ - * | | - * | remaining stack space | - * | available for data | - * stack_start (preallocated var) ==> | | BOTTOM - * +------------------------+ - * - * Initialized stack frame represents the registers as set when the - * the task function would have been called. - * - * Registers in a called function - * - * pc - PC at the beginning in the function - * a0 - return address from the function (return address to caller) - * a1 - current stack pointer at the beginning in the function - * a2 - first argument of the function - */ - - /* stack is [stack_start+0 ... stack_start+stack_size-1] */ - uint8_t *top_of_stack; - uint8_t *sp; - - top_of_stack = (uint8_t*)((uint32_t)stack_start + stack_size - 1); - - /* BEGIN - code from FreeRTOS port for Xtensa from Cadence */ - - /* Create interrupt stack frame aligned to 16 byte boundary */ - sp = (uint8_t*)(((uint32_t)(top_of_stack + 1) - XT_STK_FRMSZ - XT_CP_SIZE) & ~0xf); - - /* Clear whole stack with a known value to assist debugging */ - #if !defined(DEVELHELP) && !defined(SCHED_TEST_STACK) - /* Unfortunately, this affects thread_measure_stack_free function */ - memset(stack_start, 0, stack_size); - #else - memset(sp, 0, XT_STK_FRMSZ + XT_CP_SIZE); - #endif - - /* ensure that stack is big enough */ - assert (sp > (uint8_t*)stack_start); - - XtExcFrame* exc_frame = (XtExcFrame*)sp; - - /* Explicitly initialize certain saved registers for call0 ABI */ - exc_frame->pc = (uint32_t)task_func; /* task entry point */ - exc_frame->a0 = (uint32_t)task_exit; /* task exit point*/ - exc_frame->a1 = (uint32_t)sp + XT_STK_FRMSZ; /* physical top of stack frame */ - exc_frame->exit = (uint32_t)_xt_user_exit; /* user exception exit dispatcher */ - - /* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */ - /* Also set entry point argument parameter. */ - #ifdef __XTENSA_CALL0_ABI__ - /* for CALL0 ABI set in parameter a2 to task argument */ - exc_frame->ps = PS_UM | PS_EXCM; - exc_frame->a2 = (uint32_t)arg; /* parameters for task_func */ - #else - /* for Windowed Register ABI set PS.CALLINC=01 to handle task entry as - call4 return address in a4 and parameter in a6 and */ - exc_frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC(1); - exc_frame->a4 = (uint32_t)task_exit; /* task exit point*/ - exc_frame->a6 = (uint32_t)arg; /* parameters for task_func */ - #endif - - #ifdef XT_USE_SWPRI - /* Set the initial virtual priority mask value to all 1's. */ - exc_frame->vpri = 0xFFFFFFFF; - #endif - - #if XCHAL_CP_NUM > 0 - /* Init the coprocessor save area (see xtensa_context.h) */ - /* No access to TCB here, so derive indirectly. Stack growth is top to bottom. */ - /* p = (uint32_t *) xMPUSettings->coproc_area; */ - - uint32_t *p; - - p = (uint32_t *)(((uint32_t)(top_of_stack + 1) - XT_CP_SIZE)); - p[0] = 0; - p[1] = 0; - p[2] = (((uint32_t) p) + 12 + XCHAL_TOTAL_SA_ALIGN - 1) & -XCHAL_TOTAL_SA_ALIGN; - #endif - - /* END - code from FreeRTOS port for Xtensa from Cadence */ - DEBUG("%s start=%p size=%d top=%p sp=%p free=%u\n", - __func__, stack_start, stack_size, top_of_stack, sp, sp-(uint8_t*)stack_start); - return (char*)sp; -} - -/** - * Context switches are realized using software interrupts since interrupt - * entry and exit functions are the only way to save and restore complete - * context including spilling the register windows to the stack - */ -void IRAM_ATTR thread_yield_isr(void* arg) -{ - /* clear the interrupt first */ - DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, 0); - /* set the context switch flag (indicates that context has to be switched - is switch on exit from interrupt in _frxt_int_exit */ - _frxt_setup_switch(); -} - -/** - * If we are already in an interrupt handler, the function simply sets the - * context switch flag, which indicates that the context has to be switched - * in the _frxt_int_exit function when exiting the interrupt. Otherwise, we - * will generate a software interrupt to force the context switch when - * terminating the software interrupt (see thread_yield_isr). - */ -void thread_yield_higher(void) -{ - /* reset hardware watchdog */ - system_wdt_feed(); - - /* yield next task */ - #if defined(ENABLE_DEBUG) && defined(DEVELHELP) - if (sched_active_thread) { - DEBUG("%u old task %u %s %u\n", system_get_time(), - sched_active_thread->pid, sched_active_thread->name, - sched_active_thread->sp - sched_active_thread-> stack_start); - } - #endif - - if (!irq_is_in()) { - /* generate the software interrupt to switch the context */ - DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, DPORT_CPU_INTR_FROM_CPU_0); - } - else { - /* set the context switch flag */ - _frxt_setup_switch(); - } - - #if defined(ENABLE_DEBUG) && defined(DEVELHELP) - if (sched_active_thread) { - DEBUG("%u new task %u %s %u\n", system_get_time(), - sched_active_thread->pid, sched_active_thread->name, - sched_active_thread->sp - sched_active_thread-> stack_start); - } - #endif - - /* - * Instruction fetch synchronize: Waits for all previously fetched load, - * store, cache, and special register write instructions that affect - * instruction fetch to be performed before fetching the next instruction. - */ - __asm__("isync"); - - return; -} - -void thread_stack_print(void) -{ - /* Print the current stack to stdout. */ - - #if defined(DEVELHELP) - volatile thread_t* task = thread_get(sched_active_pid); - if (task) { - - char* stack_top = task->stack_start + task->stack_size; - int size = stack_top - task->sp; - printf("Printing current stack of thread %" PRIkernel_pid "\n", thread_getpid()); - esp_hexdump((void*)(task->sp), size >> 2, 'w', 8); - } - #else - NOT_SUPPORTED(); - #endif -} - -void thread_print_stack(void) -{ - /* Prints human readable, ps-like thread information for debugging purposes. */ - /* because of Xtensa stack structure and call ABI, it is not possible to implement */ - NOT_YET_IMPLEMENTED(); - return; -} - -#ifdef DEVELHELP - -extern uint8_t port_IntStack; -extern uint8_t port_IntStackTop; - -void thread_isr_stack_init(void) -{ - /* code from thread.c, please see the copyright notice there */ - - /* assign each int of the stack the value of it's address */ - uintptr_t *stackmax = (uintptr_t *)&port_IntStackTop; - uintptr_t *stackp = (uintptr_t *)&port_IntStack; - - while (stackp < stackmax) { - *stackp = (uintptr_t) stackp; - stackp++; - } -} - -int thread_isr_stack_usage(void) -{ - return &port_IntStackTop - &port_IntStack - - thread_measure_stack_free((char*)&port_IntStack); -} - -void *thread_isr_stack_pointer(void) -{ - /* Get the current ISR stack pointer. */ - return &port_IntStackTop; -} - -void *thread_isr_stack_start(void) -{ - /* Get the start of the ISR stack. */ - return &port_IntStack; -} - -void thread_isr_stack_print(void) -{ - printf("Printing current ISR\n"); - esp_hexdump(&port_IntStack, &port_IntStackTop-&port_IntStack, 'w', 8); -} - -#else /* DEVELHELP */ - -void thread_isr_stack_init(void) {} - -#endif /* DEVELHELP */ - -static bool _initial_exit = true; - -/** - * The function is used on task exit to switch to the context to the next - * running task. It realizes only the second half of a complete context by - * simulating the exit from an interrupt handling where a context switch is - * forced. The old context is not saved here since it is no longer needed. - */ -NORETURN void task_exit(void) -{ - DEBUG("sched_task_exit: ending thread %" PRIkernel_pid "...\n", - sched_active_thread ? sched_active_thread->pid : KERNEL_PID_UNDEF); - - (void) irq_disable(); - - /* remove old task from scheduling if it is not already done */ - if (sched_active_thread) { - sched_threads[sched_active_pid] = NULL; - sched_num_threads--; - sched_set_status((thread_t *)sched_active_thread, STATUS_STOPPED); - sched_active_thread = NULL; - } - - /* determine the new running task */ - sched_run(); - - /* set the context switch flag (indicates that context has to be switched - is switch on exit from interrupt in _frxt_int_exit */ - _frxt_setup_switch(); - - /* set interrupt nesting level to the right value */ - irq_interrupt_nesting++; - - /* reset windowed registers */ - __asm__ volatile ("movi a2, 0\n" - "wsr a2, windowstart\n" - "wsr a2, windowbase\n" - "rsync\n"); - - /* exit from simulated interrupt to switch to the new context */ - __asm__ volatile ("call0 _frxt_int_exit"); - - /* should not be executed */ - UNREACHABLE(); -} - -NORETURN void cpu_switch_context_exit(void) -{ - DEBUG("%s\n", __func__); - - /* Switch context to the highest priority ready task without context save */ - if (_initial_exit) { - _initial_exit = false; - __asm__ volatile ("call0 _frxt_dispatch"); - } - else { - task_exit(); - } - UNREACHABLE(); -} diff --git a/cpu/esp32/vendor/README.md b/cpu/esp32/vendor/README.md index 24789a06424c..38a4829a76d9 100644 --- a/cpu/esp32/vendor/README.md +++ b/cpu/esp32/vendor/README.md @@ -1,9 +1,5 @@ The subdirectories here contain third-party software components used by the RIOT port for ESP32. -### esp - -The files that are part of [esp-open-rtos](https://github.com/SuperHouse/esp-open-rtos.git). The files in this directory are under the copyright of their respective owners. Please note the copyright notice in these files. All of these files are BSD Licensed as described in the file [LICENSE](https://github.com/SuperHouse/esp-open-rtos/blob/master/LICENSE). - ### esp-idf The files in this directory and all subdirectories are from the Espressif IoT Development Framework[ESP-IDF](https://github.com/espressif/esp-idf.git), the official development framework for ESP32. All of these files are copyright of Espressif Systems (Shanghai) PTE LTD or their respective owners and licensed under the Apache License, Version 2.0. Please refer the copyright notice in these files for details. diff --git a/cpu/esp32/vendor/esp/common_macros.h b/cpu/esp32/vendor/esp/common_macros.h deleted file mode 100644 index 9189f9e60e62..000000000000 --- a/cpu/esp32/vendor/esp/common_macros.h +++ /dev/null @@ -1,141 +0,0 @@ -/* Some common compiler macros - * - * Not esp8266-specific. - * - * Part of esp-open-rtos - * Copyright (C) 2015 Superhouse Automation Pty Ltd - * BSD Licensed as described in the file LICENSE - */ - -/* -Copyright (c) 2015, SuperHouse Automation Pty Ltd -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef COMMON_MACROS_H -#define COMMON_MACROS_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define UNUSED __attributed((unused)) - -/* These macros convert values to/from bitfields specified by *_M and *_S (mask - * and shift) constants. Used primarily with ESP8266 register access. - */ - -#define VAL2FIELD(fieldname, value) ((value) << fieldname##_S) -#define FIELD2VAL(fieldname, regbits) (((regbits) >> fieldname##_S) & fieldname##_M) - -#define FIELD_MASK(fieldname) (fieldname##_M << fieldname##_S) -#define SET_FIELD(regbits, fieldname, value) (((regbits) & ~FIELD_MASK(fieldname)) | VAL2FIELD(fieldname, value)) - -/* VAL2FIELD/SET_FIELD do not normally check to make sure that the passed value - * will fit in the specified field (without clobbering other bits). This makes - * them faster and is usually fine. If you do need to make sure that the value - * will not overflow the field, use VAL2FIELD_M or SET_FIELD_M (which will - * first mask the supplied value to only the allowed number of bits) instead. - */ -#define VAL2FIELD_M(fieldname, value) (((value) & fieldname##_M) << fieldname##_S) -#define SET_FIELD_M(regbits, fieldname, value) (((regbits) & ~FIELD_MASK(fieldname)) | VAL2FIELD_M(fieldname, value)) - -/* Set bits in reg with specified mask. - */ -#define SET_MASK_BITS(reg, mask) (reg) |= (mask) - -/* Clear bits in reg with specified mask - */ -#define CLEAR_MASK_BITS(reg, mask) (reg) &= ~(mask) - -/* Use the IRAM macro to place functions into Instruction RAM (IRAM) - instead of flash (aka irom). - - (This is the opposite to the Espressif SDK, where functions default - to being placed in IRAM but the ICACHE_FLASH_ATTR attribute will - place them in flash.) - - Use the IRAM attribute for functions which are called when the - flash may not be available (for example during NMI exceptions), or - for functions which are called very frequently and need high - performance. - - Usage example: - - void IRAM high_performance_function(void) - { - // do important thing here - } - - Bear in mind IRAM is limited (32KB), compared to up to 1MB of flash. -*/ -#define IRAM __attribute__((section(".iram1.text"))) - -/* Use the RAM macro to place constant data (rodata) into RAM (data - RAM) instead of the default placement in flash. This is useful for - constant data which needs high performance access. - - Usage example: - - const RAM uint8_t constants[] = { 1, 2, 3, 7 }; - - When placing string literals in RAM, they need to be declared with - the type "const char[]" not "const char *" - - Usage example: - - const RAM char hello_world[] = "Hello World"; -*/ -#define RAM __attribute__((section(".data"))) - -/* Use the IRAM_DATA macro to place data into Instruction RAM (IRAM) - instead of the default of flash (for constant data) or data RAM - (for non-constant data). - - This may be useful to free up data RAM. However all data read from - any instruction space (either IRAM or Flash) must be 32-bit aligned - word reads. Reading unaligned data stored with IRAM_DATA will be - slower than reading data stored in RAM. You can't perform unaligned - writes to IRAM. -*/ -#define IRAM_DATA __attribute__((section(".iram1.data"))) - -/* Use the IROM macro to store constant values in IROM flash. In - esp-open-rtos this is already the default location for most constant - data (rodata), so you don't need this attribute in 99% of cases. - - The exceptions are to mark data in the core & freertos libraries, - where the default for constant data storage is RAM. - - (Unlike the Espressif SDK you don't need to use an attribute like - ICACHE_FLASH_ATTR for functions, they go into flash by default.) - - Important to note: IROM flash is accessed via 32-bit word aligned - reads. esp-open-rtos does some magic to "fix" unaligned reads, but - performance is reduced. -*/ -#ifdef __cplusplus - #define IROM __attribute__((section(".irom0.text"))) - #define IROM_LIT __attribute__((section(".irom0.literal"))) -#else - #define IROM __attribute__((section(".irom0.text"))) - #define IROM_LIT __attribute__((section(".irom0.literal"))) const -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* COMMON_MACROS_H */ diff --git a/cpu/esp8266/Makefile b/cpu/esp8266/Makefile index ebb63f918f78..a332efe22866 100644 --- a/cpu/esp8266/Makefile +++ b/cpu/esp8266/Makefile @@ -8,10 +8,6 @@ DIRS += periph DIRS += sdk DIRS += vendor -ifneq (, $(filter esp_wifi, $(USEMODULE))) - DIRS += esp-wifi -endif - INCLUDES += -I$(ESP8266_RTOS_SDK_DIR)/components/esp8266/include/internal include $(RIOTBASE)/Makefile.base diff --git a/cpu/esp8266/Makefile.dep b/cpu/esp8266/Makefile.dep index 88bfeb5923ff..1ec56a936a51 100644 --- a/cpu/esp8266/Makefile.dep +++ b/cpu/esp8266/Makefile.dep @@ -1,15 +1,8 @@ # additional modules dependencies -ifneq (, $(filter esp_spiffs, $(USEMODULE))) - export SPIFFS_STD_OPTION = -std=c99 - USEMODULE += spiffs - USEMODULE += vfs -endif - -ifneq (, $(filter esp_wifi, $(USEMODULE))) - USEMODULE += netdev_eth -endif +include $(RIOTCPU)/esp_common/Makefile.dep -ifneq (,$(filter log_color,$(USEMODULE))) - USEMODULE += esp_log_colored +ifneq (,$(filter periph_i2c,$(USEMODULE))) + USEMODULE += esp_i2c_sw + USEMODULE += periph_i2c_sw endif diff --git a/cpu/esp8266/Makefile.features b/cpu/esp8266/Makefile.features index 28368f0f7ba5..adba4e110fe8 100644 --- a/cpu/esp8266/Makefile.features +++ b/cpu/esp8266/Makefile.features @@ -1,10 +1,5 @@ # MCU defined features that are provided independent on board definitions -FEATURES_PROVIDED += arch_32bit +include $(RIOTCPU)/esp_common/Makefile.features + FEATURES_PROVIDED += arch_esp8266 -FEATURES_PROVIDED += cpp -FEATURES_PROVIDED += periph_cpuid -FEATURES_PROVIDED += periph_hwrng -FEATURES_PROVIDED += periph_pm -FEATURES_PROVIDED += periph_timer -FEATURES_PROVIDED += ssp diff --git a/cpu/esp8266/Makefile.include b/cpu/esp8266/Makefile.include index ecf4b0d864f4..ddfad8187b75 100644 --- a/cpu/esp8266/Makefile.include +++ b/cpu/esp8266/Makefile.include @@ -1,114 +1,46 @@ # check some environment variables first - ifndef ESP8266_RTOS_SDK_DIR - $(info ESP8266_RTOS_SDK_DIR should be defined as /path/to/sdk directory) - $(info ESP8266_RTOS_SDK_DIR is set by default to /opt/esp/ESP8266-RTOS-SDK) - export ESP8266_RTOS_SDK_DIR=/opt/esp/ESP8266-RTOS-SDK -endif - -# Options to control the compilation - -ifeq ($(ENABLE_GDB), 1) - USEMODULE += esp_gdb -endif - -ifeq ($(ENABLE_GDBSTUB), 1) - USEMODULE += esp_gdbstub -endif - -# SPECIAL module dependencies -# cannot be done in Makefile.dep since Makefile.dep is included too late - -ifneq (,$(filter netdev_default gnrc_netdev_default,$(USEMODULE))) - ifneq (,$(filter lwip,$(USEMODULE))) - # for lwip, use esp_wifi as default netdev if no other netdev is enabled - USEMODULE += esp_wifi - else - # otherwise use esp_now as default netdev if no other netdev is enabled - ifeq (,$(filter esp_wifi esp_eth,$(USEMODULE))) - USEMODULE += esp_now - endif - endif -endif - -ifneq (, $(filter esp_wifi, $(USEMODULE))) - $(eval GNRC_NETIF_NUMOF=$(shell echo $$(($(GNRC_NETIF_NUMOF)+1)))) - USEMODULE += esp_wifi_any -endif - -ifneq (, $(filter esp_now, $(USEMODULE))) - $(eval GNRC_NETIF_NUMOF=$(shell echo $$(($(GNRC_NETIF_NUMOF)+1)))) - USEMODULE += esp_wifi_any + $(info ESP8266_RTOS_SDK_DIR should be defined as /path/to/sdk directory) + $(info ESP8266_RTOS_SDK_DIR is set by default to /opt/esp/ESP8266-RTOS-SDK) + export ESP8266_RTOS_SDK_DIR=/opt/esp/ESP8266-RTOS-SDK endif -ifneq (, $(filter esp_wifi_any, $(USEMODULE))) - CFLAGS += -DSCHED_PRIO_LEVELS=32 - USEMODULE += netopt - USEMODULE += xtimer -endif +ESP_SDK_DIR = $(ESP8266_RTOS_SDK_DIR) -ifneq (, $(filter esp_gdbstub, $(USEMODULE))) - USEMODULE += esp_gdb -endif +# With the '-Os' option, char arrays have not to be 32-bit word aligned. This +# leads to an alignment exception when the address of a char array is assigned +# to an 'uint32_t' pointer and the pointer is used for the access. +CFLAGS_OPT ?= -O2 -ifneq (, $(filter spiffs, $(USEMODULE))) - export RIOT_TEST_TIMEOUT = 200 -endif +# ESP8266 specific flashing options +FLASH_CHIP = esp8266 +FLASH_OPTS = --version 3 +FLASH_MODE = dout # DO NOT CHANGE, ESP8266/ESP8285 modules only work with dout +FLASH_FREQ = 26m # DO NOT CHANGE +FLASH_SIZE ?= 1 +BOOTLOADER_POS = 0x0000 -ifneq (, $(filter littlefs, $(USEMODULE))) - export RIOT_TEST_TIMEOUT = 200 -endif - -ifneq (,$(filter log_color,$(USEMODULE))) - USEMODULE += esp_log_colored -endif - -ifneq (,$(filter 4 5,$(LOG_LEVEL))) - USEMODULE += esp_log_startup -endif +include $(RIOTCPU)/esp_common/Makefile.include # regular Makefile -export TARGET_ARCH ?= xtensa-esp8266-elf +TARGET_ARCH ?= xtensa-esp8266-elf -# ESP8266 pseudomodules -PSEUDOMODULES += esp_gdb -PSEUDOMODULES += esp_log_colored -PSEUDOMODULES += esp_log_tagged -PSEUDOMODULES += esp_log_startup -PSEUDOMODULES += esp_qemu PSEUDOMODULES += esp_sw_timer -PSEUDOMODULES += esp_spiffs -PSEUDOMODULES += esp_wifi_any -USEMODULE += esp_common -USEMODULE += esp_freertos -USEMODULE += esp_idf USEMODULE += esp_idf_esp8266 USEMODULE += esp_idf_nvs_flash USEMODULE += esp_idf_spi_flash USEMODULE += esp_idf_util USEMODULE += esp_idf_wpa_supplicant_crypto USEMODULE += esp_sdk -USEMODULE += log USEMODULE += mtd USEMODULE += newlib -USEMODULE += newlib_syscalls_default -USEMODULE += periph USEMODULE += periph_common -USEMODULE += periph_hrng -USEMODULE += periph_flash -USEMODULE += periph_uart USEMODULE += ps -USEMODULE += random -USEMODULE += stdio_uart -USEMODULE += xtensa -INCLUDES += -I$(RIOTBOARD)/common/$(CPU)/include -INCLUDES += -I$(RIOTCPU)/esp_common/vendor/ INCLUDES += -I$(RIOTCPU)/$(CPU) INCLUDES += -I$(RIOTCPU)/$(CPU)/include -INCLUDES += -I$(RIOTCPU)/$(CPU)/include/freertos INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/ INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/bootloader_support/include @@ -125,135 +57,23 @@ INCLUDES += -I$(ESP8266_RTOS_SDK_DIR)/components/heap/port/esp8266/include INCLUDES += -I$(ESP8266_RTOS_SDK_DIR)/components/nvs_flash/include INCLUDES += -I$(ESP8266_RTOS_SDK_DIR)/components/spi_flash/include -CFLAGS += -D__ESP_FILE__=__FILE__ -CFLAGS += -Wno-unused-parameter -Wformat=0 -CFLAGS += -mlongcalls -mtext-section-literals -fstrict-volatile-bitfields -CFLAGS += -fdata-sections -ffunction-sections -fzero-initialized-in-bss - -OPTIONAL_CFLAGS_BLACKLIST += -fdiagnostics-color -OPTIONAL_CFLAGS_BLACKLIST += -Wformat-overflow -OPTIONAL_CFLAGS_BLACKLIST += -Wformat-truncation -OPTIONAL_CFLAGS_BLACKLIST += -gz +CFLAGS += -D__ESP_FILE__=__FILE__ -ASFLAGS += --longcalls --text-section-literals - -# thin archives trigger a reboot loop - see #12258, #12035, #12346 -ARFLAGS = rcs - -ifneq (,$(filter lwip,$(USEMODULE))) - # The threads for handling the ESP hardware have the priorities from 2 to 4. - # The priority of lwIP TCPIP thread should be lower than these priorities. - CFLAGS += -DTCPIP_THREAD_PRIO=5 +ifneq (,$(filter esp_gdbstub,$(USEMODULE))) + GDBSTUB_DIR ?= $(RIOTCPU)/$(CPU)/vendor/esp-gdbstub + CFLAGS += -DGDBSTUB_BREAK_ON_INIT=1 + INCLUDES += -I$(GDBSTUB_DIR) endif -ifneq (, $(filter esp_gdbstub, $(USEMODULE))) - GDBSTUB_DIR ?= $(RIOTCPU)/$(CPU)/vendor/esp-gdbstub - CFLAGS += -DGDBSTUB_BREAK_ON_INIT=1 - INCLUDES += -I$(GDBSTUB_DIR) -endif - -ifneq (, $(filter esp_gdb, $(USEMODULE))) - CFLAGS_OPT ?= -Og -ggdb -g3 -else - # TODO should be -Os - # With -Os char arrays have not to be 32-bit word aligned. This leads to - # an alignment exception when the address of an char array is assigned to - # an uint32_t pointer and the pointer is used for the access. - CFLAGS_OPT ?= -O2 -endif - -CFLAGS += $(CFLAGS_OPT) - -ifeq ($(QEMU), 1) - USEMODULE += esp_qemu -endif - -ifeq ($(FLASH_MODE), qio) - CFLAGS += -DFLASH_MODE_QIO -endif - -ifeq ($(FLASH_MODE), qout) - CFLAGS += -DFLASH_MODE_QOUT -endif - -LINKFLAGS += -L$(ESP8266_RTOS_SDK_DIR)/components/esp8266/lib -LINKFLAGS += $(CFLAGS_OPT) - -BASELIBS += -lc -lgcc -lwpa -lcore -lnet80211 -lphy -lpp -lhal -lstdc++ +BASELIBS += -lgcc -lwpa -lcore -lnet80211 -lphy -lpp -lstdc++ ifneq (, $(filter esp_now, $(USEMODULE))) - BASELIBS += -lespnow + BASELIBS += -lespnow endif -LINKFLAGS += -u _malloc_r -LINKFLAGS += -nostdlib -Wl,-gc-sections -Wl,-static # -Wl,--print-gc-sections - LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp8266.rom.ld LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp8266.riot-os.ld LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp8266.peripherals.ld LINKFLAGS += -Wl,-wrap=pp_attach LINKFLAGS += -Wl,-wrap=pm_attach - -ifneq (, $(filter esp_idf_heap, $(USEMODULE))) - LINKFLAGS += -Wl,-wrap=_malloc_r - LINKFLAGS += -Wl,-wrap=_calloc_r - LINKFLAGS += -Wl,-wrap=_free_r - LINKFLAGS += -Wl,-wrap=_realloc_r -endif - -# The ELFFILE is the base one used for flashing -FLASHFILE ?= $(ELFFILE) - -# configure preflasher to convert .elf to .bin before flashing -FLASH_MODE = dout # FIX configuration, DO NOT CHANGE -FLASH_FREQ = 26m # FIX configuration, DO NOT CHANGE -FLASH_SIZE ?= 1MB -FLASHDEPS += preflash - -PREFLASHER ?= $(RIOTTOOLS)/esptool/esptool.py -PREFFLAGS = --chip esp8266 elf2image -PREFFLAGS += --flash_mode $(FLASH_MODE) --flash_size $(FLASH_SIZE) -PREFFLAGS += --flash_freq $(FLASH_FREQ) --version 3 -PREFFLAGS += -o $(FLASHFILE).bin $(FLASHFILE); -PREFFLAGS += printf "\n" > $(BINDIR)/partitions.csv; -PREFFLAGS += printf "nvs, data, nvs, 0x9000, 0x6000\n" >> $(BINDIR)/partitions.csv; -PREFFLAGS += printf "phy_init, data, phy, 0xf000, 0x1000\n" >> $(BINDIR)/partitions.csv; -PREFFLAGS += printf "factory, app, factory, 0x10000, " >> $(BINDIR)/partitions.csv; -PREFFLAGS += ls -l $(FLASHFILE).bin | awk '{ print $$5 }' >> $(BINDIR)/partitions.csv; - -PREFFLAGS += python $(RIOTCPU)/$(CPU)/vendor/esp-idf/partition_table/gen_esp32part.py -PREFFLAGS += --verify $(BINDIR)/partitions.csv $(BINDIR)/partitions.bin - -ifneq (,$(filter esp_log_colored,$(USEMODULE))) - BOOTLOADER_COLOR = _colors -endif - -ifneq (,$(filter esp_log_startup,$(USEMODULE))) - BOOTLOADER_INFO = _info -endif - -BOOTLOADER_BIN = bootloader$(BOOTLOADER_COLOR)$(BOOTLOADER_INFO).bin - -ifneq (, $(filter esp_qemu, $(USEMODULE))) - FLASHER = dd - FFLAGS += if=/dev/zero bs=1M count=1 | tr "\\000" "\\377" > tmp.bin && - FFLAGS += cat $(RIOTCPU)/$(CPU)/bin/$(BOOTLOADER_BIN) tmp.bin | - FFLAGS += head -c $$((0x8000)) | - FFLAGS += cat - $(BINDIR)/partitions.bin tmp.bin | - FFLAGS += head -c $$((0x10000)) | - FFLAGS += cat - $(FLASHFILE).bin tmp.bin | - FFLAGS += head -c $$((0xfc000)) | - FFLAGS += cat - $(RIOTCPU)/$(CPU)/bin/esp_init_data_default.bin tmp.bin | - FFLAGS += head -c $$((0x100000)) > $(BINDIR)/esp8266flash.bin && rm tmp.bin -else - export PROGRAMMER_SPEED ?= 460800 - FLASHER = $(RIOTBASE)/dist/tools/esptool/esptool.py - FFLAGS += --chip esp8266 --port $(PROG_DEV) --baud $(PROGRAMMER_SPEED) - FFLAGS += --before default_reset write_flash -z - FFLAGS += --flash_size detect - FFLAGS += --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) - FFLAGS += 0x0000 $(RIOTCPU)/$(CPU)/bin/$(BOOTLOADER_BIN) - FFLAGS += 0x8000 $(BINDIR)/partitions.bin - FFLAGS += 0x10000 $(FLASHFILE).bin -endif diff --git a/cpu/esp8266/esp-wifi/Makefile b/cpu/esp8266/esp-wifi/Makefile deleted file mode 100644 index 1b6125f2d9f5..000000000000 --- a/cpu/esp8266/esp-wifi/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -MODULE=esp_wifi - -# we have to do it in that way to avoid that pkg/lwip is found first -CFLAGS += -I$(ESP8266_RTOS_SDK_DIR)/components/lwip/lwip/src/include -CFLAGS += -I$(ESP8266_RTOS_SDK_DIR)/components/lwip/port/esp8266/include/ - -include $(RIOTBASE)/Makefile.base diff --git a/cpu/esp8266/freertos/portable.c b/cpu/esp8266/freertos/portable.c index 0bbfa4326e29..2dba1a85ed39 100644 --- a/cpu/esp8266/freertos/portable.c +++ b/cpu/esp8266/freertos/portable.c @@ -13,30 +13,12 @@ #define ENABLE_DEBUG (0) #include "debug.h" -#include - -#include "esp_common.h" -#include "log.h" -#ifdef MCU_ESP8266 #include "esp_attr.h" #include "irq.h" #include "rom/ets_sys.h" -#endif #include "freertos/FreeRTOS.h" -uint32_t xPortGetTickRateHz(void) { - return MSEC_PER_SEC / portTICK_PERIOD_MS; -} - -BaseType_t xPortInIsrContext(void) -{ - /* is working on single core in that way */ - return irq_is_in(); -} - -#ifdef MCU_ESP8266 - unsigned _xt_tick_divisor = 0; /* cached number of cycles per tick */ extern void vTaskEnterCritical( portMUX_TYPE *mux ); @@ -67,9 +49,7 @@ void IRAM_ATTR vPortETSIntrUnlock(void) /* source: /path/to/esp8266-rtos-sdk/components/freertos/port/esp8266/port.c */ void ResetCcountVal(unsigned int cnt_val) { - asm volatile("wsr a2, ccount"); + __asm__ volatile("wsr a2, ccount"); } -#endif /* MCU_ESP8266 */ - #endif /* DOXYGEN */ diff --git a/cpu/esp8266/include/gpio_arch.h b/cpu/esp8266/include/gpio_arch.h index ece90ae81a7e..16cf09d70207 100644 --- a/cpu/esp8266/include/gpio_arch.h +++ b/cpu/esp8266/include/gpio_arch.h @@ -20,11 +20,7 @@ #ifndef GPIO_ARCH_H #define GPIO_ARCH_H -#ifdef MCU_ESP32 -#include "periph/gpio.h" -#include "soc/io_mux_reg.h" -#include "soc/gpio_sig_map.h" -#endif /* MCU_ESP32 */ +#include "gpio_arch_common.h" #ifndef DOXYGEN @@ -32,108 +28,11 @@ extern "C" { #endif -/** Definitions for source code compatibility with ESP-IDF */ -#define GPIO_MODE_INPUT GPIO_IN -#define GPIO_MODE_OUTPUT GPIO_OUT -#define GPIO_MODE_INPUT_OUTPUT GPIO_IN_OUT - -/** Definition of possible GPIO usage types (for internal use only) */ -typedef enum -{ - _GPIO = 0, /**< pin used as standard GPIO */ -#ifdef MCU_ESP32 - _ADC, /**< pin used as ADC input */ - _CAN, /**< pin used as CAN signal */ - _DAC, /**< pin used as DAC output */ - _EMAC, /**< pin used as EMAC signal */ -#endif /* MCU_ESP32 */ - _I2C, /**< pin used as I2C signal */ - _PWM, /**< pin used as PWM output */ - _SPI, /**< pin used as SPI interface */ - _SPIF, /**< pin used as SPI flash interface */ - _UART, /**< pin used as UART interface */ - _NOT_EXIST /**< pin cannot be used at all */ -} gpio_pin_usage_t; - - -#ifdef MCU_ESP32 - -/** Table of GPIO to IOMUX register mappings */ -extern const uint32_t _gpio_to_iomux_reg[]; -#define GPIO_PIN_MUX_REG _gpio_to_iomux_reg - -#else /* MCU_ESP32 */ - /** Map of GPIO pin numbers to IOMUX pin numbers */ extern const uint8_t _gpio_to_iomux[]; /** Map of IOMUX pin numbers to GPIO pin numbers */ extern const uint8_t _iomux_to_gpio[]; -#endif /* MCU_ESP32 */ - -/** - * @brief Set the usage type of the pin - * @param pin GPIO pin - * @param usage GPIO pin usage type - * @return 0 on success - * -1 on error - */ -int gpio_set_pin_usage(gpio_t pin, gpio_pin_usage_t usage); - -/** - * @brief Get the usage type of the pin - * @param pin GPIO pin - * @return GPIO pin usage type on success - * _NOT_EXIST on error - */ -gpio_pin_usage_t gpio_get_pin_usage(gpio_t pin); - -/** - * @brief Get the usage type of the pin as string - * @param pin GPIO pin - * @return GPIO pin usage type string on success - * _NOT_EXIST on error - */ -const char* gpio_get_pin_usage_str(gpio_t pin); - -#ifdef MCU_ESP32 -/** - * @brief Disable the pullup of the pin - */ -void gpio_pullup_dis (gpio_t pin); - -/** - * @brief Returns the RTCIO pin number or -1 if the pin is not an RTCIO pin - */ -int8_t gpio_is_rtcio (gpio_t pin); - -/** - * @brief Configure sleep mode for an GPIO pin if the pin is an RTCIO pin - * @param pin GPIO pin - * @param mode active in sleep mode if true - * @param input as input if true, as output otherwise - * @return 0 on success - * @return -1 on invalid pin - */ -int gpio_config_sleep_mode (gpio_t pin, bool sleep_mode, bool input); - -/** - * @brief GPIO set direction init the pin calling gpio_init - * @param pin GPIO pin - * @param mode active in sleep mode if true - * @return 0 on success - * -1 on invalid argument - */ -int gpio_set_direction(gpio_t pin, gpio_mode_t mode); - -/** - * @brief extern declaration of ROM functions to avoid compilation problems - */ -void gpio_matrix_in (uint32_t gpio, uint32_t signal_idx, bool inv); -void gpio_matrix_out(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv); - -#endif /* MCU_ESP32 */ - #ifdef __cplusplus } #endif diff --git a/cpu/esp8266/include/irq_arch.h b/cpu/esp8266/include/irq_arch.h index 46626a081811..f6ef6533e954 100644 --- a/cpu/esp8266/include/irq_arch.h +++ b/cpu/esp8266/include/irq_arch.h @@ -21,52 +21,12 @@ #ifndef IRQ_ARCH_H #define IRQ_ARCH_H -#include "irq.h" -#include "sched.h" -#include "thread.h" +#include "irq_arch_common.h" #ifdef __cplusplus extern "C" { #endif -/** - * @brief Indicates the interrupt nesting depth - * - * The variable is increment on entry into and decremented on exit from an ISR. - */ -extern uint32_t irq_interrupt_nesting; - -/** - * @name Macros to enter and exit an ISR - * - * Since all the stuff is done in `_frxt_int_enter` and `_frxt_int_exit`, these - * macros are doing nothing and are kept only for source code compatibility. - * - * @{ - */ -#define irq_isr_enter() -#define irq_isr_exit() -/** @} */ - -/** - * @name Macros to enter and exit a critical region - * - * @note since they use a local variable they can be used only in same function - * - * @{ - */ -#define critical_enter() int _irq_state = irq_disable() -#define critical_exit() irq_restore(_irq_state) -/** @} */ - -/** - * @name Macros to enter and exit a critical region with state variable - * @{ - */ -#define critical_enter_var(m) m = irq_disable() -#define critical_exit_var(m) irq_restore(m) -/** @} */ - /** * @name Software interrupt types * diff --git a/cpu/esp8266/include/periph_cpu.h b/cpu/esp8266/include/periph_cpu.h index 461f043efe89..2361cb65107d 100644 --- a/cpu/esp8266/include/periph_cpu.h +++ b/cpu/esp8266/include/periph_cpu.h @@ -206,6 +206,17 @@ typedef struct { /** @} */ +/** + * @name RNG configuration + * @{ + */ + +/** + * @brief The address of the register for accessing the hardware RNG. + */ +#define RNG_DATA_REG_ADDR (0x3ff20e44) +/** @} */ + /** * @name SPI configuration * diff --git a/cpu/esp8266/include/sdk_conf.h b/cpu/esp8266/include/sdk_conf.h index 67f8954e2290..3d40a993479a 100644 --- a/cpu/esp8266/include/sdk_conf.h +++ b/cpu/esp8266/include/sdk_conf.h @@ -76,7 +76,6 @@ extern "C" { #define CONFIG_SCAN_AP_MAX (32) #define CONFIG_USING_NEW_ETS_VPRINTF -#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF #ifdef __cplusplus } diff --git a/cpu/esp8266/include/stdio.h b/cpu/esp8266/include/stdio.h deleted file mode 100644 index 4fc9320acf48..000000000000 --- a/cpu/esp8266/include/stdio.h +++ /dev/null @@ -1,748 +0,0 @@ -/** - * This file is a modification of the original file to overwrite the *putchar* - * and *getchar* macros in the case the *uart_stdio* module is used. If the - * *uart_stdio* module is used, *putchar* and *getchar* are redirections to - * according *uart_stdio_* functions. - */ - -/* - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * @(#)stdio.h 5.3 (Berkeley) 3/15/86 - */ - -/* - * NB: to fit things in six character monocase externals, the - * stdio code uses the prefix `__s' for stdio objects, typically - * followed by a three-character attempt at a mnemonic. - */ - -#ifndef STDIO_H -#define STDIO_H - -#ifndef DOXYGEN - -#ifdef __cplusplus -extern "C" { -#endif - -#include "_ansi.h" - -#define _FSTDIO /* ``function stdio'' */ - -#define __need_size_t -#define __need_NULL -#include -#include - -#define __need___va_list -#include - -/* - * defines __FILE, _fpos_t. - * They must be defined there because struct _reent needs them (and we don't - * want reent.h to include this file. - */ - -#include -#include - -_BEGIN_STD_C - -typedef __FILE FILE; - -#ifdef __CYGWIN__ -typedef _fpos64_t fpos_t; -#else -typedef _fpos_t fpos_t; -#ifdef __LARGE64_FILES -typedef _fpos64_t fpos64_t; -#endif -#endif /* !__CYGWIN__ */ - -#include - -#define __SLBF 0x0001 /* line buffered */ -#define __SNBF 0x0002 /* unbuffered */ -#define __SRD 0x0004 /* OK to read */ -#define __SWR 0x0008 /* OK to write */ - /* RD and WR are never simultaneously asserted */ -#define __SRW 0x0010 /* open for reading & writing */ -#define __SEOF 0x0020 /* found EOF */ -#define __SERR 0x0040 /* found error */ -#define __SMBF 0x0080 /* _buf is from malloc */ -#define __SAPP 0x0100 /* fdopen()ed in append mode - so must write to end */ -#define __SSTR 0x0200 /* this is an sprintf/snprintf string */ -#define __SOPT 0x0400 /* do fseek() optimisation */ -#define __SNPT 0x0800 /* do not do fseek() optimisation */ -#define __SOFF 0x1000 /* set iff _offset is in fact correct */ -#define __SORD 0x2000 /* true => stream orientation (byte/wide) decided */ -#if defined(__CYGWIN__) -#define __SCLE 0x4000 /* convert line endings CR/LF <-> NL */ -#endif -#define __SL64 0x8000 /* is 64-bit offset large file */ - -/* _flags2 flags */ -#define __SNLK 0x0001 /* stdio functions do not lock streams themselves */ -#define __SWID 0x2000 /* true => stream orientation wide, false => byte, only valid if __SORD in _flags is true */ - -/* - * The following three definitions are for ANSI C, which took them - * from System V, which stupidly took internal interface macros and - * made them official arguments to setvbuf(), without renaming them. - * Hence, these ugly _IOxxx names are *supposed* to appear in user code. - * - * Although these happen to match their counterparts above, the - * implementation does not rely on that (so these could be renumbered). - */ -#define _IOFBF 0 /* setvbuf should set fully buffered */ -#define _IOLBF 1 /* setvbuf should set line buffered */ -#define _IONBF 2 /* setvbuf should set unbuffered */ - -#define EOF (-1) - -#ifdef __BUFSIZ__ -#define BUFSIZ __BUFSIZ__ -#else -#define BUFSIZ 1024 -#endif - -#ifdef __FOPEN_MAX__ -#define FOPEN_MAX __FOPEN_MAX__ -#else -#define FOPEN_MAX 20 -#endif - -#ifdef __FILENAME_MAX__ -#define FILENAME_MAX __FILENAME_MAX__ -#else -#define FILENAME_MAX 1024 -#endif - -#ifdef __L_tmpnam__ -#define L_tmpnam __L_tmpnam__ -#else -#define L_tmpnam FILENAME_MAX -#endif - -#ifndef __STRICT_ANSI__ -#define P_tmpdir "/tmp" -#endif - -#ifndef SEEK_SET -#define SEEK_SET 0 /* set file offset to offset */ -#endif -#ifndef SEEK_CUR -#define SEEK_CUR 1 /* set file offset to current plus offset */ -#endif -#ifndef SEEK_END -#define SEEK_END 2 /* set file offset to EOF plus offset */ -#endif - -#define TMP_MAX 26 - -#define stdin (_REENT->_stdin) -#define stdout (_REENT->_stdout) -#define stderr (_REENT->_stderr) - -#define _stdin_r(x) ((x)->_stdin) -#define _stdout_r(x) ((x)->_stdout) -#define _stderr_r(x) ((x)->_stderr) - -/* - * Functions defined in ANSI C standard. - */ - -#ifndef __VALIST -#ifdef __GNUC__ -#define __VALIST __gnuc_va_list -#else -#define __VALIST char* -#endif -#endif - -FILE * _EXFUN(tmpfile, (void)); -char * _EXFUN(tmpnam, (char *)); -#if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112 -char * _EXFUN(tempnam, (const char *, const char *)); -#endif -int _EXFUN(fclose, (FILE *)); -int _EXFUN(fflush, (FILE *)); -FILE * _EXFUN(freopen, (const char *__restrict, const char *__restrict, FILE *__restrict)); -void _EXFUN(setbuf, (FILE *__restrict, char *__restrict)); -int _EXFUN(setvbuf, (FILE *__restrict, char *__restrict, int, size_t)); -int _EXFUN(fprintf, (FILE *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -int _EXFUN(fscanf, (FILE *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); -int _EXFUN(printf, (const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 1, 2)))); -int _EXFUN(scanf, (const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__scanf__, 1, 2)))); -int _EXFUN(sscanf, (const char *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); -int _EXFUN(vfprintf, (FILE *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(vprintf, (const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 1, 0)))); -int _EXFUN(vsprintf, (char *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(fgetc, (FILE *)); -char * _EXFUN(fgets, (char *__restrict, int, FILE *__restrict)); -int _EXFUN(fputc, (int, FILE *)); -int _EXFUN(fputs, (const char *__restrict, FILE *__restrict)); -int _EXFUN(getc, (FILE *)); -int _EXFUN(getchar, (void)); -char * _EXFUN(gets, (char *)); -int _EXFUN(putc, (int, FILE *)); -int _EXFUN(putchar, (int)); -int _EXFUN(puts, (const char *)); -int _EXFUN(ungetc, (int, FILE *)); -size_t _EXFUN(fread, (_PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); -size_t _EXFUN(fwrite, (const _PTR __restrict , size_t _size, size_t _n, FILE *)); -#ifdef _COMPILING_NEWLIB -int _EXFUN(fgetpos, (FILE *, _fpos_t *)); -#else -int _EXFUN(fgetpos, (FILE *__restrict, fpos_t *__restrict)); -#endif -int _EXFUN(fseek, (FILE *, long, int)); -#ifdef _COMPILING_NEWLIB -int _EXFUN(fsetpos, (FILE *, const _fpos_t *)); -#else -int _EXFUN(fsetpos, (FILE *, const fpos_t *)); -#endif -long _EXFUN(ftell, ( FILE *)); -void _EXFUN(rewind, (FILE *)); -void _EXFUN(clearerr, (FILE *)); -int _EXFUN(feof, (FILE *)); -int _EXFUN(ferror, (FILE *)); -void _EXFUN(perror, (const char *)); -#ifndef _REENT_ONLY -FILE * _EXFUN(fopen, (const char *__restrict _name, const char *__restrict _type)); -int _EXFUN(sprintf, (char *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -int _EXFUN(remove, (const char *)); -int _EXFUN(rename, (const char *, const char *)); -#ifdef _COMPILING_NEWLIB -int _EXFUN(_rename, (const char *, const char *)); -#endif -#endif -#if !defined(__STRICT_ANSI__) || defined(__USE_XOPEN2K) -#ifdef _COMPILING_NEWLIB -int _EXFUN(fseeko, (FILE *, _off_t, int)); -_off_t _EXFUN(ftello, ( FILE *)); -#else -int _EXFUN(fseeko, (FILE *, off_t, int)); -off_t _EXFUN(ftello, ( FILE *)); -#endif -#endif -#if __GNU_VISIBLE -int _EXFUN(fcloseall, (_VOID)); -#endif -#if !defined(__STRICT_ANSI__) || (__STDC_VERSION__ >= 199901L) || (__cplusplus >= 201103L) -#ifndef _REENT_ONLY -int _EXFUN(asiprintf, (char **, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -char * _EXFUN(asniprintf, (char *, size_t *, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -char * _EXFUN(asnprintf, (char *__restrict, size_t *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(asprintf, (char **__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -#ifndef diprintf -int _EXFUN(diprintf, (int, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -#endif -int _EXFUN(fiprintf, (FILE *, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -int _EXFUN(fiscanf, (FILE *, const char *, ...) - _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); -int _EXFUN(iprintf, (const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 1, 2)))); -int _EXFUN(iscanf, (const char *, ...) - _ATTRIBUTE ((__format__ (__scanf__, 1, 2)))); -int _EXFUN(siprintf, (char *, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -int _EXFUN(siscanf, (const char *, const char *, ...) - _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); -int _EXFUN(snprintf, (char *__restrict, size_t, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(sniprintf, (char *, size_t, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(vasiprintf, (char **, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -char * _EXFUN(vasniprintf, (char *, size_t *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -char * _EXFUN(vasnprintf, (char *, size_t *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(vasprintf, (char **, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(vdiprintf, (int, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(vfiprintf, (FILE *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(vfiscanf, (FILE *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); -int _EXFUN(vfscanf, (FILE *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); -int _EXFUN(viprintf, (const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 1, 0)))); -int _EXFUN(viscanf, (const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 1, 0)))); -int _EXFUN(vscanf, (const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 1, 0)))); -int _EXFUN(vsiprintf, (char *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(vsiscanf, (const char *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); -int _EXFUN(vsniprintf, (char *, size_t, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(vsnprintf, (char *__restrict, size_t, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(vsscanf, (const char *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); -#endif /* !_REENT_ONLY */ -#endif /* !__STRICT_ANSI__ */ - -/* - * Routines in POSIX 1003.1:2001. - */ - -#ifndef __STRICT_ANSI__ -#ifndef _REENT_ONLY -FILE * _EXFUN(fdopen, (int, const char *)); -#endif -int _EXFUN(fileno, (FILE *)); -int _EXFUN(getw, (FILE *)); -int _EXFUN(pclose, (FILE *)); -FILE * _EXFUN(popen, (const char *, const char *)); -int _EXFUN(putw, (int, FILE *)); -void _EXFUN(setbuffer, (FILE *, char *, int)); -int _EXFUN(setlinebuf, (FILE *)); -int _EXFUN(getc_unlocked, (FILE *)); -int _EXFUN(getchar_unlocked, (void)); -void _EXFUN(flockfile, (FILE *)); -int _EXFUN(ftrylockfile, (FILE *)); -void _EXFUN(funlockfile, (FILE *)); -int _EXFUN(putc_unlocked, (int, FILE *)); -int _EXFUN(putchar_unlocked, (int)); -#endif /* ! __STRICT_ANSI__ */ - -/* - * Routines in POSIX 1003.1:200x. - */ - -#ifndef __STRICT_ANSI__ -# ifndef _REENT_ONLY -# ifndef dprintf -int _EXFUN(dprintf, (int, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -# endif -FILE * _EXFUN(fmemopen, (void *__restrict, size_t, const char *__restrict)); -/* getdelim - see __getdelim for now */ -/* getline - see __getline for now */ -FILE * _EXFUN(open_memstream, (char **, size_t *)); -#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 -int _EXFUN(renameat, (int, const char *, int, const char *)); -#endif -int _EXFUN(vdprintf, (int, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -# endif -#endif - -/* - * Recursive versions of the above. - */ - -int _EXFUN(_asiprintf_r, (struct _reent *, char **, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -char * _EXFUN(_asniprintf_r, (struct _reent *, char *, size_t *, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 4, 5)))); -char * _EXFUN(_asnprintf_r, (struct _reent *, char *__restrict, size_t *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 4, 5)))); -int _EXFUN(_asprintf_r, (struct _reent *, char **__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(_diprintf_r, (struct _reent *, int, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(_dprintf_r, (struct _reent *, int, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(_fclose_r, (struct _reent *, FILE *)); -int _EXFUN(_fcloseall_r, (struct _reent *)); -FILE * _EXFUN(_fdopen_r, (struct _reent *, int, const char *)); -int _EXFUN(_fflush_r, (struct _reent *, FILE *)); -int _EXFUN(_fgetc_r, (struct _reent *, FILE *)); -int _EXFUN(_fgetc_unlocked_r, (struct _reent *, FILE *)); -char * _EXFUN(_fgets_r, (struct _reent *, char *__restrict, int, FILE *__restrict)); -char * _EXFUN(_fgets_unlocked_r, (struct _reent *, char *__restrict, int, FILE *__restrict)); -#ifdef _COMPILING_NEWLIB -int _EXFUN(_fgetpos_r, (struct _reent *, FILE *__restrict, _fpos_t *__restrict)); -int _EXFUN(_fsetpos_r, (struct _reent *, FILE *, const _fpos_t *)); -#else -int _EXFUN(_fgetpos_r, (struct _reent *, FILE *, fpos_t *)); -int _EXFUN(_fsetpos_r, (struct _reent *, FILE *, const fpos_t *)); -#endif -int _EXFUN(_fiprintf_r, (struct _reent *, FILE *, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(_fiscanf_r, (struct _reent *, FILE *, const char *, ...) - _ATTRIBUTE ((__format__ (__scanf__, 3, 4)))); -FILE * _EXFUN(_fmemopen_r, (struct _reent *, void *__restrict, size_t, const char *__restrict)); -FILE * _EXFUN(_fopen_r, (struct _reent *, const char *__restrict, const char *__restrict)); -FILE * _EXFUN(_freopen_r, (struct _reent *, const char *__restrict, const char *__restrict, FILE *__restrict)); -int _EXFUN(_fprintf_r, (struct _reent *, FILE *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(_fpurge_r, (struct _reent *, FILE *)); -int _EXFUN(_fputc_r, (struct _reent *, int, FILE *)); -int _EXFUN(_fputc_unlocked_r, (struct _reent *, int, FILE *)); -int _EXFUN(_fputs_r, (struct _reent *, const char *__restrict, FILE *__restrict)); -int _EXFUN(_fputs_unlocked_r, (struct _reent *, const char *__restrict, FILE *__restrict)); -size_t _EXFUN(_fread_r, (struct _reent *, _PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); -size_t _EXFUN(_fread_unlocked_r, (struct _reent *, _PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); -int _EXFUN(_fscanf_r, (struct _reent *, FILE *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__scanf__, 3, 4)))); -int _EXFUN(_fseek_r, (struct _reent *, FILE *, long, int)); -int _EXFUN(_fseeko_r,(struct _reent *, FILE *, _off_t, int)); -long _EXFUN(_ftell_r, (struct _reent *, FILE *)); -_off_t _EXFUN(_ftello_r,(struct _reent *, FILE *)); -void _EXFUN(_rewind_r, (struct _reent *, FILE *)); -size_t _EXFUN(_fwrite_r, (struct _reent *, const _PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); -size_t _EXFUN(_fwrite_unlocked_r, (struct _reent *, const _PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); -int _EXFUN(_getc_r, (struct _reent *, FILE *)); -int _EXFUN(_getc_unlocked_r, (struct _reent *, FILE *)); -int _EXFUN(_getchar_r, (struct _reent *)); -int _EXFUN(_getchar_unlocked_r, (struct _reent *)); -char * _EXFUN(_gets_r, (struct _reent *, char *)); -int _EXFUN(_iprintf_r, (struct _reent *, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -int _EXFUN(_iscanf_r, (struct _reent *, const char *, ...) - _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); -FILE * _EXFUN(_open_memstream_r, (struct _reent *, char **, size_t *)); -void _EXFUN(_perror_r, (struct _reent *, const char *)); -int _EXFUN(_printf_r, (struct _reent *, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 2, 3)))); -int _EXFUN(_putc_r, (struct _reent *, int, FILE *)); -int _EXFUN(_putc_unlocked_r, (struct _reent *, int, FILE *)); -int _EXFUN(_putchar_unlocked_r, (struct _reent *, int)); -int _EXFUN(_putchar_r, (struct _reent *, int)); -int _EXFUN(_puts_r, (struct _reent *, const char *)); -int _EXFUN(_remove_r, (struct _reent *, const char *)); -int _EXFUN(_rename_r, (struct _reent *, - const char *_old, const char *_new)); -int _EXFUN(_scanf_r, (struct _reent *, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__scanf__, 2, 3)))); -int _EXFUN(_siprintf_r, (struct _reent *, char *, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(_siscanf_r, (struct _reent *, const char *, const char *, ...) - _ATTRIBUTE ((__format__ (__scanf__, 3, 4)))); -int _EXFUN(_sniprintf_r, (struct _reent *, char *, size_t, const char *, ...) - _ATTRIBUTE ((__format__ (__printf__, 4, 5)))); -int _EXFUN(_snprintf_r, (struct _reent *, char *__restrict, size_t, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 4, 5)))); -int _EXFUN(_sprintf_r, (struct _reent *, char *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__printf__, 3, 4)))); -int _EXFUN(_sscanf_r, (struct _reent *, const char *__restrict, const char *__restrict, ...) - _ATTRIBUTE ((__format__ (__scanf__, 3, 4)))); -char * _EXFUN(_tempnam_r, (struct _reent *, const char *, const char *)); -FILE * _EXFUN(_tmpfile_r, (struct _reent *)); -char * _EXFUN(_tmpnam_r, (struct _reent *, char *)); -int _EXFUN(_ungetc_r, (struct _reent *, int, FILE *)); -int _EXFUN(_vasiprintf_r, (struct _reent *, char **, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -char * _EXFUN(_vasniprintf_r, (struct _reent*, char *, size_t *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 4, 0)))); -char * _EXFUN(_vasnprintf_r, (struct _reent*, char *, size_t *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 4, 0)))); -int _EXFUN(_vasprintf_r, (struct _reent *, char **, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(_vdiprintf_r, (struct _reent *, int, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(_vdprintf_r, (struct _reent *, int, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(_vfiprintf_r, (struct _reent *, FILE *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(_vfiscanf_r, (struct _reent *, FILE *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 3, 0)))); -int _EXFUN(_vfprintf_r, (struct _reent *, FILE *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(_vfscanf_r, (struct _reent *, FILE *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 3, 0)))); -int _EXFUN(_viprintf_r, (struct _reent *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(_viscanf_r, (struct _reent *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); -int _EXFUN(_vprintf_r, (struct _reent *, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 2, 0)))); -int _EXFUN(_vscanf_r, (struct _reent *, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 2, 0)))); -int _EXFUN(_vsiprintf_r, (struct _reent *, char *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(_vsiscanf_r, (struct _reent *, const char *, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 3, 0)))); -int _EXFUN(_vsniprintf_r, (struct _reent *, char *, size_t, const char *, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 4, 0)))); -int _EXFUN(_vsnprintf_r, (struct _reent *, char *__restrict, size_t, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 4, 0)))); -int _EXFUN(_vsprintf_r, (struct _reent *, char *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__printf__, 3, 0)))); -int _EXFUN(_vsscanf_r, (struct _reent *, const char *__restrict, const char *__restrict, __VALIST) - _ATTRIBUTE ((__format__ (__scanf__, 3, 0)))); - -/* Other extensions. */ - -int _EXFUN(fpurge, (FILE *)); -ssize_t _EXFUN(__getdelim, (char **, size_t *, int, FILE *)); -ssize_t _EXFUN(__getline, (char **, size_t *, FILE *)); - -#if __BSD_VISIBLE -void _EXFUN(clearerr_unlocked, (FILE *)); -int _EXFUN(feof_unlocked, (FILE *)); -int _EXFUN(ferror_unlocked, (FILE *)); -int _EXFUN(fileno_unlocked, (FILE *)); -int _EXFUN(fflush_unlocked, (FILE *)); -int _EXFUN(fgetc_unlocked, (FILE *)); -int _EXFUN(fputc_unlocked, (int, FILE *)); -size_t _EXFUN(fread_unlocked, (_PTR __restrict, size_t _size, size_t _n, FILE *__restrict)); -size_t _EXFUN(fwrite_unlocked, (const _PTR __restrict , size_t _size, size_t _n, FILE *)); -#endif - -#if __GNU_VISIBLE -char * _EXFUN(fgets_unlocked, (char *__restrict, int, FILE *__restrict)); -int _EXFUN(fputs_unlocked, (const char *__restrict, FILE *__restrict)); -#endif - -#ifdef __LARGE64_FILES -#if !defined(__CYGWIN__) || defined(_COMPILING_NEWLIB) -FILE * _EXFUN(fdopen64, (int, const char *)); -FILE * _EXFUN(fopen64, (const char *, const char *)); -FILE * _EXFUN(freopen64, (_CONST char *, _CONST char *, FILE *)); -_off64_t _EXFUN(ftello64, (FILE *)); -_off64_t _EXFUN(fseeko64, (FILE *, _off64_t, int)); -int _EXFUN(fgetpos64, (FILE *, _fpos64_t *)); -int _EXFUN(fsetpos64, (FILE *, const _fpos64_t *)); -FILE * _EXFUN(tmpfile64, (void)); - -FILE * _EXFUN(_fdopen64_r, (struct _reent *, int, const char *)); -FILE * _EXFUN(_fopen64_r, (struct _reent *,const char *, const char *)); -FILE * _EXFUN(_freopen64_r, (struct _reent *, _CONST char *, _CONST char *, FILE *)); -_off64_t _EXFUN(_ftello64_r, (struct _reent *, FILE *)); -_off64_t _EXFUN(_fseeko64_r, (struct _reent *, FILE *, _off64_t, int)); -int _EXFUN(_fgetpos64_r, (struct _reent *, FILE *, _fpos64_t *)); -int _EXFUN(_fsetpos64_r, (struct _reent *, FILE *, const _fpos64_t *)); -FILE * _EXFUN(_tmpfile64_r, (struct _reent *)); -#endif /* !__CYGWIN__ */ -#endif /* __LARGE64_FILES */ - -/* - * Routines internal to the implementation. - */ - -int _EXFUN(__srget_r, (struct _reent *, FILE *)); -int _EXFUN(__swbuf_r, (struct _reent *, int, FILE *)); - -/* - * Stdio function-access interface. - */ - -#ifndef __STRICT_ANSI__ -# ifdef __LARGE64_FILES -FILE *_EXFUN(funopen,(const _PTR __cookie, - int (*__readfn)(_PTR __c, char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - int (*__writefn)(_PTR __c, const char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - _fpos64_t (*__seekfn)(_PTR __c, _fpos64_t __off, int __whence), - int (*__closefn)(_PTR __c))); -FILE *_EXFUN(_funopen_r,(struct _reent *, const _PTR __cookie, - int (*__readfn)(_PTR __c, char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - int (*__writefn)(_PTR __c, const char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - _fpos64_t (*__seekfn)(_PTR __c, _fpos64_t __off, int __whence), - int (*__closefn)(_PTR __c))); -# else -FILE *_EXFUN(funopen,(const _PTR __cookie, - int (*__readfn)(_PTR __cookie, char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - int (*__writefn)(_PTR __cookie, const char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - fpos_t (*__seekfn)(_PTR __cookie, fpos_t __off, int __whence), - int (*__closefn)(_PTR __cookie))); -FILE *_EXFUN(_funopen_r,(struct _reent *, const _PTR __cookie, - int (*__readfn)(_PTR __cookie, char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - int (*__writefn)(_PTR __cookie, const char *__buf, - _READ_WRITE_BUFSIZE_TYPE __n), - fpos_t (*__seekfn)(_PTR __cookie, fpos_t __off, int __whence), - int (*__closefn)(_PTR __cookie))); -# endif /* !__LARGE64_FILES */ - -# define fropen(__cookie, __fn) funopen(__cookie, __fn, (int (*)())0, \ - (fpos_t (*)())0, (int (*)())0) -# define fwopen(__cookie, __fn) funopen(__cookie, (int (*)())0, __fn, \ - (fpos_t (*)())0, (int (*)())0) - -typedef ssize_t cookie_read_function_t(void *__cookie, char *__buf, size_t __n); -typedef ssize_t cookie_write_function_t(void *__cookie, const char *__buf, - size_t __n); -# ifdef __LARGE64_FILES -typedef int cookie_seek_function_t(void *__cookie, _off64_t *__off, - int __whence); -# else -typedef int cookie_seek_function_t(void *__cookie, off_t *__off, int __whence); -# endif /* !__LARGE64_FILES */ -typedef int cookie_close_function_t(void *__cookie); -typedef struct -{ - /* These four struct member names are dictated by Linux; hopefully, - they don't conflict with any macros. */ - cookie_read_function_t *read; - cookie_write_function_t *write; - cookie_seek_function_t *seek; - cookie_close_function_t *close; -} cookie_io_functions_t; -FILE *_EXFUN(fopencookie,(void *__cookie, - const char *__mode, cookie_io_functions_t __functions)); -FILE *_EXFUN(_fopencookie_r,(struct _reent *, void *__cookie, - const char *__mode, cookie_io_functions_t __functions)); -#endif /* ! __STRICT_ANSI__ */ - -#ifndef __CUSTOM_FILE_IO__ -/* - * The __sfoo macros are here so that we can - * define function versions in the C library. - */ -#define __sgetc_raw_r(__ptr, __f) (--(__f)->_r < 0 ? __srget_r(__ptr, __f) : (int)(*(__f)->_p++)) - -#ifdef __SCLE -/* For a platform with CR/LF, additional logic is required by - __sgetc_r which would otherwise simply be a macro; therefore we - use an inlined function. The function is only meant to be inlined - in place as used and the function body should never be emitted. - - There are two possible means to this end when compiling with GCC, - one when compiling with a standard C99 compiler, and for other - compilers we're just stuck. At the moment, this issue only - affects the Cygwin target, so we'll most likely be using GCC. */ - -_ELIDABLE_INLINE int __sgetc_r(struct _reent *__ptr, FILE *__p); - -_ELIDABLE_INLINE int __sgetc_r(struct _reent *__ptr, FILE *__p) - { - int __c = __sgetc_raw_r(__ptr, __p); - if ((__p->_flags & __SCLE) && (__c == '\r')) - { - int __c2 = __sgetc_raw_r(__ptr, __p); - if (__c2 == '\n') - __c = __c2; - else - ungetc(__c2, __p); - } - return __c; - } -#else -#define __sgetc_r(__ptr, __p) __sgetc_raw_r(__ptr, __p) -#endif - -#ifdef _never /* __GNUC__ */ -/* If this inline is actually used, then systems using coff debugging - info get hopelessly confused. 21sept93 rich@cygnus.com. */ -_ELIDABLE_INLINE int __sputc_r(struct _reent *_ptr, int _c, FILE *_p) { - if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n')) - return (*_p->_p++ = _c); - else - return (__swbuf_r(_ptr, _c, _p)); -} -#else -/* - * This has been tuned to generate reasonable code on the vax using pcc - */ -#define __sputc_raw_r(__ptr, __c, __p) \ - (--(__p)->_w < 0 ? \ - (__p)->_w >= (__p)->_lbfsize ? \ - (*(__p)->_p = (__c)), *(__p)->_p != '\n' ? \ - (int)*(__p)->_p++ : \ - __swbuf_r(__ptr, '\n', __p) : \ - __swbuf_r(__ptr, (int)(__c), __p) : \ - (*(__p)->_p = (__c), (int)*(__p)->_p++)) -#ifdef __SCLE -#define __sputc_r(__ptr, __c, __p) \ - ((((__p)->_flags & __SCLE) && ((__c) == '\n')) \ - ? __sputc_raw_r(__ptr, '\r', (__p)) : 0 , \ - __sputc_raw_r((__ptr), (__c), (__p))) -#else -#define __sputc_r(__ptr, __c, __p) __sputc_raw_r(__ptr, __c, __p) -#endif -#endif - -#define __sfeof(p) ((int)(((p)->_flags & __SEOF) != 0)) -#define __sferror(p) ((int)(((p)->_flags & __SERR) != 0)) -#define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF))) -#define __sfileno(p) ((p)->_file) - -#ifndef _REENT_SMALL -#define feof(p) __sfeof(p) -#define ferror(p) __sferror(p) -#define clearerr(p) __sclearerr(p) - -#if __BSD_VISIBLE -#define feof_unlocked(p) __sfeof(p) -#define ferror_unlocked(p) __sferror(p) -#define clearerr_unlocked(p) __sclearerr(p) -#endif /* __BSD_VISIBLE */ -#endif /* _REENT_SMALL */ - -#if 0 /*ndef __STRICT_ANSI__ - FIXME: must initialize stdio first, use fn */ -#define fileno(p) __sfileno(p) -#endif - -#ifndef __CYGWIN__ -#ifndef lint -#define getc(fp) __sgetc_r(_REENT, fp) -#define putc(x, fp) __sputc_r(_REENT, x, fp) -#endif /* lint */ -#endif /* __CYGWIN__ */ - -#ifndef __STRICT_ANSI__ -/* fast always-buffered version, true iff error */ -#define fast_putc(x,p) (--(p)->_w < 0 ? \ - __swbuf_r(_REENT, (int)(x), p) == EOF : (*(p)->_p = (x), (p)->_p++, 0)) - -#define L_cuserid 9 /* posix says it goes in stdio.h :( */ -#ifdef __CYGWIN__ -#define L_ctermid 16 -#endif -#endif - -#endif /* !__CUSTOM_FILE_IO__ */ - -#define getchar() getc(stdin) -#define putchar(x) putc(x, stdout) - -#ifndef __STRICT_ANSI__ -#define getchar_unlocked() getc_unlocked(stdin) -#define putchar_unlocked(x) putc_unlocked(x, stdout) -#endif - -_END_STD_C - -#undef putchar -#undef getchar - -#ifdef __cplusplus -} -#endif - -#endif /* DOXYGEN */ -#endif /* STDIO_H */ diff --git a/cpu/esp8266/include/syscalls.h b/cpu/esp8266/include/syscalls.h index 21185ec36e1b..77d3abca1f9d 100644 --- a/cpu/esp8266/include/syscalls.h +++ b/cpu/esp8266/include/syscalls.h @@ -21,38 +21,17 @@ #ifndef SYSCALLS_H #define SYSCALLS_H -#include -#include -#include -#include +#include "syscalls_common.h" #ifdef __cplusplus extern "C" { #endif -/** Necessary initializations of system call functions */ -extern void syscalls_init (void); +#ifndef DOXYGEN -/** System standard printf function */ -extern int printf(const char* format, ...); +#define MALLOC_CAP_DEFAULT MALLOC_CAP_8BIT -/** Determine free heap size */ -unsigned int get_free_heap_size (void); - -/** System standard puts function */ -extern int puts(const char * str); - -/** Determine free heap size */ -extern unsigned int get_free_heap_size (void); - -/** Time since boot in us (32bit version) */ -uint32_t system_get_time (void); - -/** Time since boot in ms (32bit version) */ -uint32_t system_get_time_ms (void); - -/** memset version that the compiler should not be allowed to optimize this */ -void *system_secure_memset(void *s, int c, size_t n); +#endif /* DOXYGEN */ #ifdef __cplusplus } diff --git a/cpu/esp8266/include/tools.h b/cpu/esp8266/include/tools.h deleted file mode 100644 index f6dc065b0e18..000000000000 --- a/cpu/esp8266/include/tools.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2019 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp8266 - * @{ - * - * @file - * @brief Implementation of some tools - * - * @author Gunar Schorcht - * - * @} - */ - -#ifndef TOOLS_H -#define TOOLS_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Hexdump of memory - * @param[in] addr start address in memory - * @param[in] num number of items to dump - * @param[in] width format of the items - * @param[in] per_line number of items per line - */ -void esp_hexdump (const void* addr, uint32_t num, char width, uint8_t per_line); - -/** - * @brief Print heap and system memory information - */ -void print_meminfo (void); - -#ifdef __cplusplus -} -#endif - -#endif /* TOOLS_H */ diff --git a/cpu/esp8266/periph/hwrng.c b/cpu/esp8266/periph/hwrng.c deleted file mode 100644 index 3984e309de87..000000000000 --- a/cpu/esp8266/periph/hwrng.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2019 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp8266 - * @ingroup drivers_periph_hwrng - * @{ - * - * @file - * @brief Low-level random number generator driver implementation - * - * @author Gunar Schorcht - * - * @} - */ - -#include "cpu.h" -#include "periph_conf.h" -#include "periph/hwrng.h" -#include "rom/ets_sys.h" - -#ifdef MCU_ESP32 -static const uint32_t* RNG_DATA_REG = (uint32_t*)0x3ff75144; -#else -static const uint32_t* RNG_DATA_REG = (uint32_t*)0x3ff20e44; -#endif - -void hwrng_init(void) -{ - /* no need for initialization */ -} - -void hwrng_read(void *buf, unsigned int num) -{ - unsigned int count = 0; - uint8_t *b = (uint8_t *)buf; - - while (count < num) { - /* read next 4 bytes of random data */ - uint32_t tmp = *RNG_DATA_REG; - - /* copy data into result vector */ - for (int i = 0; i < 4 && count < num; i++) { - b[count++] = (uint8_t)tmp; - tmp = tmp >> 8; - } - } -} - -uint32_t hwrand (void) -{ - uint32_t _tmp; - hwrng_read(&_tmp, sizeof(uint32_t)); - return _tmp; -} diff --git a/cpu/esp8266/sdk/system.h b/cpu/esp8266/sdk/system.h index 336865ae3a44..56c4d3ade7db 100644 --- a/cpu/esp8266/sdk/system.h +++ b/cpu/esp8266/sdk/system.h @@ -47,8 +47,6 @@ extern void system_restart(void); #define system_wdt_init esp_task_wdt_init #define system_wdt_feed esp_task_wdt_reset -#define system_wdt_start pp_soft_wdt_stop -#define system_wdt_stop pp_soft_wdt_restart /** @} */ diff --git a/cpu/esp8266/startup.c b/cpu/esp8266/startup.c index 31534dcd82dd..8c994f91c170 100644 --- a/cpu/esp8266/startup.c +++ b/cpu/esp8266/startup.c @@ -73,7 +73,6 @@ void esp_riot_init(void) ets_printf("CPU clock frequency: %d MHz\n", system_get_cpu_freq()); extern void heap_stats(void); heap_stats(); - ets_printf("\n"); #endif /* set exception handlers */ @@ -96,7 +95,9 @@ void esp_riot_init(void) #endif /* initialize stdio*/ + extern int stdio_is_initialized; stdio_init(); + stdio_is_initialized = 1; /* trigger static peripheral initialization */ periph_init(); @@ -107,6 +108,9 @@ void esp_riot_init(void) #ifdef MODULE_ESP_LOG_STARTUP /* print the board config */ board_print_config(); +#else + /* to have an empty line after the unreadable characters from ROM loader */ + puts(""); #endif /* initialize ESP system event loop */ diff --git a/cpu/esp8266/syscalls.c b/cpu/esp8266/syscalls.c index b8486903c17e..40e3032c4742 100644 --- a/cpu/esp8266/syscalls.c +++ b/cpu/esp8266/syscalls.c @@ -18,368 +18,36 @@ * @} */ -#include "periph/pm.h" -#include "timex.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mutex.h" -#include "rmutex.h" - -#include "esp_common.h" -#include "esp/common_macros.h" #include "esp_attr.h" +#include "esp_common.h" #include "sdk/sdk.h" -#include "syscalls.h" - -#ifdef MODULE_STDIO_UART -#include "stdio_uart.h" -#endif #ifdef MODULE_ESP_IDF_HEAP #include "esp_heap_caps.h" -#else -#include "malloc.h" #endif #define ENABLE_DEBUG (0) #include "debug.h" -#define MHZ 1000000UL - -#ifndef MODULE_PTHREAD - -#define PTHREAD_CANCEL_DISABLE 1 -/* - * This is a dummy function to avoid undefined references when linking - * against newlib and module pthread is not used. - */ -int pthread_setcancelstate(int state, int *oldstate) -{ - if (oldstate) { - *oldstate = PTHREAD_CANCEL_DISABLE; - } - return 0; -} -#endif /* MODULE_PTHREAD */ - -/* - * TODO: When the lock functions in this section are enabled, an application - * crashes when an ISR calls a `newlib` function that uses `_lock_acquire` - * or `_log_acquire_recursive` to be thread-safe, for example, `puts` in - * `tests/isr_yield_higher`. The reason is that the implementation of these - * functions uses `mutex` and `rmutex` that do not work in the interrupt - * context. Therefore, the lock functions are disabled for the moment, and - * instead `newlib`'s dummy lock functions are used which do not guarantee - * thread safety. - */ - -#if 0 - -/** - * @name Locking functions - * - * Following functions implement the lock mechanism for newlib. - */ - -/** - * _malloc_rmtx is defined as static variable to avoid recursive calls of - * malloc when _malloc_r tries to lock __malloc_lock_object the first - * time. All other mutexes that are used for the lock mechanism are allocated - * dynamically. - */ -static rmutex_t _malloc_rmtx = RMUTEX_INIT; - -/** - * To properly handle the static rmutex _malloc_rmtx, we have to know - * the address of newlib's static variable __malloc_lock_object. - */ -static _lock_t *__malloc_static_object = NULL; - -void IRAM _lock_init(_lock_t *lock) -{ - assert(lock != NULL); - - mutex_t* mtx = malloc(sizeof(mutex_t)); - - if (mtx) { - memset(mtx, 0, sizeof(mutex_t)); - *lock = (_lock_t)mtx; - } -} - -void IRAM _lock_init_recursive(_lock_t *lock) -{ - assert(lock != NULL); - - /** - * Since we don't have direct access to newlib's static variable - * __malloc_lock_object, we have to rely on the fact that function - * _lock_aqcuire_recursive, and thus function _lock_init_recursive - * is called for the first time with newlib's static variable - * __malloc_lock_object as parameter. This is ensured by calling - * malloc in the function syscalls_init. - */ - if (__malloc_static_object == NULL) { - *lock = (_lock_t)&_malloc_rmtx; - __malloc_static_object = lock; - return; - } - - /* _malloc_rmtx is static and has not to be allocated */ - if (lock == __malloc_static_object) { - return; - } - - rmutex_t* rmtx = malloc(sizeof(rmutex_t)); - - if (rmtx) { - memset(rmtx, 0, sizeof(rmutex_t)); - *lock = (_lock_t)rmtx; - } -} - -void IRAM _lock_close(_lock_t *lock) -{ - assert(lock != NULL); - assert(lock != __malloc_static_object); - - free((void*)*lock); - *lock = 0; -} - -void IRAM _lock_close_recursive(_lock_t *lock) -{ - assert(lock != NULL); - assert(lock != __malloc_static_object); - - free((void*)*lock); - *lock = 0; -} - -void IRAM _lock_acquire(_lock_t *lock) -{ - assert(lock != NULL); - - /* if the lock data structure is still not allocated, initialize it first */ - if (*lock == 0) { - _lock_init(lock); - } - - /* if scheduler is not running, we have not to lock the mutex */ - if (sched_active_thread == NULL) { - return; - } - - assert(!irq_is_in()); - mutex_lock((mutex_t*)*lock); -} - -void IRAM _lock_acquire_recursive(_lock_t *lock) -{ - assert(lock != NULL); - - /* if the lock data structure is still not allocated, initialize it first */ - if (*lock == 0) { - _lock_init_recursive(lock); - } - - /* if scheduler is not running, we have not to lock the rmutex */ - if (sched_active_thread == NULL) { - return; - } - - assert(!irq_is_in()); - rmutex_lock((rmutex_t*)*lock); -} - -int IRAM _lock_try_acquire(_lock_t *lock) -{ - assert(lock != NULL); - - /* if the lock data structure is still not allocated, initialize it first */ - if (*lock == 0) { - _lock_init(lock); - } - - /* if scheduler is not running, we have not to lock the mutex */ - if (sched_active_thread == NULL) { - return 0; - } - - if (irq_is_in()) { - return 0; - } - - return mutex_trylock((mutex_t*)*lock); -} - -int IRAM _lock_try_acquire_recursive(_lock_t *lock) -{ - assert(lock != NULL); - - /* if the lock data structure is still not allocated, initialize it first */ - if (*lock == 0) { - _lock_init_recursive(lock); - } - - /* if scheduler is not running, we have not to lock the rmutex */ - if (sched_active_thread == NULL) { - return 0; - } - - if (irq_is_in()) { - return 0; - } - - return rmutex_trylock((rmutex_t*)*lock); -} - -void IRAM _lock_release(_lock_t *lock) -{ - assert(lock != NULL && *lock != 0); - - /* if scheduler is not running, we have not to unlock the mutex */ - if (sched_active_thread == NULL) { - return; - } - - mutex_unlock((mutex_t*)*lock); -} - -void IRAM _lock_release_recursive(_lock_t *lock) -{ - assert(lock != NULL && *lock != 0); - - /* if scheduler is not running, we have not to unlock the rmutex */ - if (sched_active_thread == NULL) { - return; - } - - rmutex_unlock((rmutex_t*)*lock); -} - -#endif - -/** - * @name Memory allocation functions - */ - #ifdef MODULE_ESP_IDF_HEAP -#define MALLOC_CAP_DEFAULT MALLOC_CAP_8BIT -#define heap_caps_malloc_default(s) heap_caps_malloc(s, MALLOC_CAP_DEFAULT) -#define heap_caps_realloc_default(p,s) heap_caps_realloc(p, s, MALLOC_CAP_DEFAULT) - -void* IRAM_ATTR __wrap__malloc_r(struct _reent *r, size_t size) -{ - return heap_caps_malloc_default( size ); -} - -void IRAM_ATTR __wrap__free_r(struct _reent *r, void *ptr) -{ - heap_caps_free( ptr ); -} - -void* IRAM_ATTR __wrap__realloc_r(struct _reent *r, void* ptr, size_t size) -{ - return heap_caps_realloc_default( ptr, size ); -} - -void* IRAM_ATTR __wrap__calloc_r(struct _reent *r, size_t count, size_t size) -{ - void *result = heap_caps_malloc_default(count * size); - if (result) { - bzero(result, count * size); - } - return result; -} - -unsigned int get_free_heap_size(void) -{ - return heap_caps_get_free_size(MALLOC_CAP_DEFAULT); -} - +/* this function is platform specific if module esp_idf_heap is used */ void heap_stats(void) { + size_t _free = 0; + size_t _alloc = 0; + extern heap_region_t g_heap_region[HEAP_REGIONS_MAX]; for (int i = 0; i < HEAP_REGIONS_MAX; i++) { - ets_printf("Heap region %u @%p: %u (used %u, free %u) [bytes]\n", i, - g_heap_region[i].start_addr, - g_heap_region[i].total_size, - g_heap_region[i].total_size - g_heap_region[i].free_bytes, - g_heap_region[i].free_bytes); + _free += g_heap_region[i].free_bytes; + _alloc += g_heap_region[i].total_size - g_heap_region[i].free_bytes; } -} - -#else /* MODULE_ESP_IDF_HEAP */ -/* for compatibility with ESP-IDF heap functions */ - -void* _heap_caps_malloc(size_t size, uint32_t caps, const char *file, size_t line) -{ - (void)caps; - return malloc(size); -} - -void* _heap_caps_calloc(size_t n, size_t size, uint32_t caps, const char *file, size_t line) -{ - (void)caps; - return calloc(n, size); -} - -void* _heap_caps_realloc(void *ptr, size_t size, uint32_t caps, const char *file, size_t line) -{ - return realloc(ptr, size); -} - -void *_heap_caps_zalloc(size_t size, uint32_t caps, const char *file, size_t line) -{ - void *ptr = malloc(size); - if (ptr) { - memset(ptr, 0, size); - } - return ptr; -} - -void _heap_caps_free(void *ptr, const char *file, size_t line) -{ - (void)file; - (void)line; - free(ptr); -} - -void heap_caps_init(void) -{ -} - -extern uint8_t _eheap; /* end of heap (defined in esp32.common.ld) */ -extern uint8_t _sheap; /* start of heap (defined in esp32.common.ld) */ - -unsigned int IRAM get_free_heap_size(void) -{ - struct mallinfo minfo = mallinfo(); - return &_eheap - &_sheap - minfo.uordblks; -} - -void heap_stats(void) -{ ets_printf("heap: %u (used %u, free %u) [bytes]\n", - &_eheap - &_sheap, &_eheap - &_sheap - get_free_heap_size(), - get_free_heap_size()); + _alloc + _free, _alloc, _free); } -/* alias for compatibility with espressif/wifi_libs */ -uint32_t esp_get_free_heap_size( void ) __attribute__((alias("get_free_heap_size"))); - #endif /* MODULE_ESP_IDF_HEAP */ /** @@ -391,108 +59,6 @@ int _rename_r(struct _reent *r, const char *from, const char *to) return 0; } -void _abort(void) -{ - ets_printf("#! abort called: powering off\n"); - pm_off(); - while (1) { }; -} - -void _exit_r(struct _reent *r, int status) -{ - _exit(status); -} - -struct _reent* __getreent(void) { - return _GLOBAL_REENT; -} - -#ifdef MCU_ESP32 -static int _no_sys_func(struct _reent *r) -{ - DEBUG("%s: system function does not exist\n", __func__); - r->_errno = ENOSYS; - return -1; -} -#endif - -static struct _reent s_reent; - -#ifdef MCU_ESP32 -static struct syscall_stub_table s_stub_table = -{ - .__getreent = &__getreent, - - ._malloc_r = &_malloc_r, - ._free_r = &_free_r, - ._realloc_r = &_realloc_r, - ._calloc_r = &_calloc_r, - ._sbrk_r = &_sbrk_r, - - ._system_r = (int (*)(struct _reent *, const char*))&_no_sys_func, - ._raise_r = (void (*)(struct _reent *))&_no_sys_func, - ._abort = &_abort, - ._exit_r = &_exit_r, - ._getpid_r = &_getpid_r, - ._kill_r = &_kill_r, - - ._times_r = &_times_r, - ._gettimeofday_r = _gettimeofday_r, - - ._open_r = &_open_r, - ._close_r = &_close_r, - ._lseek_r = (int (*)(struct _reent *r, int, int, int))&_lseek_r, - ._fstat_r = &_fstat_r, - ._stat_r = &_stat_r, - ._write_r = (int (*)(struct _reent *r, int, const void *, int))&_write_r, - ._read_r = (int (*)(struct _reent *r, int, void *, int))&_read_r, - ._unlink_r = &_unlink_r, - ._link_r = (int (*)(struct _reent *r, const char*, const char*))&_no_sys_func, - ._rename_r = (int (*)(struct _reent *r, const char*, const char*))&_no_sys_func, - - ._lock_init = &_lock_init, - ._lock_init_recursive = &_lock_init_recursive, - ._lock_close = &_lock_close, - ._lock_close_recursive = &_lock_close_recursive, - ._lock_acquire = &_lock_acquire, - ._lock_acquire_recursive = &_lock_acquire_recursive, - ._lock_try_acquire = &_lock_try_acquire, - ._lock_try_acquire_recursive = &_lock_try_acquire_recursive, - ._lock_release = &_lock_release, - ._lock_release_recursive = &_lock_release_recursive, - - #if CONFIG_NEWLIB_NANO_FORMAT - ._printf_float = &_printf_float, - ._scanf_float = &_scanf_float, - #else /* CONFIG_NEWLIB_NANO_FORMAT */ - ._printf_float = NULL, - ._scanf_float = NULL, - #endif /* CONFIG_NEWLIB_NANO_FORMAT */ -}; -#endif - -void syscalls_init(void) -{ -#ifdef MCU_ESP32 - /* enable the system timer in us (TMG0 is enabled by default) */ - TIMER_SYSTEM.config.divider = rtc_clk_apb_freq_get()/MHZ; - TIMER_SYSTEM.config.autoreload = 0; - TIMER_SYSTEM.config.enable = 1; - syscall_table_ptr_pro = &s_stub_table; - syscall_table_ptr_app = &s_stub_table; -#endif - _GLOBAL_REENT = &s_reent; - - environ = malloc(sizeof(char*)); - environ[0] = NULL; - - /* - * initialization of newlib, includes the ctors initialization - */ - extern void __libc_init_array(void); - __libc_init_array(); -} - uint32_t system_get_time(void) { return phy_get_mactime(); @@ -500,107 +66,9 @@ uint32_t system_get_time(void) uint32_t system_get_time_ms(void) { - return phy_get_mactime() / US_PER_MS; -} - -#ifdef MCU_ESP32 -uint64_t system_get_time_64(void) -{ - uint64_t ret; - /* latch 64 bit timer value before read */ - TIMER_SYSTEM.update = 0; - /* wait until instructions have been finished */ - __asm__ volatile ("isync"); - /* read the current timer value */ - ret = TIMER_SYSTEM.cnt_low; - ret += ((uint64_t)TIMER_SYSTEM.cnt_high) << 32; - return ret; -} - -/* alias for compatibility with espressif/wifi_libs */ -int64_t esp_timer_get_time(void) __attribute__((alias("system_get_time_64"))); - -static IRAM void system_wdt_int_handler(void *arg) -{ - TIMERG0.int_clr_timers.wdt=1; /* clear interrupt */ - system_wdt_feed(); -} - -void IRAM system_wdt_feed(void) -{ - DEBUG("%s\n", __func__); - TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; /* disable write protection */ - TIMERG0.wdt_feed=1; /* reset MWDT */ - TIMERG0.wdt_wprotect=0; /* enable write protection */ -} - -void system_wdt_init(void) -{ - /* disable boot watchdogs */ - TIMERG0.wdt_config0.flashboot_mod_en = 0; - RTCCNTL.wdt_config0.flashboot_mod_en = 0; - - /* enable system watchdog */ - TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; /* disable write protection */ - TIMERG0.wdt_config0.stg0 = TIMG_WDT_STG_SEL_INT; /* stage0 timeout: interrupt */ - TIMERG0.wdt_config0.stg1 = TIMG_WDT_STG_SEL_RESET_SYSTEM; /* stage1 timeout: sys reset */ - TIMERG0.wdt_config0.sys_reset_length = 7; /* sys reset signal length: 3.2 us */ - TIMERG0.wdt_config0.cpu_reset_length = 7; /* sys reset signal length: 3.2 us */ - TIMERG0.wdt_config0.edge_int_en = 0; - TIMERG0.wdt_config0.level_int_en = 1; - - /* MWDT clock = 80 * 12,5 ns = 1 us */ - TIMERG0.wdt_config1.clk_prescale = 80; - - /* define stage timeouts */ - TIMERG0.wdt_config2 = 2 * US_PER_SEC; /* stage 0: 2 s (interrupt) */ - TIMERG0.wdt_config3 = 4 * US_PER_SEC; /* stage 1: 4 s (sys reset) */ - - TIMERG0.wdt_config0.en = 1; /* enable MWDT */ - TIMERG0.wdt_feed = 1; /* reset MWDT */ - TIMERG0.wdt_wprotect = 0; /* enable write protection */ - - DEBUG("%s TIMERG0 wdt_config0=%08x wdt_config1=%08x wdt_config2=%08x\n", - __func__, TIMERG0.wdt_config0.val, TIMERG0.wdt_config1.val, - TIMERG0.wdt_config2); - - /* route WDT peripheral interrupt source to CPU_INUM_WDT */ - intr_matrix_set(PRO_CPU_NUM, ETS_TG0_WDT_LEVEL_INTR_SOURCE, CPU_INUM_WDT); - /* set the interrupt handler and activate the interrupt */ - xt_set_interrupt_handler(CPU_INUM_WDT, system_wdt_int_handler, NULL); - xt_ints_on(BIT(CPU_INUM_WDT)); -} - -void system_wdt_stop(void) -{ - xt_ints_off(BIT(CPU_INUM_WDT)); - TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; /* disable write protection */ - TIMERG0.wdt_config0.en = 0; /* disable MWDT */ - TIMERG0.wdt_feed = 1; /* reset MWDT */ - TIMERG0.wdt_wprotect = 0; /* enable write protection */ -} - -void system_wdt_start(void) -{ - TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; /* disable write protection */ - TIMERG0.wdt_config0.en = 1; /* disable MWDT */ - TIMERG0.wdt_feed = 1; /* reset MWDT */ - TIMERG0.wdt_wprotect = 0; /* enable write protection */ - xt_ints_on(BIT(CPU_INUM_WDT)); -} -#endif - -__attribute__((weak)) void -_system_prevent_memset_lto(void *const s, int c, const size_t n) -{ - (void)s; - (void)c; - (void)n; + return system_get_time() / USEC_PER_MSEC; } -void *system_secure_memset(void *s, int c, size_t n) +void IRAM_ATTR syscalls_init_arch(void) { - memset(s, c, n); - _system_prevent_memset_lto(s, c, n); - return s; } diff --git a/cpu/esp8266/tools.c b/cpu/esp8266/tools.c deleted file mode 100644 index b840aea01f75..000000000000 --- a/cpu/esp8266/tools.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2019 Gunar Schorcht - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_esp8266 - * @{ - * - * @file - * @brief Implementation of some tools - * - * @author Gunar Schorcht - * - * @} - */ - -#include -#include - -#ifdef MCU_ESP8266 -#include -#include "sdk/sdk.h" -#else -#include "rom/ets_sys.h" -#endif - -#include "esp/common_macros.h" -#include "tools.h" - -extern void malloc_stats (void); -extern unsigned int get_free_heap_size (void); -extern uint8_t _eheap; /* end of heap (defined in esp8266.riot-os.app.ld) */ -extern uint8_t _sheap; /* start of heap (defined in esp8266.riot-os.app.ld) */ - -void print_meminfo (void) -{ - struct mallinfo minfo = mallinfo(); - ets_printf("heap: %lu (free %lu) byte\n", &_eheap - &_sheap, get_free_heap_size()); - ets_printf("sysmem: %d (used %d, free %d)\n", minfo.arena, minfo.uordblks, minfo.fordblks); -} - -void esp_hexdump (const void* addr, uint32_t num, char width, uint8_t per_line) -{ - uint32_t count = 0; - uint32_t size; - - uint8_t* addr8 = (uint8_t*) addr; - uint16_t* addr16 = (uint16_t*)addr; - uint32_t* addr32 = (uint32_t*)addr; - uint64_t* addr64 = (uint64_t*)addr; - - switch (width) { - case 'b': size = 1; break; - case 'h': size = 2; break; - case 'w': size = 4; break; - case 'g': size = 8; break; - default : size = 1; break; - } - - while (count < num) { - if (count % per_line == 0) { - ets_printf ("%08" PRIx32 ": ", (uint32_t)((uint8_t*)addr+count*size)); - } - switch (width) { - case 'b': ets_printf("%02" PRIx8 " ", addr8[count++]); break; - case 'h': ets_printf("%04" PRIx16 " ", addr16[count++]); break; - case 'w': ets_printf("%08" PRIx32 " ", addr32[count++]); break; - case 'g': ets_printf("%016" PRIx64 " ", addr64[count++]); break; - default : ets_printf("."); count++; break; - } - if (count % per_line == 0) { - ets_printf ("\n"); - } - } - ets_printf ("\n"); -} diff --git a/cpu/esp8266/vendor/esp-idf/esp8266/source/ets_printf.c b/cpu/esp8266/vendor/esp-idf/esp8266/source/ets_printf.c index 1406d7a5048d..97f10a2dfc4c 100644 --- a/cpu/esp8266/vendor/esp-idf/esp8266/source/ets_printf.c +++ b/cpu/esp8266/vendor/esp-idf/esp8266/source/ets_printf.c @@ -25,15 +25,24 @@ #ifdef RIOT_VERSION -/* RIOT has its own putchar function which writes to UART */ -extern int putchar(int c); -#define uart_putc putchar +/* the putchar definition from stdio.h can't be used here */ +#undef putchar -#else /* RIOT_VERSION */ +/* inidicator is true when stdio is initialized */ +int stdio_is_initialized = 0; + +#endif /* RIOT_VERSION */ #ifndef CONFIG_CONSOLE_UART_NONE static void uart_putc(int c) { +#ifdef RIOT_VERSION + if (stdio_is_initialized) { + putchar(c); + return; + } +#endif /* RIOT_VERSION */ + while (1) { uint32_t fifo_cnt = READ_PERI_REG(UART_STATUS(CONFIG_CONSOLE_UART_NUM)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S); @@ -47,8 +56,6 @@ static void uart_putc(int c) #define uart_putc(_c) { } #endif -#endif /* RIOT_VERSION */ - int __attribute__ ((weak)) ets_putc(int c) { #ifdef CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF diff --git a/cpu/esp8266/vendor/esp/xtensa_ops.h b/cpu/esp8266/vendor/esp/xtensa_ops.h deleted file mode 100644 index 12006843aab3..000000000000 --- a/cpu/esp8266/vendor/esp/xtensa_ops.h +++ /dev/null @@ -1,65 +0,0 @@ -/** xtensa_ops.h - * - * Special macros/etc which deal with Xtensa-specific architecture/CPU - * considerations. - * - * Part of esp-open-rtos - * Copyright (C) 2015 Superhouse Automation Pty Ltd - * BSD Licensed as described in the file LICENSE - */ - -/* -Copyright (c) 2015, SuperHouse Automation Pty Ltd -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef XTENSA_OPS_H -#define XTENSA_OPS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* Read stack pointer to variable. - * - * Note that the compiler will push a stack frame (minimum 16 bytes) - * in the prelude of a C function that calls any other functions. - */ -#define SP(var) __asm__ volatile ("mov %0, a1" : "=r" (var)) - -/* Read the function return address to a variable. - * - * Depends on the containing function being simple enough that a0 is - * being used as a working register. - */ -#define RETADDR(var) __asm__ volatile ("mov %0, a0" : "=r" (var)) - -// GCC macros for reading, writing, and exchanging Xtensa processor special -// registers: - -#define RSR(var, reg) __asm__ volatile ("rsr %0, " #reg : "=r" (var)); -#define WSR(var, reg) __asm__ volatile ("wsr %0, " #reg : : "r" (var)); -#define XSR(var, reg) __asm__ volatile ("xsr %0, " #reg : "+r" (var)); - -// GCC macros for performing associated "*sync" opcodes - -#define ISYNC() __asm__ volatile ( "isync" ) -#define RSYNC() __asm__ volatile ( "rsync" ) -#define ESYNC() __asm__ volatile ( "esync" ) -#define DSYNC() __asm__ volatile ( "dsync" ) - -#ifdef __cplusplus -} -#endif - -#endif /* XTENSA_OPS_H */ diff --git a/cpu/esp_common/Makefile b/cpu/esp_common/Makefile index 11c71bbbeb1f..98aa75ff8e7a 100644 --- a/cpu/esp_common/Makefile +++ b/cpu/esp_common/Makefile @@ -1,8 +1,17 @@ # add a list of subdirectories, that should also be build +DIRS += periph DIRS += vendor -ifneq (, $(filter esp_now, $(USEMODULE))) - DIRS += esp-now +ifneq (,$(filter esp_freertos_common,$(USEMODULE))) + DIRS += freertos +endif + +ifneq (,$(filter esp_now,$(USEMODULE))) + DIRS += esp-now +endif + +ifneq (,$(filter esp_wifi,$(USEMODULE))) + DIRS += esp-wifi endif include $(RIOTBASE)/Makefile.base diff --git a/cpu/esp_common/Makefile.dep b/cpu/esp_common/Makefile.dep new file mode 100644 index 000000000000..58c80f4b85f9 --- /dev/null +++ b/cpu/esp_common/Makefile.dep @@ -0,0 +1,31 @@ +# additional modules dependencies + +# each device has SPI flash memory, but it has to be enabled explicitly +ifneq (,$(filter esp_spiffs,$(USEMODULE))) + USEMODULE += spiffs +endif + +ifneq (,$(filter esp_freertos,$(USEMODULE))) + USEMODULE += esp_freertos_common +endif + +ifneq (,$(filter esp_now,$(USEMODULE))) + USEMODULE += esp_wifi_any +endif + +ifneq (,$(filter esp_wifi,$(USEMODULE))) + USEMODULE += esp_wifi_any + USEMODULE += netdev_eth +endif + +ifneq (,$(filter esp_wifi_any,$(USEMODULE))) + USEMODULE += netopt + USEMODULE += xtimer +endif + +ifneq (,$(filter esp_idf_heap,$(USEMODULE))) + LINKFLAGS += -Wl,-wrap,_malloc_r + LINKFLAGS += -Wl,-wrap,_calloc_r + LINKFLAGS += -Wl,-wrap,_realloc_r + LINKFLAGS += -Wl,-wrap,_free_r +endif diff --git a/cpu/esp_common/Makefile.features b/cpu/esp_common/Makefile.features new file mode 100644 index 000000000000..7539b394f8a9 --- /dev/null +++ b/cpu/esp_common/Makefile.features @@ -0,0 +1,9 @@ +# MCU defined features that are provided independent on board definitions + +FEATURES_PROVIDED += arch_32bit +FEATURES_PROVIDED += cpp +FEATURES_PROVIDED += periph_cpuid +FEATURES_PROVIDED += periph_hwrng +FEATURES_PROVIDED += periph_pm +FEATURES_PROVIDED += periph_timer +FEATURES_PROVIDED += ssp diff --git a/cpu/esp_common/Makefile.include b/cpu/esp_common/Makefile.include new file mode 100644 index 000000000000..597ba6c2728b --- /dev/null +++ b/cpu/esp_common/Makefile.include @@ -0,0 +1,222 @@ +# Default compile configurations + +# FLASH_MODE=[ dout | dio | qout | qio ] +# use flash mode dout by default to keep GPIO9 and GPIO10 free for use +FLASH_MODE ?= dout + +# SPECIAL module dependencies +# cannot be done in Makefile.dep since Makefile.dep is included too late + +ifneq (,$(filter netdev_default gnrc_netdev_default,$(USEMODULE))) + ifneq (,$(filter lwip,$(USEMODULE))) + # for lwip, use esp_wifi as default netdev if no other netdev is enabled + ifeq (,$(filter esp_eth,$(USEMODULE))) + USEMODULE += esp_wifi + endif + else + # otherwise use esp_now as default netdev if no other netdev is enabled + ifeq (,$(filter esp_wifi esp_eth,$(USEMODULE))) + USEMODULE += esp_now + endif + endif +endif + +ifneq (,$(filter esp_gdbstub,$(USEMODULE))) + USEMODULE += esp_gdb +endif + +ifneq (,$(filter log_color,$(USEMODULE))) + USEMODULE += esp_log_colored +endif + +ifneq (,$(filter 4 5,$(LOG_LEVEL))) + USEMODULE += esp_log_startup +endif + +# ESP* pseudomodules + +PSEUDOMODULES += esp_gdb +PSEUDOMODULES += esp_i2c_sw +PSEUDOMODULES += esp_log_colored +PSEUDOMODULES += esp_log_tagged +PSEUDOMODULES += esp_log_startup +PSEUDOMODULES += esp_qemu +PSEUDOMODULES += esp_spiffs +PSEUDOMODULES += esp_wifi_any + +# Modules used by ESP* + +USEMODULE += esp_common +USEMODULE += esp_common_periph +USEMODULE += esp_freertos +USEMODULE += esp_idf +USEMODULE += log +USEMODULE += newlib +USEMODULE += periph +USEMODULE += periph_hwrng +USEMODULE += periph_flash +USEMODULE += periph_uart +USEMODULE += random +USEMODULE += stdio_uart +USEMODULE += xtensa + +# Common includes + +INCLUDES += -I$(RIOTBOARD)/common/$(CPU)/include +INCLUDES += -I$(RIOTCPU)/esp_common +INCLUDES += -I$(RIOTCPU)/esp_common/include +INCLUDES += -I$(RIOTCPU)/esp_common/include/freertos +INCLUDES += -I$(RIOTCPU)/esp_common/vendor/ +INCLUDES += -I$(RIOTCPU)/esp_common/vendor/esp + +# Flags + +CFLAGS += -Wno-unused-parameter -Wformat=0 +CFLAGS += -mlongcalls -mtext-section-literals -fstrict-volatile-bitfields +CFLAGS += -fdata-sections -ffunction-sections -fzero-initialized-in-bss + +OPTIONAL_CFLAGS_BLACKLIST += -Wformat-overflow +OPTIONAL_CFLAGS_BLACKLIST += -Wformat-truncation +OPTIONAL_CFLAGS_BLACKLIST += -gz + +ASFLAGS += --longcalls --text-section-literals + +# thin archives trigger a reboot loop - see #12258, #12035, #12346 +ARFLAGS = rcs + +CFLAGS_DBG ?= -ggdb -g3 +CFLAGS_OPT ?= -Os + +# override default CFLAGS_OPT in case module esp_gdb is enabled +ifneq (,$(filter esp_gdb,$(USEMODULE))) + CFLAGS_OPT = -Og +endif + +CFLAGS += $(CFLAGS_OPT) $(CFLAGS_DBG) + +# add -DQEMU for qemu +ifneq (,$(filter esp_qemu,$(USEMODULE))) + CFLAGS += -DQEMU +endif + +# use 32 priority levels if any WiFi interface or the ETH interface is used +ifneq (,$(filter esp_wifi esp_now esp_eth,$(USEMODULE))) + CFLAGS += -DSCHED_PRIO_LEVELS=32 +endif + +ifneq (,$(filter esp_wifi esp_now esp_eth,$(USEMODULE))) + INCLUDES += -I$(RIOTCPU)/esp_common/esp-wifi +endif + +# The threads for handling the ESP hardware have the priorities from 2 to 4. +# The priority of lwIP TCPIP thread should be lower than these priorities. +ifneq (,$(filter lwip,$(USEMODULE))) + CFLAGS += -DTCPIP_THREAD_PRIO=5 +endif + +# if SPI RAM is enabled, the qout flash mode has to be used +ifneq (,$(filter esp_spi_ram,$(USEMODULE))) + FLASH_MODE = qout + CFLAGS += -DFLASH_MODE_QOUT=1 +else + ifeq ($(FLASH_MODE), qio) + CFLAGS += -DFLASH_MODE_QIO=1 + endif + ifeq ($(FLASH_MODE), qout) + CFLAGS += -DFLASH_MODE_QOUT=1 + endif + ifeq ($(FLASH_MODE), dio) + CFLAGS += -DFLASH_MODE_DIO=1 + endif + ifeq ($(FLASH_MODE), dout) + CFLAGS += -DFLASH_MODE_DOUT=1 + endif +endif + +BASELIBS += -lhal -lg -lc + +LINKFLAGS += $(CFLAGS_OPT) $(CFLAGS_DBG) +LINKFLAGS += -L$(ESP_SDK_DIR)/components/$(CPU) +LINKFLAGS += -L$(ESP_SDK_DIR)/components/$(CPU)/lib +LINKFLAGS += -nostdlib -Wl,-gc-sections -Wl,-static + +# LINKFLAGS += -Wl,--verbose +# LINKFLAGS += -Wl,--print-gc-sections + +ifneq (,$(filter esp_log_colored,$(USEMODULE))) + BOOTLOADER_COLOR = _colors +endif + +ifneq (,$(filter esp_log_startup,$(USEMODULE))) + BOOTLOADER_INFO = _info +endif + +BOOTLOADER_BIN = bootloader$(BOOTLOADER_COLOR)$(BOOTLOADER_INFO).bin + +ESPTOOL ?= $(RIOTTOOLS)/esptool/esptool.py + +# The ELFFILE is the base one used for flashing +FLASHFILE ?= $(ELFFILE) + +# configure preflasher to convert .elf to .bin before flashing +PREFLASHER = $(ESPTOOL) +PREFFLAGS = --chip $(FLASH_CHIP) elf2image +PREFFLAGS += --flash_mode $(FLASH_MODE) --flash_size $(FLASH_SIZE)MB +PREFFLAGS += --flash_freq $(FLASH_FREQ) $(FLASH_OPTS) +PREFFLAGS += -o $(FLASHFILE).bin $(FLASHFILE); +PREFFLAGS += printf "\n" > $(BINDIR)/partitions.csv; +PREFFLAGS += printf "nvs, data, nvs, 0x9000, 0x6000\n" >> $(BINDIR)/partitions.csv; +PREFFLAGS += printf "phy_init, data, phy, 0xf000, 0x1000\n" >> $(BINDIR)/partitions.csv; +PREFFLAGS += printf "factory, app, factory, 0x10000, " >> $(BINDIR)/partitions.csv; +PREFFLAGS += ls -l $(FLASHFILE).bin | awk '{ print $$5 }' >> $(BINDIR)/partitions.csv; + +PREFFLAGS += python $(RIOTTOOLS)/esptool/gen_esp32part.py +PREFFLAGS += --verify $(BINDIR)/partitions.csv $(BINDIR)/partitions.bin +FLASHDEPS += preflash + +# flasher configuration +ifneq (,$(filter esp_qemu,$(USEMODULE))) + FLASHER = dd + FFLAGS += if=/dev/zero bs=1M count=$(FLASH_SIZE) | + FFLAGS += tr "\\000" "\\377" > tmp.bin && cat tmp.bin | + FFLAGS += head -c $$(($(BOOTLOADER_POS))) | + FFLAGS += cat - $(RIOTCPU)/$(CPU)/bin/$(BOOTLOADER_BIN) tmp.bin | + FFLAGS += head -c $$((0x8000)) | + FFLAGS += cat - $(BINDIR)/partitions.bin tmp.bin | + FFLAGS += head -c $$((0x10000)) | + FFLAGS += cat - $(FLASHFILE).bin tmp.bin | + FFLAGS += head -c $(FLASH_SIZE)MB > $(BINDIR)/$(CPU)flash.bin && rm tmp.bin; +else + PROGRAMMER_SPEED ?= 460800 + FLASHER = $(ESPTOOL) + FFLAGS += --chip $(FLASH_CHIP) --port $(PROG_DEV) --baud $(PROGRAMMER_SPEED) + FFLAGS += --before default_reset write_flash -z + FFLAGS += --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) + FFLAGS += $(BOOTLOADER_POS) $(RIOTCPU)/$(CPU)/bin/$(BOOTLOADER_BIN) + FFLAGS += 0x8000 $(BINDIR)/partitions.bin + FFLAGS += 0x10000 $(FLASHFILE).bin +endif + +# increase the test timeout for file system tests that use the SPI flash drive + +ifneq (,$(filter spiffs,$(USEMODULE))) + export RIOT_TEST_TIMEOUT = 120 +endif + +ifneq (,$(filter littlefs,$(USEMODULE))) + export RIOT_TEST_TIMEOUT = 120 +endif + +# increase the number of netif for each enabled network interface + +ifneq (,$(filter esp_wifi,$(USEMODULE))) + $(eval GNRC_NETIF_NUMOF=$(shell echo $$(($(GNRC_NETIF_NUMOF)+1)))) +endif + +ifneq (,$(filter esp_now,$(USEMODULE))) + $(eval GNRC_NETIF_NUMOF=$(shell echo $$(($(GNRC_NETIF_NUMOF)+1)))) +endif + +ifneq (,$(filter esp_eth,$(USEMODULE))) + $(eval GNRC_NETIF_NUMOF=$(shell echo $$(($(GNRC_NETIF_NUMOF)+1)))) +endif diff --git a/cpu/esp_common/esp-now/doc.txt b/cpu/esp_common/esp-now/doc.txt index 63ddf4501974..61cd86e9f503 100644 --- a/cpu/esp_common/esp-now/doc.txt +++ b/cpu/esp_common/esp-now/doc.txt @@ -9,6 +9,8 @@ /** * @defgroup cpu_esp_common_esp_now ESP-NOW netdev interface * @ingroup cpu_esp_common + * @ingroup cpu_esp32 + * @ingroup cpu_esp8266 * @brief WiFi based ESP-NOW network device driver * * @author Gunar Schorcht diff --git a/cpu/esp_common/esp-wifi/Makefile b/cpu/esp_common/esp-wifi/Makefile new file mode 100644 index 000000000000..c92f98eb6d9e --- /dev/null +++ b/cpu/esp_common/esp-wifi/Makefile @@ -0,0 +1,9 @@ +MODULE=esp_wifi + +ifeq (esp8266,$(CPU)) + # we have to do it in that way to avoid that pkg/lwip is found first + CFLAGS += -I$(ESP8266_RTOS_SDK_DIR)/components/lwip/lwip/src/include + CFLAGS += -I$(ESP8266_RTOS_SDK_DIR)/components/lwip/port/esp8266/include/ +endif + +include $(RIOTBASE)/Makefile.base diff --git a/cpu/esp8266/esp-wifi/doc.txt b/cpu/esp_common/esp-wifi/doc.txt similarity index 79% rename from cpu/esp8266/esp-wifi/doc.txt rename to cpu/esp_common/esp-wifi/doc.txt index 97031d3a76a6..d04109e767a9 100644 --- a/cpu/esp8266/esp-wifi/doc.txt +++ b/cpu/esp_common/esp-wifi/doc.txt @@ -7,14 +7,16 @@ */ /** - * @defgroup cpu_esp8266_esp_wifi ESP8266 WiFi netdev interface + * @defgroup cpu_esp_common_esp_wifi ESP-WiFi netdev interface + * @ingroup cpu_esp_common + * @ingroup cpu_esp32 * @ingroup cpu_esp8266 - * @brief Network device driver for the ESP8266 WiFi interface + * @brief Network device driver for the ESP SoC WiFi interface * * @author Gunar Schorcht -This module realizes a `netdev` interface for the built-in WiFi interface -of ESP8266. To enable the WiFi interface, module `esp_wifi` has to be used. +This module realizes a `netdev` interface for the built-in WiFi interface of +ESP SoCs. To enable the WiFi interface, module `esp_wifi` has to be used. Furthermore, the following configuration parameters have to be defined: Configuration Parameter | Description @@ -34,7 +36,7 @@ make -C examples/gnrc_networking BOARD=... ``` @note The Wifi network interface (module `esp_wifi`) and the -\ref esp8266_esp_now_network_interface "ESP-NOW network interface" (module `esp_now`) +ESP-NOW network interface (module `esp_now`) can be used simultaneously, for example, to realize a border router for a mesh network which uses ESP-NOW. */ diff --git a/cpu/esp8266/esp-wifi/esp_wifi_gnrc.c b/cpu/esp_common/esp-wifi/esp_wifi_gnrc.c similarity index 90% rename from cpu/esp8266/esp-wifi/esp_wifi_gnrc.c rename to cpu/esp_common/esp-wifi/esp_wifi_gnrc.c index 157dd4cc282a..56e1fcf9472e 100644 --- a/cpu/esp8266/esp-wifi/esp_wifi_gnrc.c +++ b/cpu/esp_common/esp-wifi/esp_wifi_gnrc.c @@ -7,20 +7,22 @@ */ /** - * @ingroup cpu_esp8266_esp_wifi + * @ingroup cpu_esp_common_esp_wifi * @{ * * @file - * @brief GNRC network interface part for ESP8266 WiFi interface + * @brief GNRC network interface part for ESP WiFi interface * * @author Gunar Schorcht */ #if defined(MODULE_ESP_WIFI) && defined(MODULE_GNRC_NETIF_ETHERNET) +#include "net/ethernet.h" +#include "net/gnrc/netif/ethernet.h" + #include "esp_wifi_params.h" #include "esp_wifi_netdev.h" -#include "net/gnrc/netif/ethernet.h" /** the only ESP WiFi device */ extern esp_wifi_netdev_t _esp_wifi_dev; diff --git a/cpu/esp8266/esp-wifi/esp_wifi_netdev.c b/cpu/esp_common/esp-wifi/esp_wifi_netdev.c similarity index 97% rename from cpu/esp8266/esp-wifi/esp_wifi_netdev.c rename to cpu/esp_common/esp-wifi/esp_wifi_netdev.c index 388ea8a05999..c635c8ede285 100644 --- a/cpu/esp8266/esp-wifi/esp_wifi_netdev.c +++ b/cpu/esp_common/esp-wifi/esp_wifi_netdev.c @@ -7,11 +7,11 @@ */ /** - * @ingroup cpu_esp8266_esp_wifi + * @ingroup cpu_esp_common_esp_wifi * @{ * * @file - * @brief Network device driver for the ESP8266 WiFi interface + * @brief Network device driver for the ESP SoCs WiFi interface * * @author Gunar Schorcht */ @@ -22,9 +22,6 @@ #include #include -#include "net/gnrc/netif/ethernet.h" -#include "net/gnrc/netif/raw.h" -#include "net/gnrc.h" #include "net/ethernet.h" #include "net/netdev/eth.h" #include "od.h" @@ -50,9 +47,6 @@ #include "debug.h" #include "log.h" -#define SYSTEM_EVENT_WIFI_RX_DONE (SYSTEM_EVENT_MAX + 3) -#define SYSTEM_EVENT_WIFI_TX_DONE (SYSTEM_EVENT_MAX + 4) - #define ESP_WIFI_DEBUG(f, ...) \ DEBUG("[esp_wifi] %s: " f "\n", __func__, ## __VA_ARGS__) @@ -77,7 +71,7 @@ /** * The SDK interface of the WiFi module uses the lwIP `pbuf` structure for * packets sent to and received from the WiFi interface. For compatibility - * reasons with the binary SDK libraries we need to incclude the SDK lwIP + * reasons with the binary SDK libraries we need to include the SDK lwIP * `pbuf` header here. * * To avoid compilation errors, we need to undefine all our pkg/lwIP settings @@ -321,9 +315,8 @@ esp_err_t _esp_wifi_rx_cb(void *buffer, uint16_t len, void *eb) ESP_WIFI_DEBUG("buf=%p len=%d eb=%p", buffer, len, eb); /* - * The ring buffer uses a single byte for the pkt length, followed by the mac address, - * followed by the actual packet data. The MTU for ESP-NOW is 250 bytes, so len will never - * exceed the limits of a byte as the mac address length is not included. + * The ring buffer uses two bytes for the pkt length, followed by the + * actual packet data. */ if (ringbuffer_get_free(&_esp_wifi_dev.rx_buf) < len + sizeof(uint16_t)) { ESP_WIFI_DEBUG("buffer full, dropping incoming packet of %d bytes", len); @@ -453,7 +446,7 @@ static esp_err_t IRAM_ATTR _esp_system_event_handler(void *ctx, system_event_t * else if (reason <= REASON_HANDSHAKE_TIMEOUT) { reason_str = _esp_wifi_disc_reasons[reason - INDEX_BEACON_TIMEOUT]; } - ESP_WIFI_LOG_INFO("Wifi disconnected from ssid %s, reason %d (%s)", + ESP_WIFI_LOG_INFO("WiFi disconnected from ssid %s, reason %d (%s)", event->event_info.disconnected.ssid, event->event_info.disconnected.reason, reason_str); @@ -754,7 +747,7 @@ void esp_wifi_setup (esp_wifi_netdev_t* dev) #ifndef MODULE_ESP_NOW /* if module esp_now is used, the following part is already done */ -#if MCU_ESP32 +#ifdef MCU_ESP32 extern portMUX_TYPE g_intr_lock_mux; mutex_init(&g_intr_lock_mux); #endif @@ -820,5 +813,6 @@ void esp_wifi_setup (esp_wifi_netdev_t* dev) dev->event_conn = 0; dev->event_disc = 0; } + #endif /* MODULE_ESP_WIFI */ /**@}*/ diff --git a/cpu/esp8266/esp-wifi/esp_wifi_netdev.h b/cpu/esp_common/esp-wifi/esp_wifi_netdev.h similarity index 93% rename from cpu/esp8266/esp-wifi/esp_wifi_netdev.h rename to cpu/esp_common/esp-wifi/esp_wifi_netdev.h index 21ff2b5a7fa2..3a04d0ffd730 100644 --- a/cpu/esp8266/esp-wifi/esp_wifi_netdev.h +++ b/cpu/esp_common/esp-wifi/esp_wifi_netdev.h @@ -7,11 +7,11 @@ */ /** - * @ingroup cpu_esp8266_esp_wifi + * @ingroup cpu_esp_common_esp_wifi * @{ * * @file - * @brief Network device driver for the ESP32 WiFi interface + * @brief Network device driver for the ESP SoCs WiFi interface * * @author Gunar Schorcht */ diff --git a/cpu/esp8266/esp-wifi/esp_wifi_params.h b/cpu/esp_common/esp-wifi/esp_wifi_params.h similarity index 90% rename from cpu/esp8266/esp-wifi/esp_wifi_params.h rename to cpu/esp_common/esp-wifi/esp_wifi_params.h index 9298c2d4a30d..3ad1dc735762 100644 --- a/cpu/esp8266/esp-wifi/esp_wifi_params.h +++ b/cpu/esp_common/esp-wifi/esp_wifi_params.h @@ -7,12 +7,12 @@ */ /** - * @ingroup cpu_esp8266_esp_wifi - * @ingroup cpu_esp8266_conf + * @ingroup cpu_esp_common_esp_wifi + * @ingroup cpu_esp_common_conf * @{ * * @file - * @brief Parameters for the ESP32 WiFi netdev interface + * @brief Parameters for the ESP SoCs WiFi netdev interface * * @author Gunar Schorcht */ diff --git a/cpu/esp8266/esp_events.c b/cpu/esp_common/esp_events.c similarity index 98% rename from cpu/esp8266/esp_events.c rename to cpu/esp_common/esp_events.c index 13a6bfb00a44..a1640370b28f 100644 --- a/cpu/esp8266/esp_events.c +++ b/cpu/esp_common/esp_events.c @@ -7,7 +7,7 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @{ * * @file diff --git a/cpu/esp8266/exceptions.c b/cpu/esp_common/exceptions.c similarity index 85% rename from cpu/esp8266/exceptions.c rename to cpu/esp_common/exceptions.c index a81efb41fd32..befe2677dae8 100644 --- a/cpu/esp8266/exceptions.c +++ b/cpu/esp_common/exceptions.c @@ -7,19 +7,16 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @{ * * @file - * @brief ESP8266 exception handling + * @brief ESP SoCs exception handling * * @author Gunar Schorcht * @} */ -#define ENABLE_DEBUG (0) -#include "debug.h" - #include #include #include @@ -31,10 +28,12 @@ #include "esp_common.h" #include "esp/common_macros.h" #include "esp/xtensa_ops.h" -#include "sdk/ets.h" #include "xtensa/corebits.h" #include "xtensa/xtensa_api.h" +#define ENABLE_DEBUG (0) +#include "debug.h" + extern void heap_stats(void); static const char* exception_names [] = @@ -85,17 +84,32 @@ void IRAM NORETURN exception_handler (XtExcFrame *frame) { uint32_t excsave1; uint32_t epc1; - uint32_t epc2; - uint32_t epc3; RSR(excsave1, excsave1); RSR(epc1, epc1); +#if XCHAL_NMILEVEL >= 2 + uint32_t epc2; RSR(epc2, epc2); +#endif +#if XCHAL_NMILEVEL >= 3 + uint32_t epc3; RSR(epc3, epc3); - -#ifdef MCU_ESP32 +#endif +#if XCHAL_NMILEVEL >= 4 uint32_t epc4; RSR(epc4, epc4); #endif +#if XCHAL_NMILEVEL >= 5 + uint32_t epc5; + RSR(epc5, epc5); +#endif +#if XCHAL_NMILEVEL >= 6 + uint32_t epc6; + RSR(epc6, epc6); +#endif +#if XCHAL_NMILEVEL >= 7 + uint32_t epc7; + RSR(epc7, epc7); +#endif ets_printf("EXCEPTION!! exccause=%d (%s) @%08x excvaddr=%08x\n", frame->exccause, exception_names[frame->exccause], @@ -117,13 +131,25 @@ void IRAM NORETURN exception_handler (XtExcFrame *frame) ets_printf("exccause: %08x\t", frame->exccause); ets_printf("excvaddr: %08x\n", frame->excvaddr); ets_printf("epc1 : %08x\t", epc1); +#if XCHAL_NMILEVEL >= 2 ets_printf("epc2 : %08x\t", epc2); +#endif +#if XCHAL_NMILEVEL >= 3 ets_printf("epc3 : %08x\t", epc3); -#ifdef MCU_ESP32 +#endif +#if XCHAL_NMILEVEL >= 4 ets_printf("epc4 : %08x\n", epc4); -#else /* MCU_ESP32 */ - ets_printf("epc3 : %08x\n", epc3); -#endif /* MCU_ESP32 */ +#endif +#if XCHAL_NMILEVEL >= 5 + ets_printf("epc5 : %08x\t", epc5); +#endif +#if XCHAL_NMILEVEL >= 6 + ets_printf("epc6 : %08x\t", epc6); +#endif +#if XCHAL_NMILEVEL >= 7 + ets_printf("epc7 : %08x\t", epc7); +#endif + ets_printf("\n"); ets_printf("a0 : %08x\t", frame->a0); ets_printf("a1 : %08x\t", frame->a1); ets_printf("a2 : %08x\t", frame->a2); @@ -154,9 +180,7 @@ void IRAM NORETURN exception_handler (XtExcFrame *frame) One option is to break the execution and wait for the WDT reset. Maybe there is better way. If debugger is active, 'break 0,0' stops the execution in debugger. */ - /* __asm__ volatile ("break 0,0"); */ - /* hard reset */ - __asm__ volatile (" call0 0x40000080 "); + __asm__ volatile ("break 0,0"); UNREACHABLE(); } @@ -174,12 +198,14 @@ void init_exceptions (void) void IRAM NORETURN panic_arch(void) { - #if defined(DEVELHELP) +#if defined(DEVELHELP) heap_stats(); - #endif - - /* hard reset */ - __asm__ volatile (" call0 0x40000080 "); + /* break in debugger or reboot after WDT */ + __asm__ volatile ("break 0,0"); +#else /* DEVELHELP */ + /* restart */ + pm_reboot(); +#endif /* DEVELHELP */ UNREACHABLE(); } diff --git a/cpu/esp32/esp-wifi/Makefile b/cpu/esp_common/freertos/Makefile similarity index 56% rename from cpu/esp32/esp-wifi/Makefile rename to cpu/esp_common/freertos/Makefile index 1aee4b75d3ca..470278a43a2a 100644 --- a/cpu/esp32/esp-wifi/Makefile +++ b/cpu/esp_common/freertos/Makefile @@ -1,3 +1,3 @@ -MODULE=esp_wifi +MODULE=esp_freertos_common include $(RIOTBASE)/Makefile.base diff --git a/cpu/esp8266/freertos/event_groups.c b/cpu/esp_common/freertos/event_groups.c similarity index 100% rename from cpu/esp8266/freertos/event_groups.c rename to cpu/esp_common/freertos/event_groups.c diff --git a/cpu/esp32/freertos/portable.c b/cpu/esp_common/freertos/portable.c similarity index 96% rename from cpu/esp32/freertos/portable.c rename to cpu/esp_common/freertos/portable.c index 5d787fbb4e10..b5b29a880894 100644 --- a/cpu/esp32/freertos/portable.c +++ b/cpu/esp_common/freertos/portable.c @@ -10,7 +10,7 @@ #ifndef DOXYGEN -#define ENABLE_DEBUG 0 +#define ENABLE_DEBUG (0) #include "debug.h" #include diff --git a/cpu/esp8266/freertos/queue.c b/cpu/esp_common/freertos/queue.c similarity index 99% rename from cpu/esp8266/freertos/queue.c rename to cpu/esp_common/freertos/queue.c index 6d1c07290411..3adeaa46e629 100644 --- a/cpu/esp8266/freertos/queue.c +++ b/cpu/esp_common/freertos/queue.c @@ -60,10 +60,9 @@ QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, uint32_t queue_size = uxQueueLength * uxItemSize; _queue_t* queue = malloc(sizeof(_queue_t) + queue_size); - if (!queue) { - return NULL; - } + assert(queue != NULL); + memset(queue, 0, sizeof(_queue_t) + queue_size); queue->type = ucQueueType; queue->receiving.next = NULL; queue->sending.next = NULL; diff --git a/cpu/esp8266/freertos/semphr.c b/cpu/esp_common/freertos/semphr.c similarity index 100% rename from cpu/esp8266/freertos/semphr.c rename to cpu/esp_common/freertos/semphr.c diff --git a/cpu/esp8266/freertos/task.c b/cpu/esp_common/freertos/task.c similarity index 90% rename from cpu/esp8266/freertos/task.c rename to cpu/esp_common/freertos/task.c index 36ed86a08897..4309b5e05334 100644 --- a/cpu/esp8266/freertos/task.c +++ b/cpu/esp_common/freertos/task.c @@ -162,7 +162,14 @@ void vTaskEnterCritical( portMUX_TYPE *mux ) /* acquire the mutex with interrupts disabled */ if (mux) { - mutex_lock(mux); /* TODO should be only a spin lock */ + /* Locking the given mutex does not work here, as this function can also + be called in the interrupt context. Therefore, the given mutex is not + used. Instead, the basic default FreeRTOS mechanism for critical + sections is used by simply disabling interrupts. Since context + switches for the ESPs are also based on interrupts, there is no + possibility that another thread will enter the critical section + once the interrupts are disabled. */ + /* mutex_lock(mux); */ /* TODO should be only a spin lock */ } /* increment nesting counter and save old interrupt level */ @@ -189,7 +196,7 @@ void vTaskExitCritical( portMUX_TYPE *mux ) /* release the mutex with interrupts disabled */ if (mux) { - mutex_unlock(mux); /* TODO should be only a spin lock */ + /* mutex_unlock(mux); */ /* TODO should be only a spin lock */ } /* decrement nesting counter and restore old interrupt level */ diff --git a/cpu/esp8266/freertos/timers.c b/cpu/esp_common/freertos/timers.c similarity index 100% rename from cpu/esp8266/freertos/timers.c rename to cpu/esp_common/freertos/timers.c diff --git a/cpu/esp8266/include/cpu.h b/cpu/esp_common/include/cpu.h similarity index 89% rename from cpu/esp8266/include/cpu.h rename to cpu/esp_common/include/cpu.h index 021d0a624732..e28ef2139d6f 100644 --- a/cpu/esp8266/include/cpu.h +++ b/cpu/esp_common/include/cpu.h @@ -7,11 +7,11 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @{ * * @file - * @brief CPU common functions + * @brief CPU common functions for ESP SoCs * * @author Gunar Schorcht */ diff --git a/cpu/esp8266/include/esp_common.h b/cpu/esp_common/include/esp_common.h similarity index 97% rename from cpu/esp8266/include/esp_common.h rename to cpu/esp_common/include/esp_common.h index f81d80eb6a9e..1a855ea729f3 100644 --- a/cpu/esp8266/include/esp_common.h +++ b/cpu/esp_common/include/esp_common.h @@ -7,11 +7,11 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @{ * * @file - * @brief Common helper macros + * @brief Common helper macros for ESP SoCs * * @author Gunar Schorcht * diff --git a/cpu/esp8266/include/esp_common_log.h b/cpu/esp_common/include/esp_common_log.h similarity index 98% rename from cpu/esp8266/include/esp_common_log.h rename to cpu/esp_common/include/esp_common_log.h index c9e2bf9f27d6..d93722807f75 100644 --- a/cpu/esp8266/include/esp_common_log.h +++ b/cpu/esp_common/include/esp_common_log.h @@ -7,11 +7,11 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @{ * * @file - * @brief Common log macros + * @brief Common log macros for ESP SoCs * * @author Gunar Schorcht * diff --git a/cpu/esp8266/include/exceptions.h b/cpu/esp_common/include/exceptions.h similarity index 86% rename from cpu/esp8266/include/exceptions.h rename to cpu/esp_common/include/exceptions.h index 611647d076a1..15d4dc729a04 100644 --- a/cpu/esp8266/include/exceptions.h +++ b/cpu/esp_common/include/exceptions.h @@ -7,11 +7,11 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @{ * * @file - * @brief ESP8266 exception handling + * @brief Exception handling for ESP SoCs * * @author Gunar Schorcht * @} diff --git a/cpu/esp8266/include/freertos/FreeRTOS.h b/cpu/esp_common/include/freertos/FreeRTOS.h similarity index 97% rename from cpu/esp8266/include/freertos/FreeRTOS.h rename to cpu/esp_common/include/freertos/FreeRTOS.h index e333cfd72249..0331206d6ec8 100644 --- a/cpu/esp8266/include/freertos/FreeRTOS.h +++ b/cpu/esp_common/include/freertos/FreeRTOS.h @@ -22,7 +22,7 @@ extern "C" { #define configMAX_PRIORITIES SCHED_PRIO_LEVELS #ifndef configASSERT -#define configASSERT assert +#define configASSERT assert #endif #define portTICK_PERIOD_MS 10 diff --git a/cpu/esp8266/include/freertos/event_groups.h b/cpu/esp_common/include/freertos/event_groups.h similarity index 100% rename from cpu/esp8266/include/freertos/event_groups.h rename to cpu/esp_common/include/freertos/event_groups.h diff --git a/cpu/esp8266/include/freertos/portmacro.h b/cpu/esp_common/include/freertos/portmacro.h similarity index 92% rename from cpu/esp8266/include/freertos/portmacro.h rename to cpu/esp_common/include/freertos/portmacro.h index b0df76c65a60..6927fbfcafe8 100644 --- a/cpu/esp8266/include/freertos/portmacro.h +++ b/cpu/esp_common/include/freertos/portmacro.h @@ -32,29 +32,28 @@ extern "C" { #define portYIELD_FROM_ISR thread_yield_higher +#define portENTER_CRITICAL vTaskEnterCritical +#define portEXIT_CRITICAL vTaskExitCritical +#define portENTER_CRITICAL_ISR vTaskEnterCritical +#define portEXIT_CRITICAL_ISR vTaskExitCritical +#define portENTER_CRITICAL_NESTED irq_disable +#define portEXIT_CRITICAL_NESTED irq_restore + #ifdef MCU_ESP32 #define portNUM_PROCESSORS 2 #define xPortGetCoreID() PRO_CPU_NUM -#define portENTER_CRITICAL(pm) mutex_lock(pm) -#define portEXIT_CRITICAL(pm) mutex_unlock(pm) -#define portENTER_CRITICAL_NESTED irq_disable -#define portEXIT_CRITICAL_NESTED irq_restore - -#define portENTER_CRITICAL_ISR vTaskEnterCritical -#define portEXIT_CRITICAL_ISR vTaskExitCritical - #else /* MCU_ESP32 */ #define portNUM_PROCESSORS 1 #define xPortGetCoreID() PRO_CPU_NUM -#define portENTER_CRITICAL vTaskEnterCritical -#define portEXIT_CRITICAL vTaskExitCritical - #endif /* MCU_ESP32 */ +extern void vTaskEnterCritical(portMUX_TYPE *mux); +extern void vTaskExitCritical(portMUX_TYPE *mux); + #ifdef __cplusplus } #endif diff --git a/cpu/esp8266/include/freertos/queue.h b/cpu/esp_common/include/freertos/queue.h similarity index 100% rename from cpu/esp8266/include/freertos/queue.h rename to cpu/esp_common/include/freertos/queue.h diff --git a/cpu/esp8266/include/freertos/semphr.h b/cpu/esp_common/include/freertos/semphr.h similarity index 100% rename from cpu/esp8266/include/freertos/semphr.h rename to cpu/esp_common/include/freertos/semphr.h diff --git a/cpu/esp8266/include/freertos/task.h b/cpu/esp_common/include/freertos/task.h similarity index 93% rename from cpu/esp8266/include/freertos/task.h rename to cpu/esp_common/include/freertos/task.h index 0f0a95839007..7d99e2209d5b 100644 --- a/cpu/esp8266/include/freertos/task.h +++ b/cpu/esp_common/include/freertos/task.h @@ -14,6 +14,7 @@ #ifndef DOXYGEN #include "thread.h" +#include "freertos/FreeRTOS.h" #ifdef __cplusplus extern "C" { @@ -23,7 +24,7 @@ extern "C" { #define tskNO_AFFINITY INT_MAX #define taskDISABLE_INTERRUPTS portDISABLE_INTERRUPTS -#define taskENABLE_INTERRUPTS portENABLE_INTERRUPTS +#define taskENABLE_INTERRUPTS portENABLE_INTERRUPTS #define taskENTER_CRITICAL portENTER_CRITICAL #define taskEXIT_CRITICAL portEXIT_CRITICAL @@ -55,7 +56,7 @@ TaskHandle_t xTaskGetCurrentTaskHandle(void); void vTaskEnterCritical(portMUX_TYPE *mux); void vTaskExitCritical(portMUX_TYPE *mux); -TickType_t xTaskGetTickCount (void); +TickType_t xTaskGetTickCount(void); #ifdef __cplusplus } diff --git a/cpu/esp8266/include/freertos/timers.h b/cpu/esp_common/include/freertos/timers.h similarity index 100% rename from cpu/esp8266/include/freertos/timers.h rename to cpu/esp_common/include/freertos/timers.h diff --git a/cpu/esp8266/include/freertos/xtensa_api.h b/cpu/esp_common/include/freertos/xtensa_api.h similarity index 100% rename from cpu/esp8266/include/freertos/xtensa_api.h rename to cpu/esp_common/include/freertos/xtensa_api.h diff --git a/cpu/esp_common/include/gpio_arch_common.h b/cpu/esp_common/include/gpio_arch_common.h new file mode 100644 index 000000000000..f4e27fa1e9ea --- /dev/null +++ b/cpu/esp_common/include/gpio_arch_common.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2019 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_esp_common + * @{ + * + * @file + * @brief Architecture specific GPIO functions for ESP SoCs + * + * @author Gunar Schorcht + * @} + */ + +#ifndef GPIO_ARCH_COMMON_H +#define GPIO_ARCH_COMMON_H + +#ifndef DOXYGEN + +#ifdef __cplusplus +extern "C" { +#endif + +/** Definitions for source code compatibility with ESP-IDF */ +#define GPIO_MODE_INPUT GPIO_IN +#define GPIO_MODE_OUTPUT GPIO_OUT +#define GPIO_MODE_INPUT_OUTPUT GPIO_IN_OUT + +/** + * @brief Definition of possible GPIO usage types (for internal use only) + */ +typedef enum +{ + _GPIO = 0, /**< pin used as standard GPIO */ +#ifdef MCU_ESP32 + _ADC, /**< pin is used as ADC input */ + _CAN, /**< pin is used as CAN signal */ + _DAC, /**< pin is used as DAC output */ + _EMAC, /**< pin is used as EMAC signal */ +#endif /* MCU_ESP32 */ + _I2C, /**< pin is used as I2C signal */ + _PWM, /**< pin is used as PWM output */ + _SPI, /**< pin is used as SPI interface */ + _SPIF, /**< pin is used as SPI flash interface */ + _UART, /**< pin is used as UART interface */ + _NOT_EXIST /**< pin cannot be used at all */ +} gpio_pin_usage_t; + + +/** + * @brief Set the usage type of the pin + * @param pin GPIO pin + * @param usage GPIO pin usage type + * @return 0 on success + * -1 on error + */ +int gpio_set_pin_usage(gpio_t pin, gpio_pin_usage_t usage); + +/** + * @brief Get the usage type of the pin + * @param pin GPIO pin + * @return GPIO pin usage type on success + * _NOT_EXIST on error + */ +gpio_pin_usage_t gpio_get_pin_usage(gpio_t pin); + +/** + * @brief Get the usage type of the pin as string + * @param pin GPIO pin + * @return GPIO pin usage type string on success + * _NOT_EXIST on error + */ +const char* gpio_get_pin_usage_str(gpio_t pin); + +#ifdef __cplusplus +} +#endif + +#endif /* DOXYGEN */ +#endif /* GPIO_ARCH_COMMON_H */ diff --git a/cpu/esp_common/include/irq_arch_common.h b/cpu/esp_common/include/irq_arch_common.h new file mode 100644 index 000000000000..1cd811e5dca3 --- /dev/null +++ b/cpu/esp_common/include/irq_arch_common.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2019 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_esp_common + * @{ + * + * @file + * @brief Implementation of the kernels irq interface + * + * @author Gunar Schorcht + * + * @} + */ + +#ifndef IRQ_ARCH_COMMON_H +#define IRQ_ARCH_COMMON_H + +#include "irq.h" +#include "sched.h" +#include "thread.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Indicates the interrupt nesting depth + * + * The variable is incremented on entry into and decremented on exit from an ISR. + */ +extern volatile uint32_t irq_interrupt_nesting; + +/** + * @name Macros to enter and exit an ISR + * + * Since all the stuff is done in `_frxt_int_enter` and `_frxt_int_exit`, these + * macros are doing nothing and are kept only for source code compatibility. + * + * @{ + */ +#define irq_isr_enter() +#define irq_isr_exit() +/** @} */ + +/** + * @name Macros to enter and exit a critical region + * + * @note: since they use a local variable they can be used only in same function + * + * @{ + */ +#define critical_enter() int _irq_state = irq_disable() +#define critical_exit() irq_restore(_irq_state) +/** @} */ + +/** + * @name Macros to enter and exit a critical region with state variable + * @{ + */ +#define critical_enter_var(m) m = irq_disable() +#define critical_exit_var(m) irq_restore(m) +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* IRQ_ARCH_COMMON_H */ diff --git a/cpu/esp8266/include/log_module.h b/cpu/esp_common/include/log_module.h similarity index 91% rename from cpu/esp8266/include/log_module.h rename to cpu/esp_common/include/log_module.h index 08f566b87a25..d882d41d57dc 100644 --- a/cpu/esp8266/include/log_module.h +++ b/cpu/esp_common/include/log_module.h @@ -7,11 +7,11 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @{ * * @file - * @brief Log module to realize consistent log messages + * @brief Log module to realize consistent log messages for ESP SoCs * * @author Gunar Schorcht */ @@ -49,7 +49,7 @@ static inline void log_write(unsigned level, const char *format, ...) { else if (level == LOG_DEBUG) { \ LOG_TAG(LOG_DEBUG, E, __func__, ##__VA_ARGS__); \ } \ - } while (0) + } while (0U) #endif /* MODULE_LOG_PRINTFNOFORMAT */ diff --git a/cpu/esp8266/include/sys/types.h b/cpu/esp_common/include/sys/types.h similarity index 99% rename from cpu/esp8266/include/sys/types.h rename to cpu/esp_common/include/sys/types.h index 0c24654342e6..cff57fa2cf0b 100644 --- a/cpu/esp8266/include/sys/types.h +++ b/cpu/esp_common/include/sys/types.h @@ -7,7 +7,7 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @{ * * @file diff --git a/cpu/esp_common/include/syscalls_common.h b/cpu/esp_common/include/syscalls_common.h new file mode 100644 index 000000000000..2198194facfd --- /dev/null +++ b/cpu/esp_common/include/syscalls_common.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2019 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_esp_common + * @{ + * + * @file + * @brief Implementation of required system calls for ESP SoCs + * + * @author Gunar Schorcht + * + * @} + */ + +#ifndef SYSCALLS_COMMON_H +#define SYSCALLS_COMMON_H + +#include +#include +#include +#include + +#include "esp_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** Necessary initializations of system call functions */ +void syscalls_init(void); + +/** Determine free heap size */ +unsigned int get_free_heap_size(void); + +/** Time since boot in us (32bit version) */ +uint32_t system_get_time(void); + +/** Time since boot in ms (32bit version) */ +uint32_t system_get_time_ms(void); + +/** memset version that the compiler should not be allowed to optimize this */ +void *system_secure_memset(void *s, int c, size_t n); + +#ifdef __cplusplus +} +#endif + +#endif /* SYSCALLS_COMMON_H */ diff --git a/cpu/esp8266/include/thread_arch.h b/cpu/esp_common/include/thread_arch.h similarity index 89% rename from cpu/esp8266/include/thread_arch.h rename to cpu/esp_common/include/thread_arch.h index b4b585c67d2a..436a64e6f1a8 100644 --- a/cpu/esp8266/include/thread_arch.h +++ b/cpu/esp_common/include/thread_arch.h @@ -7,11 +7,12 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @{ * * @file - * @brief Implementation of the kernel's architecture dependent thread interface + * @brief Implementation of the kernel's architecture dependent thread + * interface for ESP SoCS * * @author Gunar Schorcht * diff --git a/cpu/esp32/include/tools.h b/cpu/esp_common/include/tools.h similarity index 85% rename from cpu/esp32/include/tools.h rename to cpu/esp_common/include/tools.h index f702978a3514..2b5291dbf8fc 100644 --- a/cpu/esp32/include/tools.h +++ b/cpu/esp_common/include/tools.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Gunar Schorcht + * Copyright (C) 2019 Gunar Schorcht * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -7,11 +7,11 @@ */ /** - * @ingroup cpu_esp32 + * @ingroup cpu_esp_common * @{ * * @file - * @brief Implementation of some tools + * @brief Implementation of some tools for ESP SoCs * * @author Gunar Schorcht * diff --git a/cpu/esp8266/include/xtensa_conf.h b/cpu/esp_common/include/xtensa_conf.h similarity index 84% rename from cpu/esp8266/include/xtensa_conf.h rename to cpu/esp_common/include/xtensa_conf.h index 594d810bf379..b165c9d0ccb4 100644 --- a/cpu/esp8266/include/xtensa_conf.h +++ b/cpu/esp_common/include/xtensa_conf.h @@ -7,11 +7,11 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @{ * * @file - * @brief Xtensa ASM code specific configuration options + * @brief Xtensa ASM code specific configuration options for ESP SoCs * * @author Gunar Schorcht */ diff --git a/cpu/esp8266/irq_arch.c b/cpu/esp_common/irq_arch.c similarity index 53% rename from cpu/esp8266/irq_arch.c rename to cpu/esp_common/irq_arch.c index c5f902cd997d..62d264f3ecd7 100644 --- a/cpu/esp8266/irq_arch.c +++ b/cpu/esp_common/irq_arch.c @@ -7,7 +7,7 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @{ * * @file @@ -42,14 +42,16 @@ volatile uint32_t irq_interrupt_nesting = 0; */ unsigned int IRAM irq_disable(void) { - uint32_t _saved_interrupt_level; + uint32_t state; /* read and set interrupt level (RSIL) */ - __asm__ volatile ("rsil %0, " XTSTR(XCHAL_EXCM_LEVEL) : "=a" (_saved_interrupt_level)); - DEBUG ("%s %02x(%02x)\n", __func__, - (_saved_interrupt_level & 0xfffffff0) | (XCHAL_EXCM_LEVEL), - _saved_interrupt_level); - return _saved_interrupt_level; + __asm__ volatile ("rsil %0, " XTSTR(XCHAL_EXCM_LEVEL) : "=a" (state) :: "memory"); + /* mask out everything else of the PS register that do not belong to + interrupt level (bits 3..0) */ + state &= 0xf; + + DEBUG("%s %02x(%02x)\n", __func__, XCHAL_EXCM_LEVEL, state); + return state; } /** @@ -57,13 +59,16 @@ unsigned int IRAM irq_disable(void) */ unsigned int IRAM irq_enable(void) { - uint32_t _saved_interrupt_level; + uint32_t state; /* read and set interrupt level (RSIL) */ - __asm__ volatile ("rsil %0, 0" : "=a" (_saved_interrupt_level)); - DEBUG ("%s %02x (%02x)\n", __func__, - _saved_interrupt_level & 0xfffffff0, _saved_interrupt_level); - return _saved_interrupt_level; + __asm__ volatile ("rsil %0, 0" : "=a" (state) :: "memory"); + /* mask out everything else of the PS register that do not belong to + interrupt level (bits 3..0) */ + state &= 0xf; + + DEBUG("%s %02x(%02x)\n", __func__, 0, state); + return state; } /** @@ -71,9 +76,19 @@ unsigned int IRAM irq_enable(void) */ void IRAM irq_restore(unsigned int state) { + uint32_t old = 0; + /* write interrupt level and sync */ - DEBUG ("%s %02x\n", __func__, state); - __asm__ volatile ("wsr %0, ps; rsync" :: "a" (state)); + __asm__ volatile ("extui %1, %1, 0, 4 \n" /* mask intlevel bits in param */ + "rsr.ps %0 \n" /* read current PS value */ + "movi.n a4, -16 \n" + "and a4, a4, %0 \n" /* mask out intlevel bits in PS */ + "or a4, a4, %1 \n" /* or intlevel with PS */ + "wsr.ps a4 \n" /* write back PS */ + "rsync \n" + : "+a" (old) : "a" (state) : "memory"); + + DEBUG("%s %02x(%02x)\n", __func__, state, old & 0xf); } /** diff --git a/cpu/esp_common/periph/Makefile b/cpu/esp_common/periph/Makefile new file mode 100644 index 000000000000..dda549843b7e --- /dev/null +++ b/cpu/esp_common/periph/Makefile @@ -0,0 +1,3 @@ +MODULE = esp_common_periph + +include $(RIOTMAKE)/periph.mk diff --git a/cpu/esp8266/periph/flash.c b/cpu/esp_common/periph/flash.c similarity index 99% rename from cpu/esp8266/periph/flash.c rename to cpu/esp_common/periph/flash.c index c39ea75fb1e0..b501600b279d 100644 --- a/cpu/esp8266/periph/flash.c +++ b/cpu/esp_common/periph/flash.c @@ -7,11 +7,11 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @{ * * @file - * @brief Low-level MTD flash drive implementation + * @brief Low-level MTD flash drive implementation for ESP SoCs * * @author Gunar Schorcht * diff --git a/cpu/esp32/periph/hwrng.c b/cpu/esp_common/periph/hwrng.c similarity index 81% rename from cpu/esp32/periph/hwrng.c rename to cpu/esp_common/periph/hwrng.c index 270f15def57d..ecc5bbc76214 100644 --- a/cpu/esp32/periph/hwrng.c +++ b/cpu/esp_common/periph/hwrng.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 Gunar Schorcht + * Copyright (C) 2019 Gunar Schorcht * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -7,12 +7,12 @@ */ /** - * @ingroup cpu_esp32 + * @ingroup cpu_esp_common * @ingroup drivers_periph_hwrng * @{ * * @file - * @brief Low-level random number generator driver implementation + * @brief Low-level random number generator driver implementation for ESP SoCs * * @author Gunar Schorcht * @@ -23,13 +23,13 @@ #include "periph_conf.h" #include "periph/hwrng.h" -static const uint32_t* RNG_DATA_REG = (uint32_t*)0x3ff75144; +#define RNG_DATA_REG (*(volatile uint32_t *)RNG_DATA_REG_ADDR) void hwrng_init(void) { /* no need for initialization */ } -#include "rom/ets_sys.h" + void hwrng_read(void *buf, unsigned int num) { unsigned int count = 0; @@ -37,7 +37,7 @@ void hwrng_read(void *buf, unsigned int num) while (count < num) { /* read next 4 bytes of random data */ - uint32_t tmp = *RNG_DATA_REG; + uint32_t tmp = RNG_DATA_REG; /* copy data into result vector */ for (int i = 0; i < 4 && count < num; i++) { @@ -47,7 +47,7 @@ void hwrng_read(void *buf, unsigned int num) } } -uint32_t hwrand (void) +uint32_t hwrand(void) { uint32_t _tmp; hwrng_read(&_tmp, sizeof(uint32_t)); diff --git a/cpu/esp8266/periph/i2c.c b/cpu/esp_common/periph/i2c_sw.c similarity index 80% rename from cpu/esp8266/periph/i2c.c rename to cpu/esp_common/periph/i2c_sw.c index d7608fc51d09..1ced515f05d8 100644 --- a/cpu/esp8266/periph/i2c.c +++ b/cpu/esp_common/periph/i2c_sw.c @@ -7,12 +7,12 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @ingroup drivers_periph_i2c * @{ * * @file - * @brief Low-level I2C driver implementation using ESP8266 SDK + * @brief Low-level I2C driver software implementation using for ESP SoCs * * @author Gunar Schorcht * @@ -40,6 +40,7 @@ #include "periph/gpio.h" #include "periph/i2c.h" +#include "esp_attr.h" #include "esp_common.h" #include "gpio_arch.h" #include "rom/ets_sys.h" @@ -116,7 +117,7 @@ static const uint32_t _i2c_delays[][2] = /* 1 us = 20 cycles (80 MHz) / 40 cycles (160 MHz) */ [I2C_SPEED_LOW] = {989, 1990}, /* 10 kbps (period 100 us) */ [I2C_SPEED_NORMAL] = { 89, 190}, /* 100 kbps (period 10 us) */ - [I2C_SPEED_FAST] = { 16, 40}, /* 400 kbps (period 2.5 us) */ + [I2C_SPEED_FAST] = { 15, 40}, /* 400 kbps (period 2.5 us) */ [I2C_SPEED_FAST_PLUS] = { 0, 13}, /* 1 Mbps (period 1 us) */ [I2C_SPEED_HIGH] = { 0, 0} /* 3.4 Mbps (period 0.3 us) is not working */ }; @@ -124,22 +125,22 @@ static const uint32_t _i2c_delays[][2] = /* forward declaration of internal functions */ -static inline void _i2c_delay (_i2c_bus_t* bus); -static inline bool _i2c_scl_read (_i2c_bus_t* bus); -static inline bool _i2c_sda_read (_i2c_bus_t* bus); -static inline void _i2c_scl_high (_i2c_bus_t* bus); -static inline void _i2c_scl_low (_i2c_bus_t* bus); -static inline void _i2c_sda_high (_i2c_bus_t* bus); -static inline void _i2c_sda_low (_i2c_bus_t* bus); -static int _i2c_start_cond (_i2c_bus_t* bus); -static int _i2c_stop_cond (_i2c_bus_t* bus); -static int _i2c_write_bit (_i2c_bus_t* bus, bool bit); -static int _i2c_read_bit (_i2c_bus_t* bus, bool* bit); -static int _i2c_write_byte (_i2c_bus_t* bus, uint8_t byte); -static int _i2c_read_byte (_i2c_bus_t* bus, uint8_t* byte, bool ack); -static int _i2c_arbitration_lost (_i2c_bus_t* bus, const char* func); -static void _i2c_abort (_i2c_bus_t* bus, const char* func); -static void _i2c_clear (_i2c_bus_t* bus); +static inline void _i2c_delay(_i2c_bus_t* bus); +static inline bool _i2c_scl_read(_i2c_bus_t* bus); +static inline bool _i2c_sda_read(_i2c_bus_t* bus); +static inline void _i2c_scl_high(_i2c_bus_t* bus); +static inline void _i2c_scl_low(_i2c_bus_t* bus); +static inline void _i2c_sda_high(_i2c_bus_t* bus); +static inline void _i2c_sda_low(_i2c_bus_t* bus); +static int _i2c_start_cond(_i2c_bus_t* bus); +static int _i2c_stop_cond(_i2c_bus_t* bus); +static int _i2c_write_bit(_i2c_bus_t* bus, bool bit); +static int _i2c_read_bit(_i2c_bus_t* bus, bool* bit); +static int _i2c_write_byte(_i2c_bus_t* bus, uint8_t byte); +static int _i2c_read_byte(_i2c_bus_t* bus, uint8_t* byte, bool ack); +static int _i2c_arbitration_lost(_i2c_bus_t* bus, const char* func); +static void _i2c_abort(_i2c_bus_t* bus, const char* func); +static void _i2c_clear(_i2c_bus_t* bus); /* implementation of i2c interface */ @@ -224,11 +225,11 @@ void i2c_init(i2c_t dev) gpio_set_pin_usage(_i2c_bus[dev].sda, _I2C); /* set SDA and SCL to be floating and pulled-up to high */ - _i2c_sda_high (&_i2c_bus[dev]); - _i2c_scl_high (&_i2c_bus[dev]); + _i2c_sda_high(&_i2c_bus[dev]); + _i2c_scl_high(&_i2c_bus[dev]); /* clear the bus if necessary (SDA is driven permanently low) */ - _i2c_clear (&_i2c_bus[dev]); + _i2c_clear(&_i2c_bus[dev]); return; } @@ -248,15 +249,15 @@ void i2c_release(i2c_t dev) mutex_unlock(&_i2c_bus[dev].lock); } -int /* IRAM */ i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len, uint8_t flags) +int IRAM_ATTR i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len, uint8_t flags) { - DEBUG ("%s: dev=%u addr=%02x data=%p len=%d flags=%01x\n", - __func__, dev, addr, data, len, flags); + DEBUG("%s: dev=%u addr=%02x data=%p len=%d flags=%01x\n", + __func__, dev, addr, data, len, flags); assert(dev < I2C_NUMOF); - CHECK_PARAM_RET (len > 0, -EINVAL); - CHECK_PARAM_RET (data != NULL, -EINVAL); + CHECK_PARAM_RET(len > 0, -EINVAL); + CHECK_PARAM_RET(data != NULL, -EINVAL); _i2c_bus_t* bus = &_i2c_bus[dev]; @@ -266,7 +267,7 @@ int /* IRAM */ i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len, if (!(flags & I2C_NOSTART)) { /* START condition */ - if ((res = _i2c_start_cond (bus)) != 0) { + if ((res = _i2c_start_cond(bus)) != 0) { return res; } @@ -276,18 +277,18 @@ int /* IRAM */ i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len, uint8_t addr1 = 0xf0 | (addr & 0x0300) >> 7 | I2C_READ; uint8_t addr2 = addr & 0xff; /* send address bytes with read flag */ - if ((res = _i2c_write_byte (bus, addr1)) != 0 || - (res = _i2c_write_byte (bus, addr2)) != 0) { + if ((res = _i2c_write_byte(bus, addr1)) != 0 || + (res = _i2c_write_byte(bus, addr2)) != 0) { /* abort transfer */ - _i2c_abort (bus, __func__); + _i2c_abort(bus, __func__); return -ENXIO; } } else { /* send address byte with read flag */ - if ((res = _i2c_write_byte (bus, (addr << 1 | I2C_READ))) != 0) { + if ((res = _i2c_write_byte(bus, (addr << 1 | I2C_READ))) != 0) { /* abort transfer */ - _i2c_abort (bus, __func__); + _i2c_abort(bus, __func__); return -ENXIO; } } @@ -295,30 +296,30 @@ int /* IRAM */ i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len, /* receive bytes if send address was successful */ for (unsigned int i = 0; i < len; i++) { - if ((res = _i2c_read_byte (bus, &(((uint8_t*)data)[i]), i < len-1)) != 0) { + if ((res = _i2c_read_byte(bus, &(((uint8_t*)data)[i]), i < len-1)) != 0) { /* abort transfer */ - _i2c_abort (bus, __func__); + _i2c_abort(bus, __func__); return res; } } /* send STOP condition if I2C_NOSTOP flag is not set */ if (!(flags & I2C_NOSTOP)) { - res = _i2c_stop_cond (bus); + res = _i2c_stop_cond(bus); } return res; } -int /* IRAM */ i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_t len, uint8_t flags) +int IRAM_ATTR i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_t len, uint8_t flags) { - DEBUG ("%s: dev=%u addr=%02x data=%p len=%d flags=%01x\n", - __func__, dev, addr, data, len, flags); + DEBUG("%s: dev=%u addr=%02x data=%p len=%d flags=%01x\n", + __func__, dev, addr, data, len, flags); assert(dev < I2C_NUMOF); - CHECK_PARAM_RET (len > 0, -EINVAL); - CHECK_PARAM_RET (data != NULL, -EINVAL); + CHECK_PARAM_RET(len > 0, -EINVAL); + CHECK_PARAM_RET(data != NULL, -EINVAL); _i2c_bus_t* bus = &_i2c_bus[dev]; @@ -328,7 +329,7 @@ int /* IRAM */ i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_ if (!(flags & I2C_NOSTART)) { /* START condition */ - if ((res = _i2c_start_cond (bus)) != 0) { + if ((res = _i2c_start_cond(bus)) != 0) { return res; } @@ -338,18 +339,18 @@ int /* IRAM */ i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_ uint8_t addr1 = 0xf0 | (addr & 0x0300) >> 7; uint8_t addr2 = addr & 0xff; /* send address bytes without read flag */ - if ((res = _i2c_write_byte (bus, addr1)) != 0 || - (res = _i2c_write_byte (bus, addr2)) != 0) { + if ((res = _i2c_write_byte(bus, addr1)) != 0 || + (res = _i2c_write_byte(bus, addr2)) != 0) { /* abort transfer */ - _i2c_abort (bus, __func__); + _i2c_abort(bus, __func__); return -ENXIO; } } else { /* send address byte without read flag */ - if ((res = _i2c_write_byte (bus, addr << 1)) != 0) { + if ((res = _i2c_write_byte(bus, addr << 1)) != 0) { /* abort transfer */ - _i2c_abort (bus, __func__); + _i2c_abort(bus, __func__); return -ENXIO; } } @@ -357,16 +358,16 @@ int /* IRAM */ i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_ /* send bytes if send address was successful */ for (unsigned int i = 0; i < len; i++) { - if ((res = _i2c_write_byte (bus, ((uint8_t*)data)[i])) != 0) { + if ((res = _i2c_write_byte(bus, ((uint8_t*)data)[i])) != 0) { /* abort transfer */ - _i2c_abort (bus, __func__); + _i2c_abort(bus, __func__); return res; } } /* send STOP condition if I2C_NOSTOP flag is not set */ if (!(flags & I2C_NOSTOP)) { - res = _i2c_stop_cond (bus); + res = _i2c_stop_cond(bus); } return res; @@ -386,7 +387,7 @@ void i2c_poweroff(i2c_t dev) /* --- internal functions --- */ -static inline void _i2c_delay (_i2c_bus_t* bus) +static inline void _i2c_delay(_i2c_bus_t* bus) { /* produces a delay */ uint32_t cycles = bus->delay; @@ -498,9 +499,9 @@ static void _i2c_clear(_i2c_bus_t* bus) * arbitration lost but a bus lock. */ int count = 10; - while (!_i2c_sda_read (bus) && _i2c_scl_read (bus) && count) { + while (!_i2c_sda_read(bus) && _i2c_scl_read(bus) && count) { count--; - _i2c_delay (bus); + _i2c_delay(bus); } if (count) { @@ -510,11 +511,11 @@ static void _i2c_clear(_i2c_bus_t* bus) /* send 10 clock pulses in case of bus lock */ count = 10; - while (!_i2c_sda_read (bus) && count--) { - _i2c_scl_low (bus); - _i2c_delay (bus); - _i2c_scl_high (bus); - _i2c_delay (bus); + while (!_i2c_sda_read(bus) && count--) { + _i2c_scl_low(bus); + _i2c_delay(bus); + _i2c_scl_high(bus); + _i2c_delay(bus); } } @@ -523,8 +524,8 @@ static void _i2c_abort(_i2c_bus_t* bus, const char* func) DEBUG("%s: dev=%u\n", func, bus->dev); /* reset SCL and SDA to passive HIGH (floating and pulled-up) */ - _i2c_sda_high (bus); - _i2c_scl_high (bus); + _i2c_sda_high(bus); + _i2c_scl_high(bus); /* reset repeated start indicator */ bus->started = false; @@ -533,13 +534,13 @@ static void _i2c_abort(_i2c_bus_t* bus, const char* func) _i2c_clear(bus); } -static /* IRAM */ int _i2c_arbitration_lost (_i2c_bus_t* bus, const char* func) +static IRAM_ATTR int _i2c_arbitration_lost(_i2c_bus_t* bus, const char* func) { DEBUG("%s: arbitration lost dev=%u\n", func, bus->dev); /* reset SCL and SDA to passive HIGH (floating and pulled-up) */ - _i2c_sda_high (bus); - _i2c_scl_high (bus); + _i2c_sda_high(bus); + _i2c_scl_high(bus); /* reset repeated start indicator */ bus->started = false; @@ -550,7 +551,7 @@ static /* IRAM */ int _i2c_arbitration_lost (_i2c_bus_t* bus, const char* func) return -EAGAIN; } -static /* IRAM */ int _i2c_start_cond(_i2c_bus_t* bus) +static IRAM_ATTR int _i2c_start_cond(_i2c_bus_t* bus) { /* * send start condition @@ -564,17 +565,17 @@ static /* IRAM */ int _i2c_start_cond(_i2c_bus_t* bus) /* prepare the repeated start condition */ /* SDA = passive HIGH (floating and pulled-up) */ - _i2c_sda_high (bus); + _i2c_sda_high(bus); /* t_VD;DAT not necessary */ - /* _i2c_delay (bus); */ + /* _i2c_delay(bus); */ /* SCL = passive HIGH (floating and pulled-up) */ - _i2c_scl_high (bus); + _i2c_scl_high(bus); /* clock stretching, wait as long as clock is driven to low by the slave */ uint32_t stretch = I2C_CLOCK_STRETCH; - while (stretch && !_i2c_scl_read (bus)) { + while (stretch && !_i2c_scl_read(bus)) { stretch--; } if (stretch == 0) { @@ -584,24 +585,24 @@ static /* IRAM */ int _i2c_start_cond(_i2c_bus_t* bus) /* wait t_SU;STA - set-up time for a repeated START condition */ /* min. in us: 4.7 (SM), 0.6 (FM), 0.26 (FPM), 0.16 (HSM); no max. */ - _i2c_delay (bus); + _i2c_delay(bus); } /* if SDA is low, arbitration is lost and someone else is driving the bus */ - if (!_i2c_sda_read (bus)) { - return _i2c_arbitration_lost (bus, __func__); + if (!_i2c_sda_read(bus)) { + return _i2c_arbitration_lost(bus, __func__); } /* begin the START condition: SDA = active LOW */ - _i2c_sda_low (bus); + _i2c_sda_low(bus); /* wait t_HD;STA - hold time (repeated) START condition, */ /* max none */ /* min 4.0 us (SM), 0.6 us (FM), 0.26 us (FPM), 0.16 us (HSM) */ - _i2c_delay (bus); + _i2c_delay(bus); /* complete the START condition: SCL = active LOW */ - _i2c_scl_low (bus); + _i2c_scl_low(bus); /* needed for repeated start condition */ bus->started = true; @@ -609,7 +610,7 @@ static /* IRAM */ int _i2c_start_cond(_i2c_bus_t* bus) return res; } -static /* IRAM */ int _i2c_stop_cond(_i2c_bus_t* bus) +static IRAM_ATTR int _i2c_stop_cond(_i2c_bus_t* bus) { /* * send stop condition @@ -620,18 +621,18 @@ static /* IRAM */ int _i2c_stop_cond(_i2c_bus_t* bus) int res = 0; /* begin the STOP condition: SDA = active LOW */ - _i2c_sda_low (bus); + _i2c_sda_low(bus); /* wait t_LOW - LOW period of SCL clock */ /* min. in us: 4.7 (SM), 1.3 (FM), 0.5 (FPM), 0.16 (HSM); no max. */ - _i2c_delay (bus); + _i2c_delay(bus); /* SCL = passive HIGH (floating and pulled up) while SDA = active LOW */ - _i2c_scl_high (bus); + _i2c_scl_high(bus); /* clock stretching, wait as long as clock is driven to low by the slave */ uint32_t stretch = I2C_CLOCK_STRETCH; - while (stretch && !_i2c_scl_read (bus)) { + while (stretch && !_i2c_scl_read(bus)) { stretch--; } if (stretch == 0) { @@ -641,29 +642,29 @@ static /* IRAM */ int _i2c_stop_cond(_i2c_bus_t* bus) /* wait t_SU;STO - hold time STOP condition, */ /* min. in us: 4.0 (SM), 0.6 (FM), 0.26 (FPM), 0.16 (HSM); no max. */ - _i2c_delay (bus); + _i2c_delay(bus); /* complete the STOP condition: SDA = passive HIGH (floating and pulled up) */ - _i2c_sda_high (bus); + _i2c_sda_high(bus); /* reset repeated start indicator */ bus->started = false; /* wait t_BUF - bus free time between a STOP and a START condition */ /* min. in us: 4.7 (SM), 1.3 (FM), 0.5 (FPM), 0.16 (HSM); no max. */ - _i2c_delay (bus); + _i2c_delay(bus); /* one additional delay */ - _i2c_delay (bus); + _i2c_delay(bus); /* if SDA is low, arbitration is lost and someone else is driving the bus */ - if (_i2c_sda_read (bus) == 0) { - return _i2c_arbitration_lost (bus, __func__); + if (_i2c_sda_read(bus) == 0) { + return _i2c_arbitration_lost(bus, __func__); } return res; } -static /* IRAM */ int _i2c_write_bit (_i2c_bus_t* bus, bool bit) +static IRAM_ATTR int _i2c_write_bit(_i2c_bus_t* bus, bool bit) { /* * send one bit @@ -675,26 +676,26 @@ static /* IRAM */ int _i2c_write_bit (_i2c_bus_t* bus, bool bit) /* SDA = bit */ if (bit) { - _i2c_sda_high (bus); + _i2c_sda_high(bus); } else { - _i2c_sda_low (bus); + _i2c_sda_low(bus); } /* wait t_VD;DAT - data valid time (time until data are valid) */ /* max. in us: 3.45 (SM), 0.9 (FM), 0.45 (FPM); no min */ - _i2c_delay (bus); + _i2c_delay(bus); /* SCL = passive HIGH (floating and pulled-up), SDA value is available */ - _i2c_scl_high (bus); + _i2c_scl_high(bus); /* wait t_HIGH - time for the slave to read SDA */ /* min. in us: 4 (SM), 0.6 (FM), 0.26 (FPM), 0.09 (HSM); no max. */ - _i2c_delay (bus); + _i2c_delay(bus); /* clock stretching, wait as long as clock is driven low by the slave */ uint32_t stretch = I2C_CLOCK_STRETCH; - while (stretch && !_i2c_scl_read (bus)) { + while (stretch && !_i2c_scl_read(bus)) { stretch--; } if (stretch == 0) { @@ -705,7 +706,7 @@ static /* IRAM */ int _i2c_write_bit (_i2c_bus_t* bus, bool bit) /* if SCL is high, now data is valid */ /* if SDA is high, check that nobody else is driving SDA low */ if (bit && !_i2c_sda_read(bus)) { - return _i2c_arbitration_lost (bus, __func__); + return _i2c_arbitration_lost(bus, __func__); } /* SCL = active LOW to allow next SDA change */ @@ -714,7 +715,7 @@ static /* IRAM */ int _i2c_write_bit (_i2c_bus_t* bus, bool bit) return res; } -static /* IRAM */ int _i2c_read_bit (_i2c_bus_t* bus, bool* bit) +static IRAM_ATTR int _i2c_read_bit(_i2c_bus_t* bus, bool* bit) { /* read one bit * on entry: SCL is active low, SDA can be changed @@ -724,18 +725,18 @@ static /* IRAM */ int _i2c_read_bit (_i2c_bus_t* bus, bool* bit) int res = 0; /* SDA = passive HIGH (floating and pulled-up) to let the slave drive data */ - _i2c_sda_high (bus); + _i2c_sda_high(bus); /* wait t_VD;DAT - data valid time (time until data are valid) */ /* max. in us: 3.45 (SM), 0.9 (FM), 0.45 (FPM); no min */ - _i2c_delay (bus); + _i2c_delay(bus); /* SCL = passive HIGH (floating and pulled-up), SDA value is available */ - _i2c_scl_high (bus); + _i2c_scl_high(bus); /* clock stretching, wait as long as clock is driven to low by the slave */ uint32_t stretch = I2C_CLOCK_STRETCH; - while (stretch && !_i2c_scl_read (bus)) { + while (stretch && !_i2c_scl_read(bus)) { stretch--; } if (stretch == 0) { @@ -745,10 +746,10 @@ static /* IRAM */ int _i2c_read_bit (_i2c_bus_t* bus, bool* bit) /* wait t_HIGH - time for the slave to read SDA */ /* min. in us: 4 (SM), 0.6 (FM), 0.26 (FPM), 0.09 (HSM); no max. */ - _i2c_delay (bus); + _i2c_delay(bus); /* SCL is high, read out bit */ - *bit = _i2c_sda_read (bus); + *bit = _i2c_sda_read(bus); /* SCL = active LOW to allow next SDA change */ _i2c_scl_low(bus); @@ -756,7 +757,7 @@ static /* IRAM */ int _i2c_read_bit (_i2c_bus_t* bus, bool* bit) return res; } -static /* IRAM */ int _i2c_write_byte (_i2c_bus_t* bus, uint8_t byte) +static IRAM_ATTR int _i2c_write_byte(_i2c_bus_t* bus, uint8_t byte) { /* send one byte and returns 0 in case of ACK from slave */ @@ -771,7 +772,7 @@ static /* IRAM */ int _i2c_write_byte (_i2c_bus_t* bus, uint8_t byte) /* read acknowledge bit (low) from slave */ bool bit; - int res = _i2c_read_bit (bus, &bit); + int res = _i2c_read_bit(bus, &bit); if (res != 0) { return res; } @@ -780,13 +781,13 @@ static /* IRAM */ int _i2c_write_byte (_i2c_bus_t* bus, uint8_t byte) } -static /* IRAM */ int _i2c_read_byte(_i2c_bus_t* bus, uint8_t *byte, bool ack) +static IRAM_ATTR int _i2c_read_byte(_i2c_bus_t* bus, uint8_t *byte, bool ack) { bool bit; /* read the byte */ for (unsigned i = 0; i < 8; i++) { - int res = _i2c_read_bit (bus, &bit); + int res = _i2c_read_bit(bus, &bit); if (res != 0) { return res; } diff --git a/cpu/esp8266/periph/spi.c b/cpu/esp_common/periph/spi.c similarity index 98% rename from cpu/esp8266/periph/spi.c rename to cpu/esp_common/periph/spi.c index 59d31a9f3637..b450999878ad 100644 --- a/cpu/esp8266/periph/spi.c +++ b/cpu/esp_common/periph/spi.c @@ -7,12 +7,12 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @ingroup drivers_periph_spi * @{ * * @file - * @brief Low-level SPI driver implementation + * @brief Low-level SPI driver implementation for ESP SoCs * * @author Gunar Schorcht * @@ -496,7 +496,9 @@ void IRAM_ATTR spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont, } #endif - gpio_clear(cs != SPI_CS_UNDEF ? cs : spi_config[bus].cs); + if (cs != SPI_CS_UNDEF) { + gpio_clear(cs); + } size_t blocks = len / SPI_BLOCK_SIZE; uint8_t tail = len % SPI_BLOCK_SIZE; @@ -516,8 +518,8 @@ void IRAM_ATTR spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont, in ? (uint8_t *)in + blocks * SPI_BLOCK_SIZE : NULL, tail); } - if (!cont) { - gpio_set(cs != SPI_CS_UNDEF ? cs : spi_config[bus].cs); + if (!cont && (cs != SPI_CS_UNDEF)) { + gpio_set (cs); } #if ENABLE_DEBUG diff --git a/cpu/esp8266/periph/uart.c b/cpu/esp_common/periph/uart.c similarity index 89% rename from cpu/esp8266/periph/uart.c rename to cpu/esp_common/periph/uart.c index b1dd3ecb0422..de9f2556a18a 100644 --- a/cpu/esp8266/periph/uart.c +++ b/cpu/esp_common/periph/uart.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 Gunar Schorcht + * Copyright (C) 2018 Gunar Schorcht * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -7,7 +7,7 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @ingroup drivers_periph_uart * @{ * @@ -68,8 +68,6 @@ struct uart_hw_t { uart_dev_t* regs; /* pointer to register data struct of the UART device */ - uint8_t pin_txd; /* TxD pin used */ - uint8_t pin_rxd; /* RxD pin used */ bool used; /* indicates whether UART is used */ uint32_t baudrate; /* used baudrate */ uart_data_bits_t data; /* used data bits */ @@ -136,7 +134,7 @@ static int _uart_set_mode(uart_t uart, uart_data_bits_t data_bits, static uint8_t IRAM _uart_rx_one_char(uart_t uart); static void _uart_tx_one_char(uart_t uart, uint8_t data); static void _uart_intr_enable(uart_t uart); -static void _uart_config (uart_t uart); +static void _uart_config(uart_t uart); static void IRAM _uart_intr_handler(void *para); int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) @@ -146,38 +144,36 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg) assert(uart < UART_NUMOF_MAX); assert(uart < UART_NUMOF); - _uarts[uart].pin_txd = uart_config[uart].txd; - _uarts[uart].pin_rxd = uart_config[uart].rxd; - #ifdef MCU_ESP32 /* UART1 and UART2 have configurable pins */ - if ((uart == UART_DEV(1) || uart == UART_DEV(2))) { + if ((UART_NUMOF > 0 && uart == UART_DEV(1)) || + (UART_NUMOF > 1 && uart == UART_DEV(2))) { /* reset the pins when they were already used as UART pins */ - if (gpio_get_pin_usage(_uarts[uart].pin_txd) == _UART) { - gpio_set_pin_usage(_uarts[uart].pin_txd, _GPIO); + if (gpio_get_pin_usage(uart_config[uart].txd) == _UART) { + gpio_set_pin_usage(uart_config[uart].txd, _GPIO); } - if (gpio_get_pin_usage(_uarts[uart].pin_rxd) == _UART) { - gpio_set_pin_usage(_uarts[uart].pin_rxd, _GPIO); + if (gpio_get_pin_usage(uart_config[uart].rxd) == _UART) { + gpio_set_pin_usage(uart_config[uart].rxd, _GPIO); } /* try to initialize the pins as GPIOs first */ - if (gpio_init(_uarts[uart].pin_txd, GPIO_OUT) || - gpio_init(_uarts[uart].pin_rxd, GPIO_IN)) { + if (gpio_init(uart_config[uart].txd, GPIO_OUT) || + gpio_init(uart_config[uart].rxd, GPIO_IN)) { return -1; } /* store the usage type in GPIO table */ - gpio_set_pin_usage(_uarts[uart].pin_txd, _UART); - gpio_set_pin_usage(_uarts[uart].pin_rxd, _UART); + gpio_set_pin_usage(uart_config[uart].txd, _UART); + gpio_set_pin_usage(uart_config[uart].rxd, _UART); /* connect TxD pin to the TxD output signal through the GPIO matrix */ - GPIO.func_out_sel_cfg[_uarts[uart].pin_txd].func_sel = _uarts[uart].signal_txd; + GPIO.func_out_sel_cfg[uart_config[uart].txd].func_sel = _uarts[uart].signal_txd; /* connect RxD input signal to the RxD pin through the GPIO matrix */ GPIO.func_in_sel_cfg[_uarts[uart].signal_rxd].sig_in_sel = 1; GPIO.func_in_sel_cfg[_uarts[uart].signal_rxd].sig_in_inv = 0; - GPIO.func_in_sel_cfg[_uarts[uart].signal_rxd].func_sel = _uarts[uart].pin_rxd; + GPIO.func_in_sel_cfg[_uarts[uart].signal_rxd].func_sel = uart_config[uart].rxd; } #endif _uarts[uart].baudrate = baudrate; @@ -202,16 +198,16 @@ int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity, void uart_write(uart_t uart, const uint8_t *data, size_t len) { - CHECK_PARAM(uart < UART_NUMOF); + assert(uart < UART_NUMOF); for (size_t i = 0; i < len; i++) { _uart_tx_one_char(uart, data[i]); } } -void uart_poweron (uart_t uart) +void uart_poweron(uart_t uart) { - CHECK_PARAM(uart < UART_NUMOF); + assert(uart < UART_NUMOF); #ifdef MCU_ESP32 periph_module_enable(_uarts[uart].mod); @@ -219,9 +215,9 @@ void uart_poweron (uart_t uart) _uart_config(uart); } -void uart_poweroff (uart_t uart) +void uart_poweroff(uart_t uart) { - CHECK_PARAM(uart < UART_NUMOF); + assert(uart < UART_NUMOF); #ifdef MCU_ESP32 periph_module_disable(_uarts[uart].mod); @@ -229,7 +225,7 @@ void uart_poweroff (uart_t uart) } /* systemwide UART initializations */ -void uart_system_init (void) +void uart_system_init(void) { for (unsigned uart = 0; uart < UART_NUMOF; uart++) { /* reset all UART interrupt status registers */ @@ -261,7 +257,7 @@ static void IRAM _uart_intr_handler(void *arg) if (_uarts[uart].used && _uarts[uart].regs->int_st.rxfifo_full) { /* read one byte of data */ - uint8_t data = _uart_rx_one_char (uart); + uint8_t data = _uart_rx_one_char(uart); /* if registered, call the RX callback function */ if (_uarts[uart].isr_ctx.rx_cb) { _uarts[uart].isr_ctx.rx_cb(_uarts[uart].isr_ctx.arg, data); @@ -282,7 +278,7 @@ static void IRAM _uart_intr_handler(void *arg) #define UART_FIFO_MAX 128 /* receive one data byte with wait */ -static uint8_t IRAM _uart_rx_one_char (uart_t uart) +static uint8_t IRAM _uart_rx_one_char(uart_t uart) { #if defined(MODULE_ESP_QEMU) && defined(MCU_ESP8266) /* wait until at least von byte is in RX FIFO */ @@ -331,15 +327,7 @@ static void _uart_config(uart_t uart) { assert(uart < UART_NUMOF); - while (_uarts[uart].regs->status.txfifo_cnt != 0) { } -#if 0 /* setup the baudrate */ - if (uart == UART_DEV(0) || uart == UART_DEV(1)) { - /* for UART0 and UART1, we can us the ROM function */ - uart_div_modify(uart, (UART_CLK_FREQ << 4) / _uarts[uart].baudrate); - } - else -#endif if (_uart_set_baudrate(uart, _uarts[uart].baudrate) != UART_OK) { return; } @@ -379,7 +367,7 @@ static int _uart_set_baudrate(uart_t uart, uint32_t baudrate) { DEBUG("%s uart=%d, rate=%d\n", __func__, uart, baudrate); - CHECK_PARAM_RET (uart < UART_NUMOF, -1); + assert(uart < UART_NUMOF); /* wait until TX FIFO is empty */ while (_uarts[uart].regs->status.txfifo_cnt != 0) { } @@ -412,7 +400,7 @@ static int _uart_set_mode(uart_t uart, uart_data_bits_t data_bits, DEBUG("%s uart=%d, data_bits=%d parity=%d stop_bits=%d\n", __func__, uart, data_bits, parity, stop_bits); - CHECK_PARAM_RET (uart < UART_NUMOF, UART_NODEV); + assert(uart < UART_NUMOF); critical_enter(); diff --git a/cpu/esp_common/syscalls.c b/cpu/esp_common/syscalls.c new file mode 100644 index 000000000000..cbb6a4865641 --- /dev/null +++ b/cpu/esp_common/syscalls.c @@ -0,0 +1,395 @@ +/* + * Copyright (C) 2019 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_esp_common + * @{ + * + * @file + * @brief Implementation of required system calls + * + * @author Gunar Schorcht + * + * @} + */ + +#include +#include +#include + +#include "irq_arch.h" +#include "mutex.h" +#include "rmutex.h" +#include "timex.h" + +#include "esp_attr.h" +#include "syscalls.h" + +#ifdef MODULE_ESP_IDF_HEAP +#include "esp_heap_caps.h" +#else +#include "malloc.h" +#endif + +#define ENABLE_DEBUG (0) +#include "debug.h" + +#ifndef MODULE_PTHREAD + +#define PTHREAD_CANCEL_DISABLE 1 +/* + * This is a dummy function to avoid undefined references when linking + * against newlib and module pthread is not used. + */ +int pthread_setcancelstate(int state, int *oldstate) +{ + if (oldstate) { + *oldstate = PTHREAD_CANCEL_DISABLE; + } + return 0; +} +#endif /* MODULE_PTHREAD */ + +/* + * TODO: When the lock functions in this section are enabled, an application + * crashes when an ISR calls a `newlib` function that uses `_lock_acquire` + * or `_log_acquire_recursive` to be thread-safe, for example, `puts` in + * `tests/isr_yield_higher`. The reason is that the implementation of these + * functions uses `mutex` and `rmutex` that do not work in the interrupt + * context. Therefore, the lock functions are disabled for the moment, and + * instead `newlib`'s dummy lock functions are used which do not guarantee + * thread safety. + */ + +/** + * @name Locking functions + * + * Following functions implement the lock mechanism for newlib. + */ + +/** + * _malloc_rmtx is defined as static variable to avoid recursive calls of + * malloc when _malloc_r tries to lock __malloc_lock_object the first + * time. All other mutexes that are used for the lock mechanism are allocated + * dynamically. + */ +static rmutex_t _malloc_rmtx = RMUTEX_INIT; + +/** + * To properly handle the static rmutex _malloc_rmtx, we have to know + * the address of newlib's static variable __malloc_lock_object. + */ +static _lock_t *__malloc_static_object = NULL; + +void IRAM_ATTR _lock_init(_lock_t *lock) +{ + assert(lock != NULL); + + mutex_t* mtx = malloc(sizeof(mutex_t)); + + if (mtx) { + memset(mtx, 0, sizeof(mutex_t)); + *lock = (_lock_t)mtx; + } +} + +void IRAM_ATTR _lock_init_recursive(_lock_t *lock) +{ + assert(lock != NULL); + + /** + * Since we don't have direct access to newlib's static variable + * __malloc_lock_object, we have to rely on the fact that function + * _lock_aqcuire_recursive, and thus function _lock_init_recursive + * is called for the first time with newlib's static variable + * __malloc_lock_object as parameter. This is ensured by calling + * malloc in the function syscalls_init. + */ + if (__malloc_static_object == NULL) { + *lock = (_lock_t)&_malloc_rmtx; + __malloc_static_object = lock; + return; + } + + /* _malloc_rmtx is static and has not to be allocated */ + if (lock == __malloc_static_object) { + return; + } + + rmutex_t* rmtx = malloc(sizeof(rmutex_t)); + + if (rmtx) { + memset(rmtx, 0, sizeof(rmutex_t)); + *lock = (_lock_t)rmtx; + } +} + +void IRAM_ATTR _lock_close(_lock_t *lock) +{ + assert(lock != NULL); + assert(lock != __malloc_static_object); + + free((void*)*lock); + *lock = 0; +} + +void IRAM_ATTR _lock_close_recursive(_lock_t *lock) +{ + assert(lock != NULL); + assert(lock != __malloc_static_object); + + free((void*)*lock); + *lock = 0; +} + +void IRAM_ATTR _lock_acquire(_lock_t *lock) +{ + assert(lock != NULL); + + /* if the lock data structure is still not allocated, initialize it first */ + if (*lock == 0) { + _lock_init(lock); + } + + /* if scheduler is not running, we have not to lock the mutex */ + if (sched_active_thread == NULL) { + return; + } + + assert(!irq_is_in()); + mutex_lock((mutex_t*)*lock); +} + +void IRAM_ATTR _lock_acquire_recursive(_lock_t *lock) +{ + assert(lock != NULL); + + /* if the lock data structure is still not allocated, initialize it first */ + if (*lock == 0) { + _lock_init_recursive(lock); + } + + /* if scheduler is not running, we have not to lock the rmutex */ + if (sched_active_thread == NULL) { + return; + } + + assert(!irq_is_in()); + rmutex_lock((rmutex_t*)*lock); +} + +int IRAM_ATTR _lock_try_acquire(_lock_t *lock) +{ + assert(lock != NULL); + + /* if the lock data structure is still not allocated, initialize it first */ + if (*lock == 0) { + _lock_init(lock); + } + + /* if scheduler is not running, we have not to lock the mutex */ + if (sched_active_thread == NULL) { + return 0; + } + + if (irq_is_in()) { + return 0; + } + + return mutex_trylock((mutex_t*)*lock); +} + +int IRAM_ATTR _lock_try_acquire_recursive(_lock_t *lock) +{ + assert(lock != NULL); + + /* if the lock data structure is still not allocated, initialize it first */ + if (*lock == 0) { + _lock_init_recursive(lock); + } + + /* if scheduler is not running, we have not to lock the rmutex */ + if (sched_active_thread == NULL) { + return 0; + } + + if (irq_is_in()) { + return 0; + } + + return rmutex_trylock((rmutex_t*)*lock); +} + +void IRAM_ATTR _lock_release(_lock_t *lock) +{ + assert(lock != NULL && *lock != 0); + + /* if scheduler is not running, we have not to unlock the mutex */ + if (sched_active_thread == NULL) { + return; + } + + mutex_unlock((mutex_t*)*lock); +} + +void IRAM_ATTR _lock_release_recursive(_lock_t *lock) +{ + assert(lock != NULL && *lock != 0); + + /* if scheduler is not running, we have not to unlock the rmutex */ + if (sched_active_thread == NULL) { + return; + } + + rmutex_unlock((rmutex_t*)*lock); +} + +/** + * @name Memory allocation functions + */ + +#ifdef MODULE_ESP_IDF_HEAP + +#define heap_caps_malloc_default(s) heap_caps_malloc(s, MALLOC_CAP_DEFAULT) +#define heap_caps_realloc_default(p,s) heap_caps_realloc(p, s, MALLOC_CAP_DEFAULT) + +void* IRAM_ATTR __wrap__malloc_r(struct _reent *r, size_t size) +{ + return heap_caps_malloc_default( size ); +} + +void IRAM_ATTR __wrap__free_r(struct _reent *r, void *ptr) +{ + heap_caps_free( ptr ); +} + +void* IRAM_ATTR __wrap__realloc_r(struct _reent *r, void* ptr, size_t size) +{ + return heap_caps_realloc_default( ptr, size ); +} + +void* IRAM_ATTR __wrap__calloc_r(struct _reent *r, size_t count, size_t size) +{ + void *result = heap_caps_malloc_default(count * size); + if (result) { + bzero(result, count * size); + } + return result; +} + +#else /* MODULE_ESP_IDF_HEAP */ + +/* for compatibility with ESP-IDF heap functions */ + +void* _heap_caps_malloc(size_t size, uint32_t caps, const char *file, size_t line) +{ + (void)caps; + return malloc(size); +} + +void* _heap_caps_calloc(size_t n, size_t size, uint32_t caps, const char *file, size_t line) +{ + (void)caps; + return calloc(n, size); +} + +void* _heap_caps_realloc(void *ptr, size_t size, uint32_t caps, const char *file, size_t line) +{ + return realloc(ptr, size); +} + +void *_heap_caps_zalloc(size_t size, uint32_t caps, const char *file, size_t line) +{ + void *ptr = malloc(size); + if (ptr) { + memset(ptr, 0, size); + } + return ptr; +} + +void _heap_caps_free(void *ptr, const char *file, size_t line) +{ + (void)file; + (void)line; + free(ptr); +} + +void heap_caps_init(void) +{ +} + +extern uint8_t _eheap; /* end of heap (defined in ld script) */ +extern uint8_t _sheap; /* start of heap (defined in ld script) */ + +unsigned int IRAM_ATTR get_free_heap_size(void) +{ + struct mallinfo minfo = mallinfo(); + return &_eheap - &_sheap - minfo.uordblks; +} + +void heap_stats(void) +{ + ets_printf("heap: %u (used %u, free %u) [bytes]\n", + &_eheap - &_sheap, &_eheap - &_sheap - get_free_heap_size(), + get_free_heap_size()); +} + +/* alias for compatibility with espressif/wifi_libs */ +uint32_t esp_get_free_heap_size( void ) __attribute__((alias("get_free_heap_size"))); + +#endif /* MODULE_ESP_IDF_HEAP */ + +/** + * @name Other system functions + */ + +struct _reent* __getreent(void) { + return _GLOBAL_REENT; +} + +static struct _reent s_reent; + +void syscalls_init(void) +{ + extern void syscalls_init_arch(void); + syscalls_init_arch(); + + _GLOBAL_REENT = &s_reent; + + environ = malloc(sizeof(char*)); + environ[0] = NULL; + + /* initialization of newlib, includes the ctors initialization */ + extern void __libc_init_array(void); + __libc_init_array(); + + /* initialization of global reent data structure */ + _REENT_SMALL_CHECK_INIT(_GLOBAL_REENT); + + /* + * disable the locking for stdout/stderr to avoid rmutex based locking + * when puts/printf are called from an ISR + */ + __fsetlocking(_GLOBAL_REENT->_stdout, FSETLOCKING_BYCALLER); + __fsetlocking(_GLOBAL_REENT->_stderr, FSETLOCKING_BYCALLER); +} + +__attribute__((weak)) void +_system_prevent_memset_lto(void *const s, int c, const size_t n) +{ + (void)s; + (void)c; + (void)n; +} + +void *system_secure_memset(void *s, int c, size_t n) +{ + memset(s, c, n); + _system_prevent_memset_lto(s, c, n); + return s; +} diff --git a/cpu/esp8266/thread_arch.c b/cpu/esp_common/thread_arch.c similarity index 99% rename from cpu/esp8266/thread_arch.c rename to cpu/esp_common/thread_arch.c index 7ed987d99dc9..3810bc0e37d3 100644 --- a/cpu/esp8266/thread_arch.c +++ b/cpu/esp_common/thread_arch.c @@ -7,7 +7,7 @@ */ /** - * @ingroup cpu_esp8266 + * @ingroup cpu_esp_common * @{ * * @file @@ -302,7 +302,7 @@ void IRAM_ATTR thread_yield_higher(void) return; } -void thread_stack_print(void) +void thread_stack_print(void) { /* Print the current stack to stdout. */ @@ -320,7 +320,7 @@ void thread_stack_print(void) #endif } -void thread_print_stack(void) +void thread_print_stack(void) { /* Prints human readable, ps-like thread information for debugging purposes. */ /* because of Xtensa stack structure and call0 ABI, it is not possible to implement */ diff --git a/cpu/esp32/tools.c b/cpu/esp_common/tools.c similarity index 93% rename from cpu/esp32/tools.c rename to cpu/esp_common/tools.c index 23f8878e7950..2ee52963bacc 100644 --- a/cpu/esp32/tools.c +++ b/cpu/esp_common/tools.c @@ -7,11 +7,11 @@ */ /** - * @ingroup cpu_esp32 + * @ingroup cpu_esp_common * @{ * * @file - * @brief Implementation of some tools + * @brief Implementation of some tools for ESP SoCs * * @author Gunar Schorcht * @@ -20,7 +20,6 @@ #include #include "esp/common_macros.h" -#include "rom/ets_sys.h" #include "tools.h" void esp_hexdump (const void* addr, uint32_t num, char width, uint8_t per_line) diff --git a/cpu/esp_common/vendor/README.md b/cpu/esp_common/vendor/README.md index 29377545e171..4b402f800ec8 100644 --- a/cpu/esp_common/vendor/README.md +++ b/cpu/esp_common/vendor/README.md @@ -1,4 +1,8 @@ -The subdirectories here contain third-party software components used by the RIOT port for ESP32. +The subdirectories here contain third-party software components used by the RIOT port for ESP32 and ESP8266. + +### esp + +The files that are part of [esp-open-rtos](https://github.com/SuperHouse/esp-open-rtos.git). The files in this directory are under the copyright of their respective owners. Please note the copyright notice in these files. All of these files are BSD Licensed as described in the file [LICENSE](https://github.com/SuperHouse/esp-open-rtos/blob/master/LICENSE). ### xtensa The files in this directory are from the [FreeRTOS port for Xtensa](https://github.com/tensilica/freertos) configurable processors and Diamond processors. All of these files are copyright of Cadence Design Systems Inc. and licensed under the MIT license. diff --git a/cpu/esp32/vendor/esp/LICENSE b/cpu/esp_common/vendor/esp/LICENSE similarity index 100% rename from cpu/esp32/vendor/esp/LICENSE rename to cpu/esp_common/vendor/esp/LICENSE diff --git a/cpu/esp32/vendor/esp/README.md b/cpu/esp_common/vendor/esp/README.md similarity index 100% rename from cpu/esp32/vendor/esp/README.md rename to cpu/esp_common/vendor/esp/README.md diff --git a/cpu/esp8266/vendor/esp/common_macros.h b/cpu/esp_common/vendor/esp/common_macros.h similarity index 100% rename from cpu/esp8266/vendor/esp/common_macros.h rename to cpu/esp_common/vendor/esp/common_macros.h diff --git a/cpu/esp32/vendor/esp/xtensa_ops.h b/cpu/esp_common/vendor/esp/xtensa_ops.h similarity index 100% rename from cpu/esp32/vendor/esp/xtensa_ops.h rename to cpu/esp_common/vendor/esp/xtensa_ops.h diff --git a/cpu/esp8266/vendor/esp-idf/partition_table/gen_esp32part.py b/dist/tools/esptool/gen_esp32part.py similarity index 99% rename from cpu/esp8266/vendor/esp-idf/partition_table/gen_esp32part.py rename to dist/tools/esptool/gen_esp32part.py index e789261f272b..5f9cfd774024 100755 --- a/cpu/esp8266/vendor/esp-idf/partition_table/gen_esp32part.py +++ b/dist/tools/esptool/gen_esp32part.py @@ -143,7 +143,7 @@ class PartitionDefinition(object): "data" : DATA_TYPE, } - # Keep this map in sync with esp_partition_subtype_t enum in esp_partition.h + # Keep this map in sync with esp_partition_subtype_t enum in esp_partition.h SUBTYPES = { APP_TYPE : { "factory" : 0x00,