remove ports/esp32

This commit is contained in:
Dan Halbert 2019-10-13 11:06:54 -04:00
parent b0d656683b
commit 41ef2ab591
65 changed files with 0 additions and 7937 deletions

View File

@ -1,786 +0,0 @@
include ../../py/mkenv.mk
# qstr definitions (must come before including py.mk)
QSTR_DEFS = qstrdefsport.h
MICROPY_PY_USSL = 0
MICROPY_SSL_AXTLS = 0
MICROPY_FATFS = 1
MICROPY_PY_BTREE = 1
#FROZEN_DIR = scripts
FROZEN_MPY_DIR = modules
# include py core make definitions
include $(TOP)/py/py.mk
PORT ?= /dev/ttyUSB0
BAUD ?= 460800
FLASH_MODE ?= dio
FLASH_FREQ ?= 40m
FLASH_SIZE ?= 4MB
CROSS_COMPILE ?= xtensa-esp32-elf-
ESPIDF_SUPHASH := 9a55b42f0841b3d38a61089b1dda4bf28135decd
# paths to ESP IDF and its components
ifeq ($(ESPIDF),)
ifneq ($(IDF_PATH),)
ESPIDF = $(IDF_PATH)
else
$(info The ESPIDF variable has not been set, please set it to the root of the esp-idf repository.)
$(info See README.md for installation instructions.)
$(info Supported git hash: $(ESPIDF_SUPHASH))
$(error ESPIDF not set)
endif
endif
ESPCOMP = $(ESPIDF)/components
ESPTOOL ?= $(ESPCOMP)/esptool_py/esptool/esptool.py
# verify the ESP IDF version
ESPIDF_CURHASH := $(shell git -C $(ESPIDF) show -s --pretty=format:'%H')
ifneq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH))
$(info ** WARNING **)
$(info The git hash of ESP IDF does not match the supported version)
$(info The build may complete and the firmware may work but it is not guaranteed)
$(info ESP IDF path: $(ESPIDF))
$(info Current git hash: $(ESPIDF_CURHASH))
$(info Supported git hash: $(ESPIDF_SUPHASH))
endif
# pretty format of ESP IDF version, used internally by the IDF
IDF_VER := $(shell git -C $(ESPIDF) describe)
INC += -I.
INC += -I$(TOP)
INC += -I$(TOP)/lib/mp-readline
INC += -I$(TOP)/lib/netutils
INC += -I$(TOP)/lib/timeutils
INC += -I$(BUILD)
INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include
INC_ESPCOMP += -I$(ESPCOMP)/driver/include
INC_ESPCOMP += -I$(ESPCOMP)/driver/include/driver
INC_ESPCOMP += -I$(ESPCOMP)/nghttp/port/include
INC_ESPCOMP += -I$(ESPCOMP)/nghttp/nghttp2/lib/includes
INC_ESPCOMP += -I$(ESPCOMP)/esp32/include
INC_ESPCOMP += -I$(ESPCOMP)/soc/include
INC_ESPCOMP += -I$(ESPCOMP)/soc/esp32/include
INC_ESPCOMP += -I$(ESPCOMP)/ethernet/include
INC_ESPCOMP += -I$(ESPCOMP)/expat/include/expat
INC_ESPCOMP += -I$(ESPCOMP)/expat/port/include
INC_ESPCOMP += -I$(ESPCOMP)/heap/include
INC_ESPCOMP += -I$(ESPCOMP)/json/include
INC_ESPCOMP += -I$(ESPCOMP)/json/port/include
INC_ESPCOMP += -I$(ESPCOMP)/log/include
INC_ESPCOMP += -I$(ESPCOMP)/newlib/include
INC_ESPCOMP += -I$(ESPCOMP)/nvs_flash/include
INC_ESPCOMP += -I$(ESPCOMP)/freertos/include
INC_ESPCOMP += -I$(ESPCOMP)/tcpip_adapter/include
INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/lwip
INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/lwip/port
INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/lwip/posix
INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/mbedtls/include
INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include
INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/include
INC_ESPCOMP += -I$(ESPCOMP)/ulp/include
INC_ESPCOMP += -I$(ESPCOMP)/vfs/include
INC_ESPCOMP += -I$(ESPCOMP)/newlib/platform_include
INC_ESPCOMP += -I$(ESPCOMP)/xtensa-debug-module/include
INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include
INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/port/include
INC_ESPCOMP += -I$(ESPCOMP)/ethernet/include
INC_ESPCOMP += -I$(ESPCOMP)/app_trace/include
INC_ESPCOMP += -I$(ESPCOMP)/app_update/include
INC_ESPCOMP += -I$(ESPCOMP)/pthread/include
INC_ESPCOMP += -I$(ESPCOMP)/smartconfig_ack/include
# these flags are common to C and C++ compilation
CFLAGS_COMMON = -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields \
-mlongcalls -nostdlib \
-Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable \
-Wno-error=unused-variable -Wno-error=deprecated-declarations \
-DESP_PLATFORM
CFLAGS_BASE = -std=gnu99 $(CFLAGS_COMMON) -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H
CFLAGS = $(CFLAGS_BASE) $(INC) $(INC_ESPCOMP)
CFLAGS += -DIDF_VER=\"$(IDF_VER)\"
CFLAGS += $(CFLAGS_MOD)
# this is what ESPIDF uses for c++ compilation
CXXFLAGS = -std=gnu++11 $(CFLAGS_COMMON) $(INC) $(INC_ESPCOMP)
LDFLAGS = -nostdlib -Map=$(@:.elf=.map) --cref
LDFLAGS += --gc-sections -static -EL
LDFLAGS += -u call_user_start_cpu0 -u uxTopUsedPriority -u ld_include_panic_highint_hdl
LDFLAGS += -u __cxa_guard_dummy # so that implementation of static guards is taken from cxx_guards.o instead of libstdc++.a
LDFLAGS += -L$(ESPCOMP)/esp32/ld
LDFLAGS += -T $(BUILD)/esp32_out.ld
LDFLAGS += -T ./esp32.custom_common.ld
LDFLAGS += -T esp32.rom.ld
LDFLAGS += -T esp32.peripherals.ld
LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
LIBSTDCXX_FILE_NAME = $(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a)
# Debugging/Optimization
ifeq ($(DEBUG), 1)
CFLAGS += -g
COPT = -O0
else
#CFLAGS += -fdata-sections -ffunction-sections
COPT += -Os -DNDEBUG
#LDFLAGS += --gc-sections
endif
# Enable SPIRAM support if CONFIG_SPIRAM_SUPPORT=1
ifeq ($(CONFIG_SPIRAM_SUPPORT),1)
CFLAGS_COMMON += -mfix-esp32-psram-cache-issue -DCONFIG_SPIRAM_SUPPORT=1
LIBC_LIBM = $(ESPCOMP)/newlib/lib/libc-psram-workaround.a $(ESPCOMP)/newlib/lib/libm-psram-workaround.a
else
LDFLAGS += -T esp32.rom.spiram_incompatible_fns.ld
LIBC_LIBM = $(ESPCOMP)/newlib/lib/libc.a $(ESPCOMP)/newlib/lib/libm.a
endif
################################################################################
# List of MicroPython source and object files
SRC_C = \
main.c \
uart.c \
gccollect.c \
mphalport.c \
fatfs_port.c \
help.c \
modutime.c \
moduos.c \
machine_timer.c \
machine_pin.c \
machine_touchpad.c \
machine_adc.c \
machine_dac.c \
machine_pwm.c \
machine_uart.c \
modmachine.c \
modnetwork.c \
network_lan.c \
modsocket.c \
modesp.c \
esp32_ulp.c \
modesp32.c \
espneopixel.c \
machine_hw_spi.c \
machine_wdt.c \
mpthreadport.c \
machine_rtc.c \
$(SRC_MOD)
EXTMOD_SRC_C = $(addprefix extmod/,\
modonewire.c \
)
LIB_SRC_C = $(addprefix lib/,\
libm/math.c \
libm/fmodf.c \
libm/roundf.c \
libm/ef_sqrt.c \
libm/kf_rem_pio2.c \
libm/kf_sin.c \
libm/kf_cos.c \
libm/kf_tan.c \
libm/ef_rem_pio2.c \
libm/sf_sin.c \
libm/sf_cos.c \
libm/sf_tan.c \
libm/sf_frexp.c \
libm/sf_modf.c \
libm/sf_ldexp.c \
libm/asinfacosf.c \
libm/atanf.c \
libm/atan2f.c \
mp-readline/readline.c \
netutils/netutils.c \
timeutils/timeutils.c \
utils/pyexec.c \
utils/interrupt_char.c \
utils/sys_stdio_mphal.c \
)
ifeq ($(MICROPY_FATFS), 1)
LIB_SRC_C += \
lib/oofatfs/ff.c \
lib/oofatfs/option/unicode.c
endif
DRIVERS_SRC_C = $(addprefix drivers/,\
bus/softspi.c \
dht/dht.c \
)
OBJ_MP =
OBJ_MP += $(PY_O)
OBJ_MP += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ_MP += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o))
OBJ_MP += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
OBJ_MP += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
# List of sources for qstr extraction
SRC_QSTR += $(SRC_C) $(EXTMOD_SRC_C) $(LIB_SRC_C) $(DRIVERS_SRC_C)
# Append any auto-generated sources that are needed by sources listed in SRC_QSTR
SRC_QSTR_AUTO_DEPS +=
################################################################################
# List of object files from the ESP32 IDF components
ESPIDF_DRIVER_O = $(addprefix $(ESPCOMP)/driver/,\
uart.o \
periph_ctrl.o \
ledc.o \
gpio.o \
timer.o \
spi_master.o \
spi_common.o \
rtc_module.o \
)
$(BUILD)/$(ESPCOMP)/esp32/dport_access.o: CFLAGS += -Wno-array-bounds
ESPIDF_ESP32_O = $(addprefix $(ESPCOMP)/esp32/,\
brownout.o \
panic.o \
esp_timer.o \
esp_timer_esp32.o \
ets_timer_legacy.o \
event_default_handlers.o \
fast_crypto_ops.o \
task_wdt.o \
cache_err_int.o \
clk.o \
core_dump.o \
cpu_start.o \
gdbstub.o \
crosscore_int.o \
ipc.o \
int_wdt.o \
event_loop.o \
hwcrypto/sha.o \
hwcrypto/aes.o \
lib_printf.o \
freertos_hooks.o \
system_api.o \
hw_random.o \
phy_init.o \
intr_alloc.o \
dport_access.o \
wifi_init.o \
wifi_os_adapter.o \
sleep_modes.o \
spiram.o \
spiram_psram.o \
)
ESPIDF_HEAP_O = $(addprefix $(ESPCOMP)/heap/,\
heap_caps.o \
heap_caps_init.o \
multi_heap.o \
)
ESPIDF_SOC_O = $(addprefix $(ESPCOMP)/soc/,\
esp32/cpu_util.o \
esp32/rtc_clk.o \
esp32/rtc_init.o \
esp32/rtc_pm.o \
esp32/rtc_sleep.o \
esp32/rtc_time.o \
esp32/soc_memory_layout.o \
esp32/spi_periph.o \
)
ESPIDF_CXX_O = $(addprefix $(ESPCOMP)/cxx/,\
cxx_guards.o \
)
ESPIDF_ETHERNET_O = $(addprefix $(ESPCOMP)/ethernet/,\
emac_dev.o \
emac_main.o \
eth_phy/phy_tlk110.o \
eth_phy/phy_lan8720.o \
eth_phy/phy_common.o \
)
$(BUILD)/$(ESPCOMP)/expat/%.o: CFLAGS += -Wno-unused-function
ESPIDF_EXPAT_O = $(addprefix $(ESPCOMP)/expat/,\
library/xmltok_ns.o \
library/xmltok.o \
library/xmlparse.o \
library/xmlrole.o \
library/xmltok_impl.o \
port/minicheck.o \
port/expat_element.o \
port/chardata.o \
)
ESPIDF_PTHREAD_O = $(addprefix $(ESPCOMP)/pthread/,\
pthread.o \
pthread_local_storage.o \
)
# Assembler .S files need only basic flags, and in particular should not have
# -Os because that generates subtly different code.
# We also need custom CFLAGS for .c files because FreeRTOS has headers with
# generic names (eg queue.h) which can clash with other files in the port.
CFLAGS_ASM = -I$(ESPCOMP)/esp32/include -I$(ESPCOMP)/soc/esp32/include -I$(ESPCOMP)/freertos/include/freertos -I.
$(BUILD)/$(ESPCOMP)/freertos/portasm.o: CFLAGS = $(CFLAGS_ASM)
$(BUILD)/$(ESPCOMP)/freertos/xtensa_context.o: CFLAGS = $(CFLAGS_ASM)
$(BUILD)/$(ESPCOMP)/freertos/xtensa_intr_asm.o: CFLAGS = $(CFLAGS_ASM)
$(BUILD)/$(ESPCOMP)/freertos/xtensa_vectors.o: CFLAGS = $(CFLAGS_ASM)
$(BUILD)/$(ESPCOMP)/freertos/%.o: CFLAGS = $(CFLAGS_BASE) -I. $(INC_ESPCOMP) -I$(ESPCOMP)/freertos/include/freertos -D_ESP_FREERTOS_INTERNAL
ESPIDF_FREERTOS_O = $(addprefix $(ESPCOMP)/freertos/,\
croutine.o \
event_groups.o \
FreeRTOS-openocd.o \
list.o \
portasm.o \
port.o \
queue.o \
ringbuf.o \
tasks.o \
timers.o \
xtensa_context.o \
xtensa_init.o \
xtensa_intr_asm.o \
xtensa_intr.o \
xtensa_overlay_os_hook.o \
xtensa_vector_defaults.o \
xtensa_vectors.o \
)
ESPIDF_VFS_O = $(addprefix $(ESPCOMP)/vfs/,\
vfs_uart.o \
vfs.o \
)
ESPIDF_JSON_O = $(addprefix $(ESPCOMP)/json/cJSON/,\
cJSON.o \
cJSON_Utils.o \
)
ESPIDF_LOG_O = $(addprefix $(ESPCOMP)/log/,\
log.o \
)
ESPIDF_XTENSA_DEBUG_MODULE_O = $(addprefix $(ESPCOMP)/xtensa-debug-module/,\
eri.o \
trax.o \
)
ESPIDF_TCPIP_ADAPTER_O = $(addprefix $(ESPCOMP)/tcpip_adapter/,\
tcpip_adapter_lwip.o \
)
ESPIDF_APP_TRACE_O = $(addprefix $(ESPCOMP)/app_trace/,\
app_trace.o \
)
ESPIDF_APP_UPDATE_O = $(addprefix $(ESPCOMP)/app_update/,\
esp_ota_ops.o \
)
ESPIDF_NEWLIB_O = $(addprefix $(ESPCOMP)/newlib/,\
time.o \
select.o \
syscalls.o \
syscall_table.o \
reent_init.o \
locks.o \
)
ESPIDF_NGHTTP_O = $(addprefix $(ESPCOMP)/nghttp/,\
nghttp2/lib/nghttp2_http.o \
nghttp2/lib/nghttp2_version.o \
nghttp2/lib/nghttp2_mem.o \
nghttp2/lib/nghttp2_hd_huffman.o \
nghttp2/lib/nghttp2_rcbuf.o \
nghttp2/lib/nghttp2_callbacks.o \
nghttp2/lib/nghttp2_session.o \
nghttp2/lib/nghttp2_stream.o \
nghttp2/lib/nghttp2_hd.o \
nghttp2/lib/nghttp2_priority_spec.o \
nghttp2/lib/nghttp2_buf.o \
nghttp2/lib/nghttp2_option.o \
nghttp2/lib/nghttp2_npn.o \
nghttp2/lib/nghttp2_helper.o \
nghttp2/lib/nghttp2_frame.o \
nghttp2/lib/nghttp2_outbound_item.o \
nghttp2/lib/nghttp2_hd_huffman_data.o \
nghttp2/lib/nghttp2_pq.o \
nghttp2/lib/nghttp2_queue.o \
nghttp2/lib/nghttp2_submit.o \
nghttp2/lib/nghttp2_map.o \
port/http_parser.o \
)
ESPIDF_NVS_FLASH_O = $(addprefix $(ESPCOMP)/nvs_flash/,\
src/nvs_types.o \
src/nvs_page.o \
src/nvs_item_hash_list.o \
src/nvs_pagemanager.o \
src/nvs_storage.o \
src/nvs_api.o \
)
ESPIDF_OPENSSL_O = $(addprefix $(ESPCOMP)/openssl/,\
)
ESPIDF_SMARTCONFIG_ACK_O = $(addprefix $(ESPCOMP)/smartconfig_ack/,\
smartconfig_ack.o \
)
ESPIDF_SPI_FLASH_O = $(addprefix $(ESPCOMP)/spi_flash/,\
flash_mmap.o \
partition.o \
spi_flash_rom_patch.o \
cache_utils.o \
flash_ops.o \
)
ESPIDF_ULP_O = $(addprefix $(ESPCOMP)/ulp/,\
ulp.o \
)
$(BUILD)/$(ESPCOMP)/lwip/%.o: CFLAGS += -Wno-address -Wno-unused-variable -Wno-unused-but-set-variable
ESPIDF_LWIP_O = $(addprefix $(ESPCOMP)/lwip/,\
api/pppapi.o \
api/netbuf.o \
api/api_lib.o \
api/netifapi.o \
api/tcpip.o \
api/netdb.o \
api/err.o \
api/api_msg.o \
api/sockets.o \
apps/sntp/sntp.o \
apps/dhcpserver.o \
core/ipv4/ip_frag.o \
core/ipv4/dhcp.o \
core/ipv4/ip4_addr.o \
core/ipv4/igmp.o \
core/ipv4/ip4.o \
core/ipv4/autoip.o \
core/ipv4/icmp.o \
core/ipv6/ip6_frag.o \
core/ipv6/dhcp6.o \
core/ipv6/inet6.o \
core/ipv6/ip6_addr.o \
core/ipv6/ip6.o \
core/ipv6/nd6.o \
core/ipv6/mld6.o \
core/ipv6/ethip6.o \
core/ipv6/icmp6.o \
core/mem.o \
core/init.o \
core/memp.o \
core/sys.o \
core/tcp_in.o \
core/dns.o \
core/ip.o \
core/pbuf.o \
core/raw.o \
core/tcp.o \
core/def.o \
core/netif.o \
core/stats.o \
core/timers.o \
core/inet_chksum.o \
core/udp.o \
core/tcp_out.o \
netif/slipif.o \
netif/etharp.o \
netif/ethernet.o \
netif/lowpan6.o \
netif/ethernetif.o \
port/freertos/sys_arch.o \
port/netif/wlanif.o \
port/netif/ethernetif.o \
port/vfs_lwip.o \
)
ESPIDF_MBEDTLS_O = $(addprefix $(ESPCOMP)/mbedtls/,\
mbedtls/library/entropy.o \
mbedtls/library/pkcs12.o \
mbedtls/library/ccm.o \
mbedtls/library/pk.o \
mbedtls/library/sha1.o \
mbedtls/library/x509_csr.o \
mbedtls/library/ssl_cli.o \
mbedtls/library/ecp.o \
mbedtls/library/blowfish.o \
mbedtls/library/x509.o \
mbedtls/library/ecp_curves.o \
mbedtls/library/error.o \
mbedtls/library/ssl_ticket.o \
mbedtls/library/entropy_poll.o \
mbedtls/library/cipher.o \
mbedtls/library/version_features.o \
mbedtls/library/ripemd160.o \
mbedtls/library/rsa.o \
mbedtls/library/rsa_internal.o \
mbedtls/library/md.o \
mbedtls/library/md_wrap.o \
mbedtls/library/sha256.o \
mbedtls/library/dhm.o \
mbedtls/library/ssl_cache.o \
mbedtls/library/pkwrite.o \
mbedtls/library/base64.o \
mbedtls/library/asn1parse.o \
mbedtls/library/ssl_tls.o \
mbedtls/library/hmac_drbg.o \
mbedtls/library/pem.o \
mbedtls/library/version.o \
mbedtls/library/gcm.o \
mbedtls/library/memory_buffer_alloc.o \
mbedtls/library/md2.o \
mbedtls/library/ecdsa.o \
mbedtls/library/ssl_srv.o \
mbedtls/library/x509_crt.o \
mbedtls/library/ecdh.o \
mbedtls/library/asn1write.o \
mbedtls/library/md4.o \
mbedtls/library/debug.o \
mbedtls/library/x509_create.o \
mbedtls/library/ecjpake.o \
mbedtls/library/oid.o \
mbedtls/library/md5.o \
mbedtls/library/ssl_ciphersuites.o \
mbedtls/library/sha512.o \
mbedtls/library/xtea.o \
mbedtls/library/aes.o \
mbedtls/library/cipher_wrap.o \
mbedtls/library/arc4.o \
mbedtls/library/bignum.o \
mbedtls/library/pkparse.o \
mbedtls/library/padlock.o \
mbedtls/library/threading.o \
mbedtls/library/x509_crl.o \
mbedtls/library/pkcs11.o \
mbedtls/library/aesni.o \
mbedtls/library/timing.o \
mbedtls/library/certs.o \
mbedtls/library/pkcs5.o \
mbedtls/library/ssl_cookie.o \
mbedtls/library/camellia.o \
mbedtls/library/havege.o \
mbedtls/library/des.o \
mbedtls/library/x509write_csr.o \
mbedtls/library/platform.o \
mbedtls/library/ctr_drbg.o \
mbedtls/library/x509write_crt.o \
mbedtls/library/pk_wrap.o \
port/esp_bignum.o \
port/esp_hardware.o \
port/esp_sha1.o \
port/esp_sha256.o \
port/esp_sha512.o \
)
$(BUILD)/$(ESPCOMP)/wpa_supplicant/%.o: CFLAGS += -DEMBEDDED_SUPP -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_MSCHAPv2 -DEAP_TTLS -DEAP_TLS -DEAP_PEAP -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -D__ets__ -Wno-strict-aliasing
ESPIDF_WPA_SUPPLICANT_O = $(addprefix $(ESPCOMP)/wpa_supplicant/,\
src/crypto/aes-internal-enc.o \
src/crypto/sha256-internal.o \
src/crypto/md5-internal.o \
src/crypto/aes-internal.o \
src/crypto/sha1.o \
src/crypto/aes-internal-dec.o \
src/crypto/aes-unwrap.o \
src/crypto/crypto_internal-rsa.o \
src/crypto/dh_groups.o \
src/crypto/crypto_internal.o \
src/crypto/aes-wrap.o \
src/crypto/sha1-internal.o \
src/crypto/dh_group5.o \
src/crypto/sha256.o \
src/crypto/rc4.o \
src/crypto/md5.o \
src/crypto/aes-cbc.o \
src/crypto/sha1-pbkdf2.o \
src/crypto/bignum.o \
src/crypto/crypto_internal-modexp.o \
src/crypto/crypto_internal-cipher.o \
src/fast_crypto/fast_aes-unwrap.o \
src/fast_crypto/fast_aes-wrap.o \
src/fast_crypto/fast_sha256.o \
src/fast_crypto/fast_sha256-internal.o \
port/os_xtensa.o \
)
OBJ_ESPIDF =
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NEWLIB_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_DRIVER_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ESP32_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_HEAP_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_SOC_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_CXX_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ETHERNET_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_EXPAT_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_PTHREAD_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_FREERTOS_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_VFS_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_JSON_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_LOG_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_LWIP_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_MBEDTLS_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_XTENSA_DEBUG_MODULE_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_TCPIP_ADAPTER_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_APP_TRACE_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_APP_UPDATE_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NGHTTP_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NVS_FLASH_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_OPENSSL_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_SMARTCONFIG_ACK_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_SPI_FLASH_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ULP_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_WPA_SUPPLICANT_O))
################################################################################
# Main targets
all: $(BUILD)/firmware.bin
.PHONY: idf-version deploy erase
idf-version:
$(ECHO) "ESP IDF supported hash: $(ESPIDF_SUPHASH)"
$(BUILD)/firmware.bin: $(BUILD)/bootloader.bin $(BUILD)/partitions.bin $(BUILD)/application.bin
$(ECHO) "Create $@"
$(Q)$(PYTHON) makeimg.py $^ $@
deploy: $(BUILD)/firmware.bin
$(ECHO) "Writing $^ to the board"
$(Q)$(ESPTOOL) --chip esp32 --port $(PORT) --baud $(BAUD) write_flash -z --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) 0x1000 $^
erase:
$(ECHO) "Erasing flash"
$(Q)$(ESPTOOL) --chip esp32 --port $(PORT) --baud $(BAUD) erase_flash
################################################################################
# Declarations to build the application
OBJ = $(OBJ_MP) $(OBJ_ESPIDF)
APP_LD_ARGS =
APP_LD_ARGS += $(LDFLAGS_MOD)
APP_LD_ARGS += --start-group
APP_LD_ARGS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc
APP_LD_ARGS += -L$(dir $(LIBSTDCXX_FILE_NAME)) -lstdc++
APP_LD_ARGS += $(LIBC_LIBM)
APP_LD_ARGS += $(ESPCOMP)/esp32/libhal.a
APP_LD_ARGS += -L$(ESPCOMP)/esp32/lib -lcore -lmesh -lnet80211 -lphy -lrtc -lpp -lwpa -lsmartconfig -lcoexist -lwps -lwpa2
APP_LD_ARGS += $(OBJ)
APP_LD_ARGS += --end-group
$(BUILD)/esp32_out.ld: sdkconfig.h
$(Q)$(CC) -I. -C -P -x c -E $(ESPCOMP)/esp32/ld/esp32.ld -o $@
$(BUILD)/application.bin: $(BUILD)/application.elf
$(ECHO) "Create $@"
$(Q)$(ESPTOOL) --chip esp32 elf2image --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) --flash_size $(FLASH_SIZE) $<
$(BUILD)/application.elf: $(OBJ) $(BUILD)/esp32_out.ld
$(ECHO) "LINK $@"
$(Q)$(LD) $(LDFLAGS) -o $@ $(APP_LD_ARGS)
$(Q)$(SIZE) $@
define compile_cxx
$(ECHO) "CXX $<"
$(Q)$(CXX) $(CXXFLAGS) -c -MD -o $@ $<
@# The following fixes the dependency file.
@# See http://make.paulandlesley.org/autodep.html for details.
@# Regex adjusted from the above to play better with Windows paths, etc.
@$(CP) $(@:.o=.d) $(@:.o=.P); \
$(SED) -e 's/#.*//' -e 's/^.*: *//' -e 's/ *\\$$//' \
-e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.d) >> $(@:.o=.P); \
$(RM) -f $(@:.o=.d)
endef
vpath %.cpp . $(TOP)
$(BUILD)/%.o: %.cpp
$(call compile_cxx)
################################################################################
# Declarations to build the bootloader
$(BUILD)/bootloader/$(ESPCOMP)/%.o: CFLAGS += -DBOOTLOADER_BUILD=1 -I$(ESPCOMP)/bootloader_support/include_priv -I$(ESPCOMP)/bootloader_support/include -I$(ESPCOMP)/micro-ecc/micro-ecc -I$(ESPCOMP)/esp32 -Wno-error=format
BOOTLOADER_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\
bootloader_support/src/bootloader_clock.o \
bootloader_support/src/bootloader_common.o \
bootloader_support/src/bootloader_flash.o \
bootloader_support/src/bootloader_init.o \
bootloader_support/src/bootloader_random.o \
bootloader_support/src/bootloader_sha.o \
bootloader_support/src/bootloader_utility.o \
bootloader_support/src/efuse.o \
bootloader_support/src/flash_qio_mode.o \
bootloader_support/src/secure_boot_signatures.o \
bootloader_support/src/secure_boot.o \
bootloader_support/src/esp_image_format.o \
bootloader_support/src/flash_encrypt.o \
bootloader_support/src/flash_partitions.o \
log/log.o \
spi_flash/spi_flash_rom_patch.o \
soc/esp32/rtc_clk.o \
soc/esp32/rtc_time.o \
soc/esp32/cpu_util.o \
micro-ecc/micro-ecc/uECC.o \
bootloader/subproject/main/bootloader_start.o \
)
BOOTLOADER_LIBS =
BOOTLOADER_LIBS += -Wl,--start-group
BOOTLOADER_LIBS += $(BOOTLOADER_OBJ)
BOOTLOADER_LIBS += -L$(ESPCOMP)/esp32/lib -lrtc
BOOTLOADER_LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc
BOOTLOADER_LIBS += -Wl,--end-group
BOOTLOADER_LDFLAGS =
BOOTLOADER_LDFLAGS += -nostdlib
BOOTLOADER_LDFLAGS += -L$(ESPIDF)/lib
BOOTLOADER_LDFLAGS += -L$(ESPIDF)/ld
BOOTLOADER_LDFLAGS += -u call_user_start_cpu0
BOOTLOADER_LDFLAGS += -Wl,--gc-sections
BOOTLOADER_LDFLAGS += -static
BOOTLOADER_LDFLAGS += -Wl,-EL
BOOTLOADER_LDFLAGS += -Wl,-Map=$(@:.elf=.map) -Wl,--cref
BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/bootloader/subproject/main/esp32.bootloader.ld
BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/bootloader/subproject/main/esp32.bootloader.rom.ld
BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.rom.ld
BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.rom.spiram_incompatible_fns.ld
BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.peripherals.ld
BOOTLOADER_OBJ_DIRS = $(sort $(dir $(BOOTLOADER_OBJ)))
$(BOOTLOADER_OBJ): | $(BOOTLOADER_OBJ_DIRS)
$(BOOTLOADER_OBJ_DIRS):
$(MKDIR) -p $@
$(BUILD)/bootloader/%.o: %.c
$(call compile_c)
$(BUILD)/bootloader.bin: $(BUILD)/bootloader.elf
$(ECHO) "Create $@"
$(Q)$(ESPTOOL) --chip esp32 elf2image --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ) --flash_size $(FLASH_SIZE) $<
$(BUILD)/bootloader.elf: $(BOOTLOADER_OBJ)
$(ECHO) "LINK $@"
$(Q)$(CC) $(BOOTLOADER_LDFLAGS) -o $@ $(BOOTLOADER_LIBS)
################################################################################
# Declarations to build the partitions
PYTHON2 ?= python2
PART_SRC = partitions.csv
$(BUILD)/partitions.bin: $(PART_SRC)
$(ECHO) "Create $@"
$(Q)$(PYTHON2) $(ESPCOMP)/partition_table/gen_esp32part.py -q $< $@
################################################################################
include $(TOP)/py/mkrules.mk

View File

@ -1,202 +0,0 @@
MicroPython port to the ESP32
=============================
This is an experimental port of MicroPython to the Espressif ESP32
microcontroller. It uses the ESP-IDF framework and MicroPython runs as
a task under FreeRTOS.
Supported features include:
- REPL (Python prompt) over UART0.
- 16k stack for the MicroPython task and 96k Python heap.
- Many of MicroPython's features are enabled: unicode, arbitrary-precision
integers, single-precision floats, complex numbers, frozen bytecode, as
well as many of the internal modules.
- Internal filesystem using the flash (currently 2M in size).
- The machine module with GPIO, UART, SPI, software I2C, ADC, DAC, PWM,
TouchPad, WDT and Timer.
- The network module with WLAN (WiFi) support.
Development of this ESP32 port was sponsored in part by Microbric Pty Ltd.
Setting up the toolchain and ESP-IDF
------------------------------------
There are two main components that are needed to build the firmware:
- the Xtensa cross-compiler that targets the CPU in the ESP32 (this is
different to the compiler used by the ESP8266)
- the Espressif IDF (IoT development framework, aka SDK)
The ESP-IDF changes quickly and MicroPython only supports a certain version. The
git hash of this version can be found by running `make` without a configured
`ESPIDF`. Then you can fetch only the given esp-idf using the following command:
$ git clone https://github.com/espressif/esp-idf.git
$ git checkout <Current supported ESP-IDF commit hash>
$ git submodule update --init --recursive
The binary toolchain (binutils, gcc, etc.) can be installed using the following
guides:
* [Linux installation](https://esp-idf.readthedocs.io/en/latest/get-started/linux-setup.html)
* [MacOS installation](https://esp-idf.readthedocs.io/en/latest/get-started/macos-setup.html)
* [Windows installation](https://esp-idf.readthedocs.io/en/latest/get-started/windows-setup.html)
If you are on a Windows machine then the
[Windows Subsystem for Linux](https://msdn.microsoft.com/en-au/commandline/wsl/install_guide)
is the most efficient way to install the ESP32 toolchain and build the project.
If you use WSL then follow the
[Linux guidelines](https://esp-idf.readthedocs.io/en/latest/get-started/linux-setup.html)
for the ESP-IDF instead of the Windows ones.
The Espressif ESP-IDF instructions above only install pyserial for Python 2,
so if you're running Python 3 or a non-system Python you'll also need to
install `pyserial` (or `esptool`) so that the Makefile can flash the board
and set parameters:
```bash
$ pip install pyserial
```
Once everything is set up you should have a functioning toolchain with
prefix xtensa-esp32-elf- (or otherwise if you configured it differently)
as well as a copy of the ESP-IDF repository. You will need to update your `PATH`
environment variable to include the ESP32 toolchain. For example, you can issue
the following commands on (at least) Linux:
$ export PATH=$PATH:$HOME/esp/crosstool-NG/builds/xtensa-esp32-elf/bin
You can put this command in your `.profile` or `.bash_login`.
You then need to set the `ESPIDF` environment/makefile variable to point to
the root of the ESP-IDF repository. You can set the variable in your PATH,
or at the command line when calling make, or in your own custom `makefile`.
The last option is recommended as it allows you to easily configure other
variables for the build. In that case, create a new file in the esp32
directory called `makefile` and add the following lines to that file:
```
ESPIDF = <path to root of esp-idf repository>
#PORT = /dev/ttyUSB0
#FLASH_MODE = qio
#FLASH_SIZE = 4MB
#CROSS_COMPILE = xtensa-esp32-elf-
#CONFIG_SPIRAM_SUPPORT = 1
include Makefile
```
Be sure to enter the correct path to your local copy of the IDF repository
(and use `$(HOME)`, not tilde, to reference your home directory).
If your filesystem is case-insensitive then you'll need to use `GNUmakefile`
instead of `makefile`.
If the Xtensa cross-compiler is not in your path you can use the
`CROSS_COMPILE` variable to set its location. Other options of interest
are `PORT` for the serial port of your esp32 module, and `FLASH_MODE`
(which may need to be `dio` for some modules)
and `FLASH_SIZE`. See the Makefile for further information.
Building the firmware
---------------------
The MicroPython cross-compiler must be built to pre-compile some of the
built-in scripts to bytecode. This can be done by (from the root of
this repository):
```bash
$ make -C mpy-cross
```
The ESP32 port has a dependency on Berkeley DB, which is an external
dependency (git submodule). You'll need to have git initialize that
module using the commands:
```bash
$ git submodule init lib/berkeley-db-1.xx
$ git submodule update
```
Then to build MicroPython for the ESP32 run:
```bash
$ cd ports/esp32
$ make
```
This will produce binary firmware images in the `build/` subdirectory
(three of them: bootloader.bin, partitions.bin and application.bin).
To flash the firmware you must have your ESP32 module in the bootloader
mode and connected to a serial port on your PC. Refer to the documentation
for your particular ESP32 module for how to do this. The serial port and
flash settings are set in the `Makefile`, and can be overridden in your
local `makefile`; see above for more details.
You will also need to have user permissions to access the /dev/ttyUSB0 device.
On Linux, you can enable this by adding your user to the `dialout` group,
and rebooting or logging out and in again.
```bash
$ sudo adduser <username> dialout
```
If you are installing MicroPython to your module for the first time, or
after installing any other firmware, you should first erase the flash
completely:
```bash
$ make erase
```
To flash the MicroPython firmware to your ESP32 use:
```bash
$ make deploy
```
This will use the `esptool.py` script (provided by ESP-IDF) to download the
binary images.
Getting a Python prompt
-----------------------
You can get a prompt via the serial port, via UART0, which is the same UART
that is used for programming the firmware. The baudrate for the REPL is
115200 and you can use a command such as:
```bash
$ picocom -b 115200 /dev/ttyUSB0
```
Configuring the WiFi and using the board
----------------------------------------
The ESP32 port is designed to be (almost) equivalent to the ESP8266 in
terms of the modules and user-facing API. There are some small differences,
notably that the ESP32 does not automatically connect to the last access
point when booting up. But for the most part the documentation and tutorials
for the ESP8266 should apply to the ESP32 (at least for the components that
are implemented).
See http://docs.micropython.org/en/latest/esp8266/esp8266/quickref.html for
a quick reference, and http://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/intro.html
for a tutorial.
The following function can be used to connect to a WiFi access point (you can
either pass in your own SSID and password, or change the defaults so you can
quickly call `wlan_connect()` and it just works):
```python
def wlan_connect(ssid='MYSSID', password='MYPASS'):
import network
wlan = network.WLAN(network.STA_IF)
if not wlan.active() or not wlan.isconnected():
wlan.active(True)
print('connecting to:', ssid)
wlan.connect(ssid, password)
while not wlan.isconnected():
pass
print('network config:', wlan.ifconfig())
```
Note that some boards require you to configure the WiFi antenna before using
the WiFi. On Pycom boards like the LoPy and WiPy 2.0 you need to execute the
following code to select the internal antenna (best to put this line in your
boot.py file):
```python
import machine
antenna = machine.Pin(16, machine.Pin.OUT, value=0)
```
Troubleshooting
---------------
* Continuous reboots after programming: Ensure FLASH_MODE is correct for your
board (e.g. ESP-WROOM-32 should be DIO). Then perform a `make clean`, rebuild,
redeploy.

View File

@ -1,126 +0,0 @@
# ULP
To compile binarys for the ulp you need the ulp toolkit. Download it from https://github.com/espressif/binutils-esp32ulp/wiki#downloads
Then extract it, then add ```esp32ulp-elf-binutils/bin``` to your PATH
## Example Makefile
```make
ULP_S_SOURCES := main.S
ULP_APP_NAME := test
ULP_LD_SCRIPT := esp32.ulp.ld
SRC_PATH := src
BUILD_PATH := build
include $(ESPIDF)/components/ulp/Makefile.projbuild
ULP_ELF := $(ULP_APP_NAME).elf
ULP_MAP := $(ULP_ELF:.elf=.map)
ULP_SYM := $(ULP_ELF:.elf=.sym)
ULP_BIN := $(ULP_ELF:.elf=.bin)
ULP_EXPORTS_LD := $(ULP_ELF:.elf=.ld)
ULP_EXPORTS_HEADER := $(ULP_ELF:.elf=.h)
ULP_OBJECTS := $(notdir $(ULP_S_SOURCES:.S=.ulp.o))
ULP_DEP := $(notdir $(ULP_S_SOURCES:.S=.ulp.d)) $(ULP_LD_SCRIPT:.ld=.d)
ULP_PREPROCESSED := $(notdir $(ULP_S_SOURCES:.S=.ulp.pS))
ULP_LISTINGS := $(notdir $(ULP_S_SOURCES:.S=.ulp.lst))
.PHONY: all clean
all: $(BUILD_PATH) $(BUILD_PATH)/$(ULP_BIN)
clean:
rm -rf $(BUILD_PATH)
$(BUILD_PATH):
mkdir $@
# Generate preprocessed linker file.
$(BUILD_PATH)/$(ULP_APP_NAME).ld: $(SRC_PATH)/$(ULP_LD_SCRIPT)
cpp -P $< -o $@
# Generate preprocessed assembly files.
# To inspect these preprocessed files, add a ".PRECIOUS: %.ulp.pS" rule.
$(BUILD_PATH)/%.ulp.pS: $(SRC_PATH)/%.S
cpp $< -o $@
# Compiled preprocessed files into object files.
$(BUILD_PATH)/%.ulp.o: $(BUILD_PATH)/%.ulp.pS
$(ULP_AS) -al=$(patsubst %.ulp.o,%.ulp.lst,$@) -o $@ $<
# Link object files and generate map file
$(BUILD_PATH)/$(ULP_ELF): $(BUILD_PATH)/$(ULP_OBJECTS) $(BUILD_PATH)/$(ULP_APP_NAME).ld
$(ULP_LD) -o $@ -A elf32-esp32ulp -Map=$(BUILD_PATH)/$(ULP_MAP) -T $(BUILD_PATH)/$(ULP_APP_NAME).ld $<
# Dump the list of global symbols in a convenient format.
$(ULP_SYM): $(ULP_ELF)
$(ULP_NM) -g -f posix $< > $@
# Dump the binary for inclusion into the project
$(BUILD_PATH)/$(ULP_BIN): $(BUILD_PATH)/$(ULP_ELF)
$(ULP_OBJCOPY) -O binary $< $@
```
## Example linker script for the ulp
```
#define ULP_BIN_MAGIC 0x00706c75
#define HEADER_SIZE 12
#define CONFIG_ULP_COPROC_RESERVE_MEM 4096
MEMORY
{
ram(RW) : ORIGIN = 0, LENGTH = CONFIG_ULP_COPROC_RESERVE_MEM
}
SECTIONS
{
.text : AT(HEADER_SIZE)
{
*(.text)
} >ram
.data :
{
. = ALIGN(4);
*(.data)
} >ram
.bss :
{
. = ALIGN(4);
*(.bss)
} >ram
.header : AT(0)
{
LONG(ULP_BIN_MAGIC)
SHORT(LOADADDR(.text))
SHORT(SIZEOF(.text))
SHORT(SIZEOF(.data))
SHORT(SIZEOF(.bss))
}
}
```
## Example ulp code
```asm
move R3, 99
move R0, 10
# mem[R0+0] = R3
st R3, R0, 0
HALT
```
## Example python code using the ulp
```python
import esp32
import time
u = esp32.ULP()
with open('test.bin', 'rb') as f:
b = f.read()
u.load_binary(0,b)
u.run(0)
```

View File

@ -1,254 +0,0 @@
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
/* RTC fast memory holds RTC wake stub code,
including from any source file named rtc_wake_stub*.c
*/
.rtc.text :
{
. = ALIGN(4);
*(.rtc.literal .rtc.text)
*rtc_wake_stub*.o(.literal .text .literal.* .text.*)
} > rtc_iram_seg
/* RTC slow memory holds RTC wake stub
data/rodata, including from any source file
named rtc_wake_stub*.c
*/
.rtc.data :
{
_rtc_data_start = ABSOLUTE(.);
*(.rtc.data)
*(.rtc.rodata)
*rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*)
_rtc_data_end = ABSOLUTE(.);
} > rtc_slow_seg
/* RTC bss, from any source file named rtc_wake_stub*.c */
.rtc.bss (NOLOAD) :
{
_rtc_bss_start = ABSOLUTE(.);
*rtc_wake_stub*.o(.bss .bss.*)
*rtc_wake_stub*.o(COMMON)
_rtc_bss_end = ABSOLUTE(.);
} > rtc_slow_seg
/* This section holds data that should not be initialized at power up
and will be retained during deep sleep. The section located in
RTC SLOW Memory area. User data marked with RTC_NOINIT_ATTR will be placed
into this section. See the file "esp_attr.h" for more information.
*/
.rtc_noinit (NOLOAD):
{
. = ALIGN(4);
_rtc_noinit_start = ABSOLUTE(.);
*(.rtc_noinit .rtc_noinit.*)
. = ALIGN(4) ;
_rtc_noinit_end = ABSOLUTE(.);
} > rtc_slow_seg
/* Send .iram0 code to iram */
.iram0.vectors :
{
/* Vectors go to IRAM */
_init_start = ABSOLUTE(.);
/* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */
. = 0x0;
KEEP(*(.WindowVectors.text));
. = 0x180;
KEEP(*(.Level2InterruptVector.text));
. = 0x1c0;
KEEP(*(.Level3InterruptVector.text));
. = 0x200;
KEEP(*(.Level4InterruptVector.text));
. = 0x240;
KEEP(*(.Level5InterruptVector.text));
. = 0x280;
KEEP(*(.DebugExceptionVector.text));
. = 0x2c0;
KEEP(*(.NMIExceptionVector.text));
. = 0x300;
KEEP(*(.KernelExceptionVector.text));
. = 0x340;
KEEP(*(.UserExceptionVector.text));
. = 0x3C0;
KEEP(*(.DoubleExceptionVector.text));
. = 0x400;
*(.*Vector.literal)
*(.UserEnter.literal);
*(.UserEnter.text);
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
_init_end = ABSOLUTE(.);
/* This goes here, not at top of linker script, so addr2line finds it last,
and uses it in preference to the first symbol in IRAM */
_iram_start = ABSOLUTE(0);
} > iram0_0_seg
.iram0.text :
{
/* Code marked as runnning out of IRAM */
_iram_text_start = ABSOLUTE(.);
*(.iram1 .iram1.*)
*freertos/*(.literal .text .literal.* .text.*)
*heap/multi_heap.o(.literal .text .literal.* .text.*)
*heap/multi_heap_poisoning.o(.literal .text .literal.* .text.*)
*esp32/panic.o(.literal .text .literal.* .text.*)
*esp32/core_dump.o(.literal .text .literal.* .text.*)
*app_trace/*(.literal .text .literal.* .text.*)
*xtensa-debug-module/eri.o(.literal .text .literal.* .text.*)
*librtc.a:(.literal .text .literal.* .text.*)
*soc/esp32/*(.literal .text .literal.* .text.*)
*libhal.a:(.literal .text .literal.* .text.*)
*libgcc.a:lib2funcs.o(.literal .text .literal.* .text.*)
*spi_flash/spi_flash_rom_patch.o(.literal .text .literal.* .text.*)
*libgcov.a:(.literal .text .literal.* .text.*)
INCLUDE esp32.spiram.rom-functions-iram.ld
*py/scheduler.o*(.literal .text .literal.* .text.*)
_iram_text_end = ABSOLUTE(.);
} > iram0_0_seg
.dram0.data :
{
_data_start = ABSOLUTE(.);
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
*(.dram1 .dram1.*)
*esp32/panic.o(.rodata .rodata.*)
*libphy.a:(.rodata .rodata.*)
*soc/esp32/rtc_clk.o(.rodata .rodata.*)
*app_trace/app_trace.o(.rodata .rodata.*)
*libgcov.a:(.rodata .rodata.*)
*heap/multi_heap.o(.rodata .rodata.*)
*heap/multi_heap_poisoning.o(.rodata .rodata.*)
INCLUDE esp32.spiram.rom-functions-dram.ld
_data_end = ABSOLUTE(.);
. = ALIGN(4);
} > dram0_0_seg
/*This section holds data that should not be initialized at power up.
The section located in Internal SRAM memory region. The macro _NOINIT
can be used as attribute to place data into this section.
See the esp_attr.h file for more information.
*/
.noinit (NOLOAD):
{
. = ALIGN(4);
_noinit_start = ABSOLUTE(.);
*(.noinit .noinit.*)
. = ALIGN(4) ;
_noinit_end = ABSOLUTE(.);
} > dram0_0_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.share.mem)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
/* The heap starts right after end of this section */
_heap_start = ABSOLUTE(.);
} > dram0_0_seg
.flash.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
*(.gnu.linkonce.r.*)
*(.rodata1)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table .gcc_except_table.*)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
. = (. + 3) & ~ 3;
__eh_frame = ABSOLUTE(.);
KEEP(*(.eh_frame))
. = (. + 7) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_thread_local_start = ABSOLUTE(.);
*(.tdata)
*(.tdata.*)
*(.tbss)
*(.tbss.*)
_thread_local_end = ABSOLUTE(.);
. = ALIGN(4);
} >drom0_0_seg
.flash.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
_text_end = ABSOLUTE(.);
_etext = .;
/* Similar to _iram_start, this symbol goes here so it is
resolved by addr2line in preference to the first symbol in
the flash.text segment.
*/
_flash_cache_start = ABSOLUTE(0);
} >iram0_2_seg
}

View File

@ -1,97 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 "Andreas Valder" <andreas.valder@serioese.gmbh>
*
* 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.
*/
#include "py/runtime.h"
#include "esp32/ulp.h"
#include "esp_err.h"
typedef struct _esp32_ulp_obj_t {
mp_obj_base_t base;
} esp32_ulp_obj_t;
const mp_obj_type_t esp32_ulp_type;
// singleton ULP object
STATIC const esp32_ulp_obj_t esp32_ulp_obj = {{&esp32_ulp_type}};
STATIC mp_obj_t esp32_ulp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 0, 0, false);
// return constant object
return (mp_obj_t)&esp32_ulp_obj;
}
STATIC mp_obj_t esp32_ulp_set_wakeup_period(mp_obj_t self_in, mp_obj_t period_index_in, mp_obj_t period_us_in) {
mp_uint_t period_index = mp_obj_get_int(period_index_in);
mp_uint_t period_us = mp_obj_get_int(period_us_in);
int _errno = ulp_set_wakeup_period(period_index, period_us);
if (_errno != ESP_OK) {
mp_raise_OSError(_errno);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp32_ulp_set_wakeup_period_obj, esp32_ulp_set_wakeup_period);
STATIC mp_obj_t esp32_ulp_load_binary(mp_obj_t self_in, mp_obj_t load_addr_in, mp_obj_t program_binary_in) {
mp_uint_t load_addr = mp_obj_get_int(load_addr_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(program_binary_in, &bufinfo, MP_BUFFER_READ);
int _errno = ulp_load_binary(load_addr, bufinfo.buf, bufinfo.len/sizeof(uint32_t));
if (_errno != ESP_OK) {
mp_raise_OSError(_errno);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp32_ulp_load_binary_obj, esp32_ulp_load_binary);
STATIC mp_obj_t esp32_ulp_run(mp_obj_t self_in, mp_obj_t entry_point_in) {
mp_uint_t entry_point = mp_obj_get_int(entry_point_in);
int _errno = ulp_run(entry_point/sizeof(uint32_t));
if (_errno != ESP_OK) {
mp_raise_OSError(_errno);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_ulp_run_obj, esp32_ulp_run);
STATIC const mp_rom_map_elem_t esp32_ulp_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_set_wakeup_period), MP_ROM_PTR(&esp32_ulp_set_wakeup_period_obj) },
{ MP_ROM_QSTR(MP_QSTR_load_binary), MP_ROM_PTR(&esp32_ulp_load_binary_obj) },
{ MP_ROM_QSTR(MP_QSTR_run), MP_ROM_PTR(&esp32_ulp_run_obj) },
{ MP_ROM_QSTR(MP_QSTR_RESERVE_MEM), MP_ROM_INT(CONFIG_ULP_COPROC_RESERVE_MEM) },
};
STATIC MP_DEFINE_CONST_DICT(esp32_ulp_locals_dict, esp32_ulp_locals_dict_table);
const mp_obj_type_t esp32_ulp_type = {
{ &mp_type_type },
.name = MP_QSTR_ULP,
.make_new = esp32_ulp_make_new,
.locals_dict = (mp_obj_t)&esp32_ulp_locals_dict,
};

View File

@ -1,53 +0,0 @@
// Original version from https://github.com/adafruit/Adafruit_NeoPixel
// Modifications by dpgeorge to support auto-CPU-frequency detection
// This is a mash-up of the Due show() code + insights from Michael Miller's
// ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus
// Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution.
#include "py/mpconfig.h"
#include "py/mphal.h"
#include "modesp.h"
void IRAM_ATTR esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t timing) {
uint8_t *p, *end, pix, mask;
uint32_t t, time0, time1, period, c, startTime, pinMask;
pinMask = 1 << pin;
p = pixels;
end = p + numBytes;
pix = *p++;
mask = 0x80;
startTime = 0;
uint32_t fcpu = ets_get_cpu_frequency() * 1000000;
if (timing == 1) {
// 800 KHz
time0 = (fcpu * 0.35) / 1000000; // 0.35us
time1 = (fcpu * 0.8) / 1000000; // 0.8us
period = (fcpu * 1.25) / 1000000; // 1.25us per bit
} else {
// 400 KHz
time0 = (fcpu * 0.5) / 1000000; // 0.35us
time1 = (fcpu * 1.2) / 1000000; // 0.8us
period = (fcpu * 2.5) / 1000000; // 1.25us per bit
}
uint32_t irq_state = mp_hal_quiet_timing_enter();
for (t = time0;; t = time0) {
if (pix & mask) t = time1; // Bit high duration
while (((c = mp_hal_ticks_cpu()) - startTime) < period); // Wait for bit start
GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, pinMask); // Set high
startTime = c; // Save start time
while (((c = mp_hal_ticks_cpu()) - startTime) < t); // Wait high duration
GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, pinMask); // Set low
if (!(mask >>= 1)) { // Next bit/byte
if(p >= end) break;
pix = *p++;
mask = 0x80;
}
}
while ((mp_hal_ticks_cpu() - startTime) < period); // Wait for last bit
mp_hal_quiet_timing_exit(irq_state);
}

View File

@ -1,80 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2015-2017 Damien P. George
*
* 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.
*/
#include "py/mphal.h"
#include "esp8266/esponewire.h"
#define TIMING_RESET1 (0)
#define TIMING_RESET2 (1)
#define TIMING_RESET3 (2)
#define TIMING_READ1 (3)
#define TIMING_READ2 (4)
#define TIMING_READ3 (5)
#define TIMING_WRITE1 (6)
#define TIMING_WRITE2 (7)
#define TIMING_WRITE3 (8)
uint16_t esp_onewire_timings[9] = {480, 40, 420, 5, 5, 40, 10, 50, 10};
#define DELAY_US mp_hal_delay_us_fast
int esp_onewire_reset(mp_hal_pin_obj_t pin) {
mp_hal_pin_write(pin, 0);
DELAY_US(esp_onewire_timings[TIMING_RESET1]);
uint32_t i = MICROPY_BEGIN_ATOMIC_SECTION();
mp_hal_pin_write(pin, 1);
DELAY_US(esp_onewire_timings[TIMING_RESET2]);
int status = !mp_hal_pin_read(pin);
MICROPY_END_ATOMIC_SECTION(i);
DELAY_US(esp_onewire_timings[TIMING_RESET3]);
return status;
}
int esp_onewire_readbit(mp_hal_pin_obj_t pin) {
mp_hal_pin_write(pin, 1);
uint32_t i = MICROPY_BEGIN_ATOMIC_SECTION();
mp_hal_pin_write(pin, 0);
DELAY_US(esp_onewire_timings[TIMING_READ1]);
mp_hal_pin_write(pin, 1);
DELAY_US(esp_onewire_timings[TIMING_READ2]);
int value = mp_hal_pin_read(pin);
MICROPY_END_ATOMIC_SECTION(i);
DELAY_US(esp_onewire_timings[TIMING_READ3]);
return value;
}
void esp_onewire_writebit(mp_hal_pin_obj_t pin, int value) {
uint32_t i = MICROPY_BEGIN_ATOMIC_SECTION();
mp_hal_pin_write(pin, 0);
DELAY_US(esp_onewire_timings[TIMING_WRITE1]);
if (value) {
mp_hal_pin_write(pin, 1);
}
DELAY_US(esp_onewire_timings[TIMING_WRITE2]);
mp_hal_pin_write(pin, 1);
DELAY_US(esp_onewire_timings[TIMING_WRITE3]);
MICROPY_END_ATOMIC_SECTION(i);
}

View File

@ -1,41 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014, 2016 Damien P. George
*
* 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.
*/
#include <sys/time.h>
#include "lib/oofatfs/ff.h"
#include "timeutils.h"
DWORD get_fattime(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
timeutils_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(tv.tv_sec, &tm);
return (((DWORD)(tm.tm_year - 1980) << 25) | ((DWORD)tm.tm_mon << 21) | ((DWORD)tm.tm_mday << 16) |
((DWORD)tm.tm_hour << 11) | ((DWORD)tm.tm_min << 5) | ((DWORD)tm.tm_sec >> 1));
}

View File

@ -1,66 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Damien P. George
* Copyright (c) 2017 Pycom Limited
*
* 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.
*/
#include <stdio.h>
#include "py/mpconfig.h"
#include "py/mpstate.h"
#include "py/gc.h"
#include "py/mpthread.h"
#include "gccollect.h"
#include "soc/cpu.h"
#include "xtensa/hal.h"
static void gc_collect_inner(int level) {
if (level < XCHAL_NUM_AREGS / 8) {
gc_collect_inner(level + 1);
if (level != 0) {
return;
}
}
if (level == XCHAL_NUM_AREGS / 8) {
// get the sp
volatile uint32_t sp = (uint32_t)get_sp();
gc_collect_root((void**)sp, ((mp_uint_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t));
return;
}
// trace root pointers from any threads
#if MICROPY_PY_THREAD
mp_thread_gc_others();
#endif
}
void gc_collect(void) {
gc_collect_start();
gc_collect_inner(0);
gc_collect_end();
}

View File

@ -1,42 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Damien P. George
*
* 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.
*/
extern uint32_t _text_start;
extern uint32_t _text_end;
extern uint32_t _irom0_text_start;
extern uint32_t _irom0_text_end;
extern uint32_t _data_start;
extern uint32_t _data_end;
extern uint32_t _rodata_start;
extern uint32_t _rodata_end;
extern uint32_t _bss_start;
extern uint32_t _bss_end;
extern uint32_t _heap_start;
extern uint32_t _heap_end;
void gc_collect(void);

View File

@ -1,65 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2016 Damien P. George
*
* 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.
*/
#include "py/builtin.h"
const char esp32_help_text[] =
"Welcome to MicroPython on the ESP32!\n"
"\n"
"For generic online docs please visit http://docs.micropython.org/\n"
"\n"
"For access to the hardware use the 'machine' module:\n"
"\n"
"import machine\n"
"pin12 = machine.Pin(12, machine.Pin.OUT)\n"
"pin12.value(1)\n"
"pin13 = machine.Pin(13, machine.Pin.IN, machine.Pin.PULL_UP)\n"
"print(pin13.value())\n"
"i2c = machine.I2C(scl=machine.Pin(21), sda=machine.Pin(22))\n"
"i2c.scan()\n"
"i2c.writeto(addr, b'1234')\n"
"i2c.readfrom(addr, 4)\n"
"\n"
"Basic WiFi configuration:\n"
"\n"
"import network\n"
"sta_if = network.WLAN(network.STA_IF); sta_if.active(True)\n"
"sta_if.scan() # Scan for available access points\n"
"sta_if.connect(\"<AP_name>\", \"<password>\") # Connect to an AP\n"
"sta_if.isconnected() # Check for successful connection\n"
"\n"
"Control commands:\n"
" CTRL-A -- on a blank line, enter raw REPL mode\n"
" CTRL-B -- on a blank line, enter normal REPL mode\n"
" CTRL-C -- interrupt a running program\n"
" CTRL-D -- on a blank line, do a soft reset of the board\n"
" CTRL-E -- on a blank line, enter paste mode\n"
"\n"
"For further help on a specific object, type help(obj)\n"
"For a list of available modules, type help('modules')\n"
;

View File

@ -1,132 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 Nick Moore
*
* 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.
*/
#include <stdio.h>
#include "esp_log.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "modmachine.h"
typedef struct _madc_obj_t {
mp_obj_base_t base;
gpio_num_t gpio_id;
adc1_channel_t adc1_id;
} madc_obj_t;
STATIC const madc_obj_t madc_obj[] = {
{{&machine_adc_type}, GPIO_NUM_36, ADC1_CHANNEL_0},
{{&machine_adc_type}, GPIO_NUM_37, ADC1_CHANNEL_1},
{{&machine_adc_type}, GPIO_NUM_38, ADC1_CHANNEL_2},
{{&machine_adc_type}, GPIO_NUM_39, ADC1_CHANNEL_3},
{{&machine_adc_type}, GPIO_NUM_32, ADC1_CHANNEL_4},
{{&machine_adc_type}, GPIO_NUM_33, ADC1_CHANNEL_5},
{{&machine_adc_type}, GPIO_NUM_34, ADC1_CHANNEL_6},
{{&machine_adc_type}, GPIO_NUM_35, ADC1_CHANNEL_7},
};
STATIC mp_obj_t madc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
const mp_obj_t *args) {
static int initialized = 0;
if (!initialized) {
adc1_config_width(ADC_WIDTH_12Bit);
initialized = 1;
}
mp_arg_check_num(n_args, n_kw, 1, 1, true);
gpio_num_t pin_id = machine_pin_get_id(args[0]);
const madc_obj_t *self = NULL;
for (int i = 0; i < MP_ARRAY_SIZE(madc_obj); i++) {
if (pin_id == madc_obj[i].gpio_id) { self = &madc_obj[i]; break; }
}
if (!self) mp_raise_ValueError("invalid Pin for ADC");
esp_err_t err = adc1_config_channel_atten(self->adc1_id, ADC_ATTEN_0db);
if (err == ESP_OK) return MP_OBJ_FROM_PTR(self);
mp_raise_ValueError("Parameter Error");
}
STATIC void madc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
madc_obj_t *self = self_in;
mp_printf(print, "ADC(Pin(%u))", self->gpio_id);
}
STATIC mp_obj_t madc_read(mp_obj_t self_in) {
madc_obj_t *self = self_in;
int val = adc1_get_raw(self->adc1_id);
if (val == -1) mp_raise_ValueError("Parameter Error");
return MP_OBJ_NEW_SMALL_INT(val);
}
MP_DEFINE_CONST_FUN_OBJ_1(madc_read_obj, madc_read);
STATIC mp_obj_t madc_atten(mp_obj_t self_in, mp_obj_t atten_in) {
madc_obj_t *self = self_in;
adc_atten_t atten = mp_obj_get_int(atten_in);
esp_err_t err = adc1_config_channel_atten(self->adc1_id, atten);
if (err == ESP_OK) return mp_const_none;
mp_raise_ValueError("Parameter Error");
}
MP_DEFINE_CONST_FUN_OBJ_2(madc_atten_obj, madc_atten);
STATIC mp_obj_t madc_width(mp_obj_t cls_in, mp_obj_t width_in) {
adc_bits_width_t width = mp_obj_get_int(width_in);
esp_err_t err = adc1_config_width(width);
if (err == ESP_OK) return mp_const_none;
mp_raise_ValueError("Parameter Error");
}
MP_DEFINE_CONST_FUN_OBJ_2(madc_width_fun_obj, madc_width);
MP_DEFINE_CONST_CLASSMETHOD_OBJ(madc_width_obj, MP_ROM_PTR(&madc_width_fun_obj));
STATIC const mp_rom_map_elem_t madc_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&madc_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_atten), MP_ROM_PTR(&madc_atten_obj) },
{ MP_ROM_QSTR(MP_QSTR_width), MP_ROM_PTR(&madc_width_obj) },
{ MP_ROM_QSTR(MP_QSTR_ATTN_0DB), MP_ROM_INT(ADC_ATTEN_0db) },
{ MP_ROM_QSTR(MP_QSTR_ATTN_2_5DB), MP_ROM_INT(ADC_ATTEN_2_5db) },
{ MP_ROM_QSTR(MP_QSTR_ATTN_6DB), MP_ROM_INT(ADC_ATTEN_6db) },
{ MP_ROM_QSTR(MP_QSTR_ATTN_11DB), MP_ROM_INT(ADC_ATTEN_11db) },
{ MP_ROM_QSTR(MP_QSTR_WIDTH_9BIT), MP_ROM_INT(ADC_WIDTH_9Bit) },
{ MP_ROM_QSTR(MP_QSTR_WIDTH_10BIT), MP_ROM_INT(ADC_WIDTH_10Bit) },
{ MP_ROM_QSTR(MP_QSTR_WIDTH_11BIT), MP_ROM_INT(ADC_WIDTH_11Bit) },
{ MP_ROM_QSTR(MP_QSTR_WIDTH_12BIT), MP_ROM_INT(ADC_WIDTH_12Bit) },
};
STATIC MP_DEFINE_CONST_DICT(madc_locals_dict, madc_locals_dict_table);
const mp_obj_type_t machine_adc_type = {
{ &mp_type_type },
.name = MP_QSTR_ADC,
.print = madc_print,
.make_new = madc_make_new,
.locals_dict = (mp_obj_t)&madc_locals_dict,
};

View File

@ -1,97 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 Nick Moore
*
* 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.
*/
#include <stdio.h>
#include "esp_log.h"
#include "driver/gpio.h"
#include "driver/dac.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "modmachine.h"
typedef struct _mdac_obj_t {
mp_obj_base_t base;
gpio_num_t gpio_id;
dac_channel_t dac_id;
} mdac_obj_t;
STATIC const mdac_obj_t mdac_obj[] = {
{{&machine_dac_type}, GPIO_NUM_25, DAC_CHANNEL_1},
{{&machine_dac_type}, GPIO_NUM_26, DAC_CHANNEL_2},
};
STATIC mp_obj_t mdac_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, 1, true);
gpio_num_t pin_id = machine_pin_get_id(args[0]);
const mdac_obj_t *self = NULL;
for (int i = 0; i < MP_ARRAY_SIZE(mdac_obj); i++) {
if (pin_id == mdac_obj[i].gpio_id) { self = &mdac_obj[i]; break; }
}
if (!self) mp_raise_ValueError("invalid Pin for DAC");
esp_err_t err = dac_output_enable(self->dac_id);
if (err == ESP_OK) {
err = dac_output_voltage(self->dac_id, 0);
}
if (err == ESP_OK) return MP_OBJ_FROM_PTR(self);
mp_raise_ValueError("Parameter Error");
}
STATIC void mdac_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mdac_obj_t *self = self_in;
mp_printf(print, "DAC(Pin(%u))", self->gpio_id);
}
STATIC mp_obj_t mdac_write(mp_obj_t self_in, mp_obj_t value_in) {
mdac_obj_t *self = self_in;
int value = mp_obj_get_int(value_in);
if (value < 0 || value > 255) mp_raise_ValueError("Value out of range");
esp_err_t err = dac_output_voltage(self->dac_id, value);
if (err == ESP_OK) return mp_const_none;
mp_raise_ValueError("Parameter Error");
}
MP_DEFINE_CONST_FUN_OBJ_2(mdac_write_obj, mdac_write);
STATIC const mp_rom_map_elem_t mdac_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mdac_write_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mdac_locals_dict, mdac_locals_dict_table);
const mp_obj_type_t machine_dac_type = {
{ &mp_type_type },
.name = MP_QSTR_DAC,
.print = mdac_print,
.make_new = mdac_make_new,
.locals_dict = (mp_obj_t)&mdac_locals_dict,
};

View File

@ -1,390 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 "Eric Poulsen" <eric@zyxod.com>
*
* 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.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mphal.h"
#include "extmod/machine_spi.h"
#include "modmachine.h"
#include "driver/spi_master.h"
#define MP_HW_SPI_MAX_XFER_BYTES (4092)
#define MP_HW_SPI_MAX_XFER_BITS (MP_HW_SPI_MAX_XFER_BYTES * 8) // Has to be an even multiple of 8
typedef struct _machine_hw_spi_obj_t {
mp_obj_base_t base;
spi_host_device_t host;
uint32_t baudrate;
uint8_t polarity;
uint8_t phase;
uint8_t bits;
uint8_t firstbit;
int8_t sck;
int8_t mosi;
int8_t miso;
spi_device_handle_t spi;
enum {
MACHINE_HW_SPI_STATE_NONE,
MACHINE_HW_SPI_STATE_INIT,
MACHINE_HW_SPI_STATE_DEINIT
} state;
} machine_hw_spi_obj_t;
STATIC void machine_hw_spi_deinit_internal(machine_hw_spi_obj_t *self) {
switch (spi_bus_remove_device(self->spi)) {
case ESP_ERR_INVALID_ARG:
mp_raise_msg(&mp_type_OSError, "invalid configuration");
return;
case ESP_ERR_INVALID_STATE:
mp_raise_msg(&mp_type_OSError, "SPI device already freed");
return;
}
switch (spi_bus_free(self->host)) {
case ESP_ERR_INVALID_ARG:
mp_raise_msg(&mp_type_OSError, "invalid configuration");
return;
case ESP_ERR_INVALID_STATE:
mp_raise_msg(&mp_type_OSError, "SPI bus already freed");
return;
}
int8_t pins[3] = {self->miso, self->mosi, self->sck};
for (int i = 0; i < 3; i++) {
if (pins[i] != -1) {
gpio_pad_select_gpio(pins[i]);
gpio_matrix_out(pins[i], SIG_GPIO_OUT_IDX, false, false);
gpio_set_direction(pins[i], GPIO_MODE_INPUT);
}
}
}
STATIC void machine_hw_spi_init_internal(
machine_hw_spi_obj_t *self,
int8_t host,
int32_t baudrate,
int8_t polarity,
int8_t phase,
int8_t bits,
int8_t firstbit,
int8_t sck,
int8_t mosi,
int8_t miso) {
// if we're not initialized, then we're
// implicitly 'changed', since this is the init routine
bool changed = self->state != MACHINE_HW_SPI_STATE_INIT;
esp_err_t ret;
machine_hw_spi_obj_t old_self = *self;
if (host != -1 && host != self->host) {
self->host = host;
changed = true;
}
if (baudrate != -1 && baudrate != self->baudrate) {
self->baudrate = baudrate;
changed = true;
}
if (polarity != -1 && polarity != self->polarity) {
self->polarity = polarity;
changed = true;
}
if (phase != -1 && phase != self->phase) {
self->phase = phase;
changed = true;
}
if (bits != -1 && bits != self->bits) {
self->bits = bits;
changed = true;
}
if (firstbit != -1 && firstbit != self->firstbit) {
self->firstbit = firstbit;
changed = true;
}
if (sck != -2 && sck != self->sck) {
self->sck = sck;
changed = true;
}
if (mosi != -2 && mosi != self->mosi) {
self->mosi = mosi;
changed = true;
}
if (miso != -2 && miso != self->miso) {
self->miso = miso;
changed = true;
}
if (self->host != HSPI_HOST && self->host != VSPI_HOST) {
mp_raise_ValueError("SPI ID must be either HSPI(1) or VSPI(2)");
}
if (changed) {
if (self->state == MACHINE_HW_SPI_STATE_INIT) {
self->state = MACHINE_HW_SPI_STATE_DEINIT;
machine_hw_spi_deinit_internal(&old_self);
}
} else {
return; // no changes
}
spi_bus_config_t buscfg = {
.miso_io_num = self->miso,
.mosi_io_num = self->mosi,
.sclk_io_num = self->sck,
.quadwp_io_num = -1,
.quadhd_io_num = -1
};
spi_device_interface_config_t devcfg = {
.clock_speed_hz = self->baudrate,
.mode = self->phase | (self->polarity << 1),
.spics_io_num = -1, // No CS pin
.queue_size = 1,
.flags = self->firstbit == MICROPY_PY_MACHINE_SPI_LSB ? SPI_DEVICE_TXBIT_LSBFIRST | SPI_DEVICE_RXBIT_LSBFIRST : 0,
.pre_cb = NULL
};
//Initialize the SPI bus
// FIXME: Does the DMA matter? There are two
ret = spi_bus_initialize(self->host, &buscfg, 1);
switch (ret) {
case ESP_ERR_INVALID_ARG:
mp_raise_msg(&mp_type_OSError, "invalid configuration");
return;
case ESP_ERR_INVALID_STATE:
mp_raise_msg(&mp_type_OSError, "SPI device already in use");
return;
}
ret = spi_bus_add_device(self->host, &devcfg, &self->spi);
switch (ret) {
case ESP_ERR_INVALID_ARG:
mp_raise_msg(&mp_type_OSError, "invalid configuration");
spi_bus_free(self->host);
return;
case ESP_ERR_NO_MEM:
mp_raise_msg(&mp_type_OSError, "out of memory");
spi_bus_free(self->host);
return;
case ESP_ERR_NOT_FOUND:
mp_raise_msg(&mp_type_OSError, "no free slots");
spi_bus_free(self->host);
return;
}
self->state = MACHINE_HW_SPI_STATE_INIT;
}
STATIC void machine_hw_spi_deinit(mp_obj_base_t *self_in) {
machine_hw_spi_obj_t *self = (machine_hw_spi_obj_t *) self_in;
if (self->state == MACHINE_HW_SPI_STATE_INIT) {
self->state = MACHINE_HW_SPI_STATE_DEINIT;
machine_hw_spi_deinit_internal(self);
}
}
STATIC void machine_hw_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
machine_hw_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->state == MACHINE_HW_SPI_STATE_DEINIT) {
mp_raise_msg(&mp_type_OSError, "transfer on deinitialized SPI");
return;
}
struct spi_transaction_t transaction = { 0 };
// Round to nearest whole set of bits
int bits_to_send = len * 8 / self->bits * self->bits;
if (len <= 4) {
if (src != NULL) {
memcpy(&transaction.tx_data, src, len);
}
transaction.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
transaction.length = bits_to_send;
spi_device_transmit(self->spi, &transaction);
if (dest != NULL) {
memcpy(dest, &transaction.rx_data, len);
}
} else {
int offset = 0;
int bits_remaining = bits_to_send;
while (bits_remaining) {
memset(&transaction, 0, sizeof(transaction));
transaction.length =
bits_remaining > MP_HW_SPI_MAX_XFER_BITS ? MP_HW_SPI_MAX_XFER_BITS : bits_remaining;
if (src != NULL) {
transaction.tx_buffer = src + offset;
}
if (dest != NULL) {
transaction.rx_buffer = dest + offset;
}
spi_device_transmit(self->spi, &transaction);
bits_remaining -= transaction.length;
// doesn't need ceil(); loop ends when bits_remaining is 0
offset += transaction.length / 8;
}
}
}
/******************************************************************************/
// MicroPython bindings for hw_spi
STATIC void machine_hw_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_hw_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "SPI(id=%u, baudrate=%u, polarity=%u, phase=%u, bits=%u, firstbit=%u, sck=%d, mosi=%d, miso=%d)",
self->host, self->baudrate, self->polarity,
self->phase, self->bits, self->firstbit,
self->sck, self->mosi, self->miso);
}
STATIC void machine_hw_spi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
machine_hw_spi_obj_t *self = (machine_hw_spi_obj_t *) self_in;
enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args),
allowed_args, args);
int8_t sck, mosi, miso;
if (args[ARG_sck].u_obj == MP_OBJ_NULL) {
sck = -2;
} else if (args[ARG_sck].u_obj == mp_const_none) {
sck = -1;
} else {
sck = machine_pin_get_id(args[ARG_sck].u_obj);
}
if (args[ARG_miso].u_obj == MP_OBJ_NULL) {
miso = -2;
} else if (args[ARG_miso].u_obj == mp_const_none) {
miso = -1;
} else {
miso = machine_pin_get_id(args[ARG_miso].u_obj);
}
if (args[ARG_mosi].u_obj == MP_OBJ_NULL) {
mosi = -2;
} else if (args[ARG_mosi].u_obj == mp_const_none) {
mosi = -1;
} else {
mosi = machine_pin_get_id(args[ARG_mosi].u_obj);
}
machine_hw_spi_init_internal(self, args[ARG_id].u_int, args[ARG_baudrate].u_int,
args[ARG_polarity].u_int, args[ARG_phase].u_int, args[ARG_bits].u_int,
args[ARG_firstbit].u_int, sck, mosi, miso);
}
mp_obj_t machine_hw_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit, ARG_sck, ARG_mosi, ARG_miso };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 500000} },
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = MICROPY_PY_MACHINE_SPI_MSB} },
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
machine_hw_spi_obj_t *self = m_new_obj(machine_hw_spi_obj_t);
self->base.type = &machine_hw_spi_type;
machine_hw_spi_init_internal(
self,
args[ARG_id].u_int,
args[ARG_baudrate].u_int,
args[ARG_polarity].u_int,
args[ARG_phase].u_int,
args[ARG_bits].u_int,
args[ARG_firstbit].u_int,
args[ARG_sck].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_sck].u_obj),
args[ARG_mosi].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_mosi].u_obj),
args[ARG_miso].u_obj == MP_OBJ_NULL ? -1 : machine_pin_get_id(args[ARG_miso].u_obj));
return MP_OBJ_FROM_PTR(self);
}
STATIC const mp_machine_spi_p_t machine_hw_spi_p = {
.init = machine_hw_spi_init,
.deinit = machine_hw_spi_deinit,
.transfer = machine_hw_spi_transfer,
};
const mp_obj_type_t machine_hw_spi_type = {
{ &mp_type_type },
.name = MP_QSTR_SPI,
.print = machine_hw_spi_print,
.make_new = machine_hw_spi_make_new,
.protocol = &machine_hw_spi_p,
.locals_dict = (mp_obj_dict_t *) &mp_machine_spi_locals_dict,
};

View File

@ -1,414 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* 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.
*/
#include <stdio.h>
#include <string.h>
#include "driver/gpio.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "modmachine.h"
#include "extmod/virtpin.h"
#include "machine_rtc.h"
#include "modesp32.h"
typedef struct _machine_pin_obj_t {
mp_obj_base_t base;
gpio_num_t id;
} machine_pin_obj_t;
typedef struct _machine_pin_irq_obj_t {
mp_obj_base_t base;
gpio_num_t id;
} machine_pin_irq_obj_t;
STATIC const machine_pin_obj_t machine_pin_obj[] = {
{{&machine_pin_type}, GPIO_NUM_0},
{{&machine_pin_type}, GPIO_NUM_1},
{{&machine_pin_type}, GPIO_NUM_2},
{{&machine_pin_type}, GPIO_NUM_3},
{{&machine_pin_type}, GPIO_NUM_4},
{{&machine_pin_type}, GPIO_NUM_5},
{{&machine_pin_type}, GPIO_NUM_6},
{{&machine_pin_type}, GPIO_NUM_7},
{{&machine_pin_type}, GPIO_NUM_8},
{{&machine_pin_type}, GPIO_NUM_9},
{{&machine_pin_type}, GPIO_NUM_10},
{{&machine_pin_type}, GPIO_NUM_11},
{{&machine_pin_type}, GPIO_NUM_12},
{{&machine_pin_type}, GPIO_NUM_13},
{{&machine_pin_type}, GPIO_NUM_14},
{{&machine_pin_type}, GPIO_NUM_15},
{{&machine_pin_type}, GPIO_NUM_16},
{{&machine_pin_type}, GPIO_NUM_17},
{{&machine_pin_type}, GPIO_NUM_18},
{{&machine_pin_type}, GPIO_NUM_19},
{{NULL}, -1},
{{&machine_pin_type}, GPIO_NUM_21},
{{&machine_pin_type}, GPIO_NUM_22},
{{&machine_pin_type}, GPIO_NUM_23},
{{NULL}, -1},
{{&machine_pin_type}, GPIO_NUM_25},
{{&machine_pin_type}, GPIO_NUM_26},
{{&machine_pin_type}, GPIO_NUM_27},
{{NULL}, -1},
{{NULL}, -1},
{{NULL}, -1},
{{NULL}, -1},
{{&machine_pin_type}, GPIO_NUM_32},
{{&machine_pin_type}, GPIO_NUM_33},
{{&machine_pin_type}, GPIO_NUM_34},
{{&machine_pin_type}, GPIO_NUM_35},
{{&machine_pin_type}, GPIO_NUM_36},
{{&machine_pin_type}, GPIO_NUM_37},
{{&machine_pin_type}, GPIO_NUM_38},
{{&machine_pin_type}, GPIO_NUM_39},
};
// forward declaration
STATIC const machine_pin_irq_obj_t machine_pin_irq_object[];
void machine_pins_init(void) {
static bool did_install = false;
if (!did_install) {
gpio_install_isr_service(0);
did_install = true;
}
memset(&MP_STATE_PORT(machine_pin_irq_handler[0]), 0, sizeof(MP_STATE_PORT(machine_pin_irq_handler)));
}
void machine_pins_deinit(void) {
for (int i = 0; i < MP_ARRAY_SIZE(machine_pin_obj); ++i) {
if (machine_pin_obj[i].id != (gpio_num_t)-1) {
gpio_isr_handler_remove(machine_pin_obj[i].id);
}
}
}
STATIC void IRAM_ATTR machine_pin_isr_handler(void *arg) {
machine_pin_obj_t *self = arg;
mp_obj_t handler = MP_STATE_PORT(machine_pin_irq_handler)[self->id];
mp_sched_schedule(handler, MP_OBJ_FROM_PTR(self));
}
gpio_num_t machine_pin_get_id(mp_obj_t pin_in) {
if (mp_obj_get_type(pin_in) != &machine_pin_type) {
mp_raise_ValueError("expecting a pin");
}
machine_pin_obj_t *self = pin_in;
return self->id;
}
STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_pin_obj_t *self = self_in;
mp_printf(print, "Pin(%u)", self->id);
}
// pin.init(mode, pull=None, *, value)
STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_mode, ARG_pull, ARG_value };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_mode, MP_ARG_OBJ, {.u_obj = mp_const_none}},
{ MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}},
{ MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
};
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// configure the pin for gpio
gpio_pad_select_gpio(self->id);
// set initial value (do this before configuring mode/pull)
if (args[ARG_value].u_obj != MP_OBJ_NULL) {
gpio_set_level(self->id, mp_obj_is_true(args[ARG_value].u_obj));
}
// configure mode
if (args[ARG_mode].u_obj != mp_const_none) {
mp_int_t pin_io_mode = mp_obj_get_int(args[ARG_mode].u_obj);
if (self->id >= 34 && (pin_io_mode & GPIO_MODE_DEF_OUTPUT)) {
mp_raise_ValueError("pin can only be input");
} else {
gpio_set_direction(self->id, pin_io_mode);
}
}
// configure pull
if (args[ARG_pull].u_obj != mp_const_none) {
gpio_set_pull_mode(self->id, mp_obj_get_int(args[ARG_pull].u_obj));
}
return mp_const_none;
}
// constructor(id, ...)
mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// get the wanted pin object
int wanted_pin = mp_obj_get_int(args[0]);
const machine_pin_obj_t *self = NULL;
if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj)) {
self = (machine_pin_obj_t*)&machine_pin_obj[wanted_pin];
}
if (self == NULL || self->base.type == NULL) {
mp_raise_ValueError("invalid pin");
}
if (n_args > 1 || n_kw > 0) {
// pin mode given, so configure this GPIO
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
machine_pin_obj_init_helper(self, n_args - 1, args + 1, &kw_args);
}
return MP_OBJ_FROM_PTR(self);
}
// fast method for getting/setting pin value
STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
machine_pin_obj_t *self = self_in;
if (n_args == 0) {
// get pin
return MP_OBJ_NEW_SMALL_INT(gpio_get_level(self->id));
} else {
// set pin
gpio_set_level(self->id, mp_obj_is_true(args[0]));
return mp_const_none;
}
}
// pin.init(mode, pull)
STATIC mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
}
MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init);
// pin.value([value])
STATIC mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) {
return machine_pin_call(args[0], n_args - 1, 0, args + 1);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value);
// pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING)
STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_handler, ARG_trigger, ARG_wake };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_handler, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_trigger, MP_ARG_INT, {.u_int = GPIO_PIN_INTR_POSEDGE | GPIO_PIN_INTR_NEGEDGE} },
{ MP_QSTR_wake, MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
machine_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
if (n_args > 1 || kw_args->used != 0) {
// configure irq
mp_obj_t handler = args[ARG_handler].u_obj;
uint32_t trigger = args[ARG_trigger].u_int;
mp_obj_t wake_obj = args[ARG_wake].u_obj;
if ((trigger == GPIO_PIN_INTR_LOLEVEL || trigger == GPIO_PIN_INTR_HILEVEL) && wake_obj != mp_const_none) {
mp_int_t wake;
if (mp_obj_get_int_maybe(wake_obj, &wake)) {
if (wake < 2 || wake > 7) {
mp_raise_ValueError("bad wake value");
}
} else {
mp_raise_ValueError("bad wake value");
}
if (machine_rtc_config.wake_on_touch) { // not compatible
mp_raise_ValueError("no resources");
}
if (!RTC_IS_VALID_EXT_PIN(self->id)) {
mp_raise_ValueError("invalid pin for wake");
}
if (machine_rtc_config.ext0_pin == -1) {
machine_rtc_config.ext0_pin = self->id;
} else if (machine_rtc_config.ext0_pin != self->id) {
mp_raise_ValueError("no resources");
}
machine_rtc_config.ext0_level = trigger == GPIO_PIN_INTR_LOLEVEL ? 0 : 1;
machine_rtc_config.ext0_wake_types = wake;
} else {
if (machine_rtc_config.ext0_pin == self->id) {
machine_rtc_config.ext0_pin = -1;
}
if (handler == mp_const_none) {
handler = MP_OBJ_NULL;
trigger = 0;
}
gpio_isr_handler_remove(self->id);
MP_STATE_PORT(machine_pin_irq_handler)[self->id] = handler;
gpio_set_intr_type(self->id, trigger);
gpio_isr_handler_add(self->id, machine_pin_isr_handler, (void*)self);
}
}
// return the irq object
return MP_OBJ_FROM_PTR(&machine_pin_irq_object[self->id]);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_irq_obj, 1, machine_pin_irq);
STATIC const mp_rom_map_elem_t machine_pin_locals_dict_table[] = {
// instance methods
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_pin_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_pin_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&machine_pin_irq_obj) },
// class constants
{ MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_INPUT) },
{ MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT) },
{ MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_INPUT_OUTPUT_OD) },
{ MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULLUP_ONLY) },
{ MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULLDOWN_ONLY) },
{ MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_PIN_INTR_POSEDGE) },
{ MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_PIN_INTR_NEGEDGE) },
{ MP_ROM_QSTR(MP_QSTR_WAKE_LOW), MP_ROM_INT(GPIO_PIN_INTR_LOLEVEL) },
{ MP_ROM_QSTR(MP_QSTR_WAKE_HIGH), MP_ROM_INT(GPIO_PIN_INTR_HILEVEL) },
};
STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
(void)errcode;
machine_pin_obj_t *self = self_in;
switch (request) {
case MP_PIN_READ: {
return gpio_get_level(self->id);
}
case MP_PIN_WRITE: {
gpio_set_level(self->id, arg);
return 0;
}
}
return -1;
}
STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table);
STATIC const mp_pin_p_t pin_pin_p = {
.ioctl = pin_ioctl,
};
const mp_obj_type_t machine_pin_type = {
{ &mp_type_type },
.name = MP_QSTR_Pin,
.print = machine_pin_print,
.make_new = mp_pin_make_new,
.call = machine_pin_call,
.protocol = &pin_pin_p,
.locals_dict = (mp_obj_t)&machine_pin_locals_dict,
};
/******************************************************************************/
// Pin IRQ object
STATIC const mp_obj_type_t machine_pin_irq_type;
STATIC const machine_pin_irq_obj_t machine_pin_irq_object[] = {
{{&machine_pin_irq_type}, GPIO_NUM_0},
{{&machine_pin_irq_type}, GPIO_NUM_1},
{{&machine_pin_irq_type}, GPIO_NUM_2},
{{&machine_pin_irq_type}, GPIO_NUM_3},
{{&machine_pin_irq_type}, GPIO_NUM_4},
{{&machine_pin_irq_type}, GPIO_NUM_5},
{{&machine_pin_irq_type}, GPIO_NUM_6},
{{&machine_pin_irq_type}, GPIO_NUM_7},
{{&machine_pin_irq_type}, GPIO_NUM_8},
{{&machine_pin_irq_type}, GPIO_NUM_9},
{{&machine_pin_irq_type}, GPIO_NUM_10},
{{&machine_pin_irq_type}, GPIO_NUM_11},
{{&machine_pin_irq_type}, GPIO_NUM_12},
{{&machine_pin_irq_type}, GPIO_NUM_13},
{{&machine_pin_irq_type}, GPIO_NUM_14},
{{&machine_pin_irq_type}, GPIO_NUM_15},
{{&machine_pin_irq_type}, GPIO_NUM_16},
{{&machine_pin_irq_type}, GPIO_NUM_17},
{{&machine_pin_irq_type}, GPIO_NUM_18},
{{&machine_pin_irq_type}, GPIO_NUM_19},
{{NULL}, -1},
{{&machine_pin_irq_type}, GPIO_NUM_21},
{{&machine_pin_irq_type}, GPIO_NUM_22},
{{&machine_pin_irq_type}, GPIO_NUM_23},
{{NULL}, -1},
{{&machine_pin_irq_type}, GPIO_NUM_25},
{{&machine_pin_irq_type}, GPIO_NUM_26},
{{&machine_pin_irq_type}, GPIO_NUM_27},
{{NULL}, -1},
{{NULL}, -1},
{{NULL}, -1},
{{NULL}, -1},
{{&machine_pin_irq_type}, GPIO_NUM_32},
{{&machine_pin_irq_type}, GPIO_NUM_33},
{{&machine_pin_irq_type}, GPIO_NUM_34},
{{&machine_pin_irq_type}, GPIO_NUM_35},
{{&machine_pin_irq_type}, GPIO_NUM_36},
{{&machine_pin_irq_type}, GPIO_NUM_37},
{{&machine_pin_irq_type}, GPIO_NUM_38},
{{&machine_pin_irq_type}, GPIO_NUM_39},
};
STATIC mp_obj_t machine_pin_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
machine_pin_irq_obj_t *self = self_in;
mp_arg_check_num(n_args, n_kw, 0, 0, false);
machine_pin_isr_handler((void*)&machine_pin_obj[self->id]);
return mp_const_none;
}
STATIC mp_obj_t machine_pin_irq_trigger(size_t n_args, const mp_obj_t *args) {
machine_pin_irq_obj_t *self = args[0];
uint32_t orig_trig = GPIO.pin[self->id].int_type;
if (n_args == 2) {
// set trigger
gpio_set_intr_type(self->id, mp_obj_get_int(args[1]));
}
// return original trigger value
return MP_OBJ_NEW_SMALL_INT(orig_trig);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_irq_trigger_obj, 1, 2, machine_pin_irq_trigger);
STATIC const mp_rom_map_elem_t machine_pin_irq_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_trigger), MP_ROM_PTR(&machine_pin_irq_trigger_obj) },
};
STATIC MP_DEFINE_CONST_DICT(machine_pin_irq_locals_dict, machine_pin_irq_locals_dict_table);
STATIC const mp_obj_type_t machine_pin_irq_type = {
{ &mp_type_type },
.name = MP_QSTR_IRQ,
.call = machine_pin_irq_call,
.locals_dict = (mp_obj_dict_t*)&machine_pin_irq_locals_dict,
};

View File

@ -1,277 +0,0 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* 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.
*/
#include <stdio.h>
#include "driver/ledc.h"
#include "esp_err.h"
#include "py/nlr.h"
#include "py/runtime.h"
#include "modmachine.h"
#include "mphalport.h"
// Forward dec'l
extern const mp_obj_type_t machine_pwm_type;
typedef struct _esp32_pwm_obj_t {
mp_obj_base_t base;
gpio_num_t pin;
uint8_t active;
uint8_t channel;
} esp32_pwm_obj_t;
// Which channel has which GPIO pin assigned?
// (-1 if not assigned)
STATIC int chan_gpio[LEDC_CHANNEL_MAX];
// Params for PW operation
// 5khz
#define PWFREQ (5000)
// High speed mode
#define PWMODE (LEDC_HIGH_SPEED_MODE)
// 10-bit resolution (compatible with esp8266 PWM)
#define PWRES (LEDC_TIMER_10_BIT)
// Timer 1
#define PWTIMER (LEDC_TIMER_1)
// Config of timer upon which we run all PWM'ed GPIO pins
STATIC bool pwm_inited = false;
STATIC ledc_timer_config_t timer_cfg = {
.bit_num = PWRES,
.freq_hz = PWFREQ,
.speed_mode = PWMODE,
.timer_num = PWTIMER
};
STATIC void pwm_init(void) {
// Initial condition: no channels assigned
for (int x = 0; x < LEDC_CHANNEL_MAX; ++x) {
chan_gpio[x] = -1;
}
// Init with default timer params
ledc_timer_config(&timer_cfg);
}
STATIC int set_freq(int newval) {
int oval = timer_cfg.freq_hz;
timer_cfg.freq_hz = newval;
if (ledc_timer_config(&timer_cfg) != ESP_OK) {
timer_cfg.freq_hz = oval;
return 0;
}
return 1;
}
/******************************************************************************/
// MicroPython bindings for PWM
STATIC void esp32_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "PWM(%u", self->pin);
if (self->active) {
mp_printf(print, ", freq=%u, duty=%u", timer_cfg.freq_hz,
ledc_get_duty(PWMODE, self->channel));
}
mp_printf(print, ")");
}
STATIC void esp32_pwm_init_helper(esp32_pwm_obj_t *self,
size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_freq, ARG_duty };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_freq, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_duty, MP_ARG_INT, {.u_int = -1} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args,
MP_ARRAY_SIZE(allowed_args), allowed_args, args);
int channel;
int avail = -1;
// Find a free PWM channel, also spot if our pin is
// already mentioned.
for (channel = 0; channel < LEDC_CHANNEL_MAX; ++channel) {
if (chan_gpio[channel] == self->pin) {
break;
}
if ((avail == -1) && (chan_gpio[channel] == -1)) {
avail = channel;
}
}
if (channel >= LEDC_CHANNEL_MAX) {
if (avail == -1) {
mp_raise_ValueError("out of PWM channels");
}
channel = avail;
}
self->channel = channel;
// New PWM assignment
self->active = 1;
if (chan_gpio[channel] == -1) {
ledc_channel_config_t cfg = {
.channel = channel,
.duty = (1 << PWRES) / 2,
.gpio_num = self->pin,
.intr_type = LEDC_INTR_DISABLE,
.speed_mode = PWMODE,
.timer_sel = PWTIMER,
};
if (ledc_channel_config(&cfg) != ESP_OK) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"PWM not supported on pin %d", self->pin));
}
chan_gpio[channel] = self->pin;
}
// Maybe change PWM timer
int tval = args[ARG_freq].u_int;
if (tval != -1) {
if (tval != timer_cfg.freq_hz) {
if (!set_freq(tval)) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"Bad frequency %d", tval));
}
}
}
// Set duty cycle?
int dval = args[ARG_duty].u_int;
if (dval != -1) {
dval &= ((1 << PWRES)-1);
ledc_set_duty(PWMODE, channel, dval);
ledc_update_duty(PWMODE, channel);
}
}
STATIC mp_obj_t esp32_pwm_make_new(const mp_obj_type_t *type,
size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
gpio_num_t pin_id = machine_pin_get_id(args[0]);
// create PWM object from the given pin
esp32_pwm_obj_t *self = m_new_obj(esp32_pwm_obj_t);
self->base.type = &machine_pwm_type;
self->pin = pin_id;
self->active = 0;
self->channel = -1;
// start the PWM subsystem if it's not already running
if (!pwm_inited) {
pwm_init();
pwm_inited = true;
}
// start the PWM running for this channel
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
esp32_pwm_init_helper(self, n_args - 1, args + 1, &kw_args);
return MP_OBJ_FROM_PTR(self);
}
STATIC mp_obj_t esp32_pwm_init(size_t n_args,
const mp_obj_t *args, mp_map_t *kw_args) {
esp32_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(esp32_pwm_init_obj, 1, esp32_pwm_init);
STATIC mp_obj_t esp32_pwm_deinit(mp_obj_t self_in) {
esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
int chan = self->channel;
// Valid channel?
if ((chan >= 0) && (chan < LEDC_CHANNEL_MAX)) {
// Mark it unused, and tell the hardware to stop routing
chan_gpio[chan] = -1;
ledc_stop(PWMODE, chan, 0);
self->active = 0;
self->channel = -1;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_pwm_deinit_obj, esp32_pwm_deinit);
STATIC mp_obj_t esp32_pwm_freq(size_t n_args, const mp_obj_t *args) {
if (n_args == 1) {
// get
return MP_OBJ_NEW_SMALL_INT(timer_cfg.freq_hz);
}
// set
int tval = mp_obj_get_int(args[1]);
if (!set_freq(tval)) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"Bad frequency %d", tval));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_pwm_freq_obj, 1, 2, esp32_pwm_freq);
STATIC mp_obj_t esp32_pwm_duty(size_t n_args, const mp_obj_t *args) {
esp32_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
int duty;
if (n_args == 1) {
// get
duty = ledc_get_duty(PWMODE, self->channel);
return MP_OBJ_NEW_SMALL_INT(duty);
}
// set
duty = mp_obj_get_int(args[1]);
duty &= ((1 << PWRES)-1);
ledc_set_duty(PWMODE, self->channel, duty);
ledc_update_duty(PWMODE, self->channel);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_pwm_duty_obj,
1, 2, esp32_pwm_duty);
STATIC const mp_rom_map_elem_t esp32_pwm_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&esp32_pwm_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&esp32_pwm_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&esp32_pwm_freq_obj) },
{ MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&esp32_pwm_duty_obj) },
};
STATIC MP_DEFINE_CONST_DICT(esp32_pwm_locals_dict,
esp32_pwm_locals_dict_table);
const mp_obj_type_t machine_pwm_type = {
{ &mp_type_type },
.name = MP_QSTR_PWM,
.print = esp32_pwm_print,
.make_new = esp32_pwm_make_new,
.locals_dict = (mp_obj_dict_t*)&esp32_pwm_locals_dict,
};

View File

@ -1,162 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 "Eric Poulsen" <eric@zyxod.com>
* Copyright (c) 2017 "Tom Manning" <tom@manningetal.com>
*
* 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.
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "driver/gpio.h"
#include "py/nlr.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "timeutils.h"
#include "modmachine.h"
#include "machine_rtc.h"
typedef struct _machine_rtc_obj_t {
mp_obj_base_t base;
} machine_rtc_obj_t;
#define MEM_MAGIC 0x75507921
/* There is 8K of rtc_slow_memory, but some is used by the system software
If the USER_MAXLEN is set to high, the following compile error will happen:
region `rtc_slow_seg' overflowed by N bytes
The current system software allows almost 4096 to be used.
To avoid running into issues if the system software uses more, 2048 was picked as a max length
*/
#define MEM_USER_MAXLEN 2048
RTC_DATA_ATTR uint32_t rtc_user_mem_magic;
RTC_DATA_ATTR uint32_t rtc_user_mem_len;
RTC_DATA_ATTR uint8_t rtc_user_mem_data[MEM_USER_MAXLEN];
// singleton RTC object
STATIC const machine_rtc_obj_t machine_rtc_obj = {{&machine_rtc_type}};
machine_rtc_config_t machine_rtc_config = {
.ext1_pins = 0,
.ext0_pin = -1
};
STATIC mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 0, 0, false);
// return constant object
return (mp_obj_t)&machine_rtc_obj;
}
STATIC mp_obj_t machine_rtc_datetime_helper(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 1) {
// Get time
struct timeval tv;
gettimeofday(&tv, NULL);
timeutils_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(tv.tv_sec, &tm);
mp_obj_t tuple[8] = {
mp_obj_new_int(tm.tm_year),
mp_obj_new_int(tm.tm_mon),
mp_obj_new_int(tm.tm_mday),
mp_obj_new_int(tm.tm_wday),
mp_obj_new_int(tm.tm_hour),
mp_obj_new_int(tm.tm_min),
mp_obj_new_int(tm.tm_sec),
mp_obj_new_int(tv.tv_usec)
};
return mp_obj_new_tuple(8, tuple);
} else {
// Set time
mp_obj_t *items;
mp_obj_get_array_fixed_n(args[1], 8, &items);
struct timeval tv = {0};
tv.tv_sec = timeutils_seconds_since_2000(mp_obj_get_int(items[0]), mp_obj_get_int(items[1]), mp_obj_get_int(items[2]), mp_obj_get_int(items[4]), mp_obj_get_int(items[5]), mp_obj_get_int(items[6]));
settimeofday(&tv, NULL);
return mp_const_none;
}
}
STATIC mp_obj_t machine_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
return machine_rtc_datetime_helper(n_args, args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_datetime_obj, 1, 2, machine_rtc_datetime);
STATIC mp_obj_t machine_rtc_init(mp_obj_t self_in, mp_obj_t date) {
mp_obj_t args[2] = {self_in, date};
machine_rtc_datetime_helper(2, args);
if (rtc_user_mem_magic != MEM_MAGIC) {
rtc_user_mem_magic = MEM_MAGIC;
rtc_user_mem_len = 0;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_rtc_init_obj, machine_rtc_init);
STATIC mp_obj_t machine_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 1) {
// read RTC memory
uint32_t len = rtc_user_mem_len;
uint8_t rtcram[MEM_USER_MAXLEN];
memcpy( (char *) rtcram, (char *) rtc_user_mem_data, len);
return mp_obj_new_bytes(rtcram, len);
} else {
// write RTC memory
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
if (bufinfo.len > MEM_USER_MAXLEN) {
mp_raise_ValueError("buffer too long");
}
memcpy( (char *) rtc_user_mem_data, (char *) bufinfo.buf, bufinfo.len);
rtc_user_mem_len = bufinfo.len;
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_rtc_memory_obj, 1, 2, machine_rtc_memory);
STATIC const mp_rom_map_elem_t machine_rtc_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_rtc_datetime_obj) },
{ MP_ROM_QSTR(MP_QSTR_datetime), MP_ROM_PTR(&machine_rtc_datetime_obj) },
{ MP_ROM_QSTR(MP_QSTR_memory), MP_ROM_PTR(&machine_rtc_memory_obj) },
};
STATIC MP_DEFINE_CONST_DICT(machine_rtc_locals_dict, machine_rtc_locals_dict_table);
const mp_obj_type_t machine_rtc_type = {
{ &mp_type_type },
.name = MP_QSTR_RTC,
.make_new = machine_rtc_make_new,
.locals_dict = (mp_obj_t)&machine_rtc_locals_dict,
};

View File

@ -1,44 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 "Eric Poulsen" <eric@zyxod.com>
* Copyright (c) 2017 "Tom Manning" <tom@manningetal.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESP32_MACHINE_RTC_H
#define MICROPY_INCLUDED_ESP32_MACHINE_RTC_H
#include "modmachine.h"
typedef struct {
uint64_t ext1_pins; // set bit == pin#
int8_t ext0_pin; // just the pin#, -1 == None
bool wake_on_touch : 1;
bool ext0_level : 1;
wake_type_t ext0_wake_types;
bool ext1_level : 1;
} machine_rtc_config_t;
extern machine_rtc_config_t machine_rtc_config;
#endif

View File

@ -1,192 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2015 Damien P. George
* Copyright (c) 2016 Paul Sokolovsky
*
* 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.
*/
#include <stdint.h>
#include <stdio.h>
#include "driver/timer.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "modmachine.h"
#define TIMER_INTR_SEL TIMER_INTR_LEVEL
#define TIMER_DIVIDER 40000
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER)
#define TIMER_FLAGS 0
typedef struct _machine_timer_obj_t {
mp_obj_base_t base;
mp_uint_t group;
mp_uint_t index;
mp_uint_t repeat;
mp_uint_t period;
mp_obj_t callback;
intr_handle_t handle;
} machine_timer_obj_t;
const mp_obj_type_t machine_timer_type;
STATIC esp_err_t check_esp_err(esp_err_t code) {
if (code) {
mp_raise_OSError(code);
}
return code;
}
STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_timer_obj_t *self = self_in;
timer_config_t config;
mp_printf(print, "Timer(%p; ", self);
timer_get_config(self->group, self->index, &config);
mp_printf(print, "alarm_en=%d, ", config.alarm_en);
mp_printf(print, "auto_reload=%d, ", config.auto_reload);
mp_printf(print, "counter_en=%d)", config.counter_en);
}
STATIC mp_obj_t machine_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, 1, false);
machine_timer_obj_t *self = m_new_obj(machine_timer_obj_t);
self->base.type = &machine_timer_type;
self->group = (mp_obj_get_int(args[0]) >> 1) & 1;
self->index = mp_obj_get_int(args[0]) & 1;
return self;
}
STATIC void machine_timer_disable(machine_timer_obj_t *self) {
if (self->handle) {
timer_pause(self->group, self->index);
esp_intr_free(self->handle);
self->handle = NULL;
}
}
STATIC void machine_timer_isr(void *self_in) {
machine_timer_obj_t *self = self_in;
timg_dev_t *device = self->group ? &(TIMERG1) : &(TIMERG0);
device->hw_timer[self->index].update = 1;
if (self->index) {
device->int_clr_timers.t1 = 1;
} else {
device->int_clr_timers.t0 = 1;
}
device->hw_timer[self->index].config.alarm_en = self->repeat;
mp_sched_schedule(self->callback, self);
}
STATIC void machine_timer_enable(machine_timer_obj_t *self) {
timer_config_t config;
config.alarm_en = TIMER_ALARM_EN;
config.auto_reload = self->repeat;
config.counter_dir = TIMER_COUNT_UP;
config.divider = TIMER_DIVIDER;
config.intr_type = TIMER_INTR_LEVEL;
config.counter_en = TIMER_PAUSE;
check_esp_err(timer_init(self->group, self->index, &config));
check_esp_err(timer_set_counter_value(self->group, self->index, 0x00000000));
check_esp_err(timer_set_alarm_value(self->group, self->index, self->period));
check_esp_err(timer_enable_intr(self->group, self->index));
check_esp_err(timer_isr_register(self->group, self->index, machine_timer_isr, (void*)self, TIMER_FLAGS, &self->handle));
check_esp_err(timer_start(self->group, self->index));
}
STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} },
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
machine_timer_disable(self);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// Timer uses an 80MHz base clock, which is divided by the divider/scalar, we then convert to ms.
self->period = (args[0].u_int * TIMER_BASE_CLK) / (1000 * TIMER_DIVIDER);
self->repeat = args[1].u_int;
self->callback = args[2].u_obj;
self->handle = NULL;
machine_timer_enable(self);
return mp_const_none;
}
STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) {
machine_timer_disable(self_in);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit);
STATIC mp_obj_t machine_timer_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
return machine_timer_init_helper(args[0], n_args - 1, args + 1, kw_args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init);
STATIC mp_obj_t machine_timer_value(mp_obj_t self_in) {
machine_timer_obj_t *self = self_in;
double result;
timer_get_counter_time_sec(self->group, self->index, &result);
return MP_OBJ_NEW_SMALL_INT((mp_uint_t)(result * 1000)); // value in ms
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_value_obj, machine_timer_value);
STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_timer_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&machine_timer_value_obj) },
{ MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(false) },
{ MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(true) },
};
STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);
const mp_obj_type_t machine_timer_type = {
{ &mp_type_type },
.name = MP_QSTR_Timer,
.print = machine_timer_print,
.make_new = machine_timer_make_new,
.locals_dict = (mp_obj_t)&machine_timer_locals_dict,
};

View File

@ -1,110 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 Nick Moore
*
* 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.
*/
#include <stdio.h>
#include "esp_log.h"
#include "driver/gpio.h"
#include "driver/touch_pad.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "modmachine.h"
typedef struct _mtp_obj_t {
mp_obj_base_t base;
gpio_num_t gpio_id;
touch_pad_t touchpad_id;
} mtp_obj_t;
STATIC const mtp_obj_t touchpad_obj[] = {
{{&machine_touchpad_type}, GPIO_NUM_4, TOUCH_PAD_NUM0},
{{&machine_touchpad_type}, GPIO_NUM_0, TOUCH_PAD_NUM1},
{{&machine_touchpad_type}, GPIO_NUM_2, TOUCH_PAD_NUM2},
{{&machine_touchpad_type}, GPIO_NUM_15, TOUCH_PAD_NUM3},
{{&machine_touchpad_type}, GPIO_NUM_13, TOUCH_PAD_NUM4},
{{&machine_touchpad_type}, GPIO_NUM_12, TOUCH_PAD_NUM5},
{{&machine_touchpad_type}, GPIO_NUM_14, TOUCH_PAD_NUM6},
{{&machine_touchpad_type}, GPIO_NUM_27, TOUCH_PAD_NUM7},
{{&machine_touchpad_type}, GPIO_NUM_33, TOUCH_PAD_NUM8},
{{&machine_touchpad_type}, GPIO_NUM_32, TOUCH_PAD_NUM9},
};
STATIC mp_obj_t mtp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, 1, true);
gpio_num_t pin_id = machine_pin_get_id(args[0]);
const mtp_obj_t *self = NULL;
for (int i = 0; i < MP_ARRAY_SIZE(touchpad_obj); i++) {
if (pin_id == touchpad_obj[i].gpio_id) { self = &touchpad_obj[i]; break; }
}
if (!self) mp_raise_ValueError("invalid pin for touchpad");
static int initialized = 0;
if (!initialized) {
touch_pad_init();
initialized = 1;
}
esp_err_t err = touch_pad_config(self->touchpad_id, 0);
if (err == ESP_OK) return MP_OBJ_FROM_PTR(self);
mp_raise_ValueError("Touch pad error");
}
STATIC mp_obj_t mtp_config(mp_obj_t self_in, mp_obj_t value_in) {
mtp_obj_t *self = self_in;
uint16_t value = mp_obj_get_int(value_in);
esp_err_t err = touch_pad_config(self->touchpad_id, value);
if (err == ESP_OK) return mp_const_none;
mp_raise_ValueError("Touch pad error");
}
MP_DEFINE_CONST_FUN_OBJ_2(mtp_config_obj, mtp_config);
STATIC mp_obj_t mtp_read(mp_obj_t self_in) {
mtp_obj_t *self = self_in;
uint16_t value;
esp_err_t err = touch_pad_read(self->touchpad_id, &value);
if (err == ESP_OK) return MP_OBJ_NEW_SMALL_INT(value);
mp_raise_ValueError("Touch pad error");
}
MP_DEFINE_CONST_FUN_OBJ_1(mtp_read_obj, mtp_read);
STATIC const mp_rom_map_elem_t mtp_locals_dict_table[] = {
// instance methods
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&mtp_config_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mtp_read_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mtp_locals_dict, mtp_locals_dict_table);
const mp_obj_type_t machine_touchpad_type = {
{ &mp_type_type },
.name = MP_QSTR_TouchPad,
.make_new = mtp_make_new,
.locals_dict = (mp_obj_t)&mtp_locals_dict,
};

View File

@ -1,357 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* 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.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "driver/uart.h"
#include "freertos/FreeRTOS.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mperrno.h"
#include "modmachine.h"
typedef struct _machine_uart_obj_t {
mp_obj_base_t base;
uart_port_t uart_num;
uint8_t bits;
uint8_t parity;
uint8_t stop;
int8_t tx;
int8_t rx;
int8_t rts;
int8_t cts;
uint16_t timeout; // timeout waiting for first char (in ms)
uint16_t timeout_char; // timeout waiting between chars (in ms)
} machine_uart_obj_t;
STATIC const char *_parity_name[] = {"None", "1", "0"};
/******************************************************************************/
// MicroPython bindings for UART
STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
uint32_t baudrate;
uart_get_baudrate(self->uart_num, &baudrate);
mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, tx=%d, rx=%d, rts=%d, cts=%d, timeout=%u, timeout_char=%u)",
self->uart_num, baudrate, self->bits, _parity_name[self->parity],
self->stop, self->tx, self->rx, self->rts, self->cts, self->timeout, self->timeout_char);
}
STATIC void machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, ARG_rts, ARG_cts, ARG_timeout, ARG_timeout_char };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_bits, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_stop, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_PIN_NO_CHANGE} },
{ MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_PIN_NO_CHANGE} },
{ MP_QSTR_rts, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_PIN_NO_CHANGE} },
{ MP_QSTR_cts, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UART_PIN_NO_CHANGE} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// wait for all data to be transmitted before changing settings
uart_wait_tx_done(self->uart_num, pdMS_TO_TICKS(1000));
// set baudrate
uint32_t baudrate = 115200;
if (args[ARG_baudrate].u_int > 0) {
uart_set_baudrate(self->uart_num, args[ARG_baudrate].u_int);
uart_get_baudrate(self->uart_num, &baudrate);
}
uart_set_pin(self->uart_num, args[ARG_tx].u_int, args[ARG_rx].u_int, args[ARG_rts].u_int, args[ARG_cts].u_int);
if (args[ARG_tx].u_int != UART_PIN_NO_CHANGE) {
self->tx = args[ARG_tx].u_int;
}
if (args[ARG_rx].u_int != UART_PIN_NO_CHANGE) {
self->rx = args[ARG_rx].u_int;
}
if (args[ARG_rts].u_int != UART_PIN_NO_CHANGE) {
self->rts = args[ARG_rts].u_int;
}
if (args[ARG_cts].u_int != UART_PIN_NO_CHANGE) {
self->cts = args[ARG_cts].u_int;
}
// set data bits
switch (args[ARG_bits].u_int) {
case 0:
break;
case 5:
uart_set_word_length(self->uart_num, UART_DATA_5_BITS);
self->bits = 5;
break;
case 6:
uart_set_word_length(self->uart_num, UART_DATA_6_BITS);
self->bits = 6;
break;
case 7:
uart_set_word_length(self->uart_num, UART_DATA_7_BITS);
self->bits = 7;
break;
case 8:
uart_set_word_length(self->uart_num, UART_DATA_8_BITS);
self->bits = 8;
break;
default:
mp_raise_ValueError("invalid data bits");
break;
}
// set parity
if (args[ARG_parity].u_obj != MP_OBJ_NULL) {
if (args[ARG_parity].u_obj == mp_const_none) {
uart_set_parity(self->uart_num, UART_PARITY_DISABLE);
self->parity = 0;
} else {
mp_int_t parity = mp_obj_get_int(args[ARG_parity].u_obj);
if (parity & 1) {
uart_set_parity(self->uart_num, UART_PARITY_ODD);
self->parity = 1;
} else {
uart_set_parity(self->uart_num, UART_PARITY_EVEN);
self->parity = 2;
}
}
}
// set stop bits
switch (args[ARG_stop].u_int) {
// FIXME: ESP32 also supports 1.5 stop bits
case 0:
break;
case 1:
uart_set_stop_bits(self->uart_num, UART_STOP_BITS_1);
self->stop = 1;
break;
case 2:
uart_set_stop_bits(self->uart_num, UART_STOP_BITS_2);
self->stop = 2;
break;
default:
mp_raise_ValueError("invalid stop bits");
break;
}
// set timeout
self->timeout = args[ARG_timeout].u_int;
// set timeout_char
// make sure it is at least as long as a whole character (13 bits to be safe)
self->timeout_char = args[ARG_timeout_char].u_int;
uint32_t min_timeout_char = 13000 / baudrate + 1;
if (self->timeout_char < min_timeout_char) {
self->timeout_char = min_timeout_char;
}
}
STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// get uart id
mp_int_t uart_num = mp_obj_get_int(args[0]);
if (uart_num < 0 || uart_num >= UART_NUM_MAX) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) does not exist", uart_num));
}
// Attempts to use UART0 from Python has resulted in all sorts of fun errors.
// FIXME: UART0 is disabled for now.
if (uart_num == UART_NUM_0) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) is disabled (dedicated to REPL)", uart_num));
}
// Defaults
uart_config_t uartcfg = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.rx_flow_ctrl_thresh = 0
};
// create instance
machine_uart_obj_t *self = m_new_obj(machine_uart_obj_t);
self->base.type = &machine_uart_type;
self->uart_num = uart_num;
self->bits = 8;
self->parity = 0;
self->stop = 1;
self->rts = UART_PIN_NO_CHANGE;
self->cts = UART_PIN_NO_CHANGE;
self->timeout = 0;
self->timeout_char = 0;
switch (uart_num) {
case UART_NUM_0:
self->rx = UART_PIN_NO_CHANGE; // GPIO 3
self->tx = UART_PIN_NO_CHANGE; // GPIO 1
break;
case UART_NUM_1:
self->rx = 9;
self->tx = 10;
break;
case UART_NUM_2:
self->rx = 16;
self->tx = 17;
break;
}
// Remove any existing configuration
uart_driver_delete(self->uart_num);
// init the peripheral
// Setup
uart_param_config(self->uart_num, &uartcfg);
// RX and TX buffers are currently hardcoded at 256 bytes each (IDF minimum).
uart_driver_install(uart_num, 256, 256, 0, NULL, 0);
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
machine_uart_init_helper(self, n_args - 1, args + 1, &kw_args);
// Make sure pins are connected.
uart_set_pin(self->uart_num, self->tx, self->rx, self->rts, self->cts);
return MP_OBJ_FROM_PTR(self);
}
STATIC mp_obj_t machine_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
machine_uart_init_helper(args[0], n_args - 1, args + 1, kw_args);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(machine_uart_init_obj, 1, machine_uart_init);
STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
size_t rxbufsize;
uart_get_buffered_data_len(self->uart_num, &rxbufsize);
return MP_OBJ_NEW_SMALL_INT(rxbufsize);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any);
STATIC const mp_rom_map_elem_t machine_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_uart_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_uart_any_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
};
STATIC MP_DEFINE_CONST_DICT(machine_uart_locals_dict, machine_uart_locals_dict_table);
STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
// make sure we want at least 1 char
if (size == 0) {
return 0;
}
TickType_t time_to_wait;
if (self->timeout == 0) {
time_to_wait = 0;
} else {
time_to_wait = pdMS_TO_TICKS(self->timeout);
}
int bytes_read = uart_read_bytes(self->uart_num, buf_in, size, time_to_wait);
if (bytes_read <= 0) {
*errcode = MP_EAGAIN;
return MP_STREAM_ERROR;
}
return bytes_read;
}
STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
int bytes_written = uart_write_bytes(self->uart_num, buf_in, size);
if (bytes_written < 0) {
*errcode = MP_EAGAIN;
return MP_STREAM_ERROR;
}
// return number of bytes written
return bytes_written;
}
STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
machine_uart_obj_t *self = self_in;
mp_uint_t ret;
if (request == MP_STREAM_POLL) {
mp_uint_t flags = arg;
ret = 0;
size_t rxbufsize;
uart_get_buffered_data_len(self->uart_num, &rxbufsize);
if ((flags & MP_STREAM_POLL_RD) && rxbufsize > 0) {
ret |= MP_STREAM_POLL_RD;
}
if ((flags & MP_STREAM_POLL_WR) && 1) { // FIXME: uart_tx_any_room(self->uart_num)
ret |= MP_STREAM_POLL_WR;
}
} else {
*errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
}
return ret;
}
STATIC const mp_stream_p_t uart_stream_p = {
.read = machine_uart_read,
.write = machine_uart_write,
.ioctl = machine_uart_ioctl,
.is_text = false,
};
const mp_obj_type_t machine_uart_type = {
{ &mp_type_type },
.name = MP_QSTR_UART,
.print = machine_uart_print,
.make_new = machine_uart_make_new,
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &uart_stream_p,
.locals_dict = (mp_obj_dict_t*)&machine_uart_locals_dict,
};

View File

@ -1,78 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
* Copyright (c) 2017 Eric Poulsen
*
* 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.
*/
#include <string.h>
#include "py/nlr.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "esp_task_wdt.h"
const mp_obj_type_t machine_wdt_type;
typedef struct _machine_wdt_obj_t {
mp_obj_base_t base;
} machine_wdt_obj_t;
STATIC machine_wdt_obj_t wdt_default = {{&machine_wdt_type}};
STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_int_t id = 0;
if (n_args > 0) {
id = mp_obj_get_int(args[0]);
}
switch (id) {
case 0:
esp_task_wdt_add(NULL);
return &wdt_default;
default:
mp_raise_ValueError(NULL);
}
}
STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) {
(void)self_in;
esp_task_wdt_reset();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed);
STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&machine_wdt_feed_obj) },
};
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
const mp_obj_type_t machine_wdt_type = {
{ &mp_type_type },
.name = MP_QSTR_WDT,
.make_new = machine_wdt_make_new,
.locals_dict = (mp_obj_t)&machine_wdt_locals_dict,
};

View File

@ -1,146 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* 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.
*/
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_task.h"
#include "soc/cpu.h"
#include "esp_log.h"
#include "py/stackctrl.h"
#include "py/nlr.h"
#include "py/compile.h"
#include "py/runtime.h"
#include "py/repl.h"
#include "py/gc.h"
#include "py/mphal.h"
#include "lib/mp-readline/readline.h"
#include "lib/utils/pyexec.h"
#include "uart.h"
#include "modmachine.h"
#include "modnetwork.h"
#include "mpthreadport.h"
// MicroPython runs as a task under FreeRTOS
#define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1)
#define MP_TASK_STACK_SIZE (16 * 1024)
#define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(StackType_t))
STATIC StaticTask_t mp_task_tcb;
STATIC StackType_t mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8)));
int vprintf_null(const char *format, va_list ap) {
// do nothing: this is used as a log target during raw repl mode
return 0;
}
void mp_task(void *pvParameter) {
volatile uint32_t sp = (uint32_t)get_sp();
#if MICROPY_PY_THREAD
mp_thread_init(&mp_task_stack[0], MP_TASK_STACK_LEN);
#endif
uart_init();
// Allocate the uPy heap using malloc and get the largest available region
size_t mp_task_heap_size = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT);
void *mp_task_heap = malloc(mp_task_heap_size);
soft_reset:
// initialise the stack pointer for the main thread
mp_stack_set_top((void *)sp);
mp_stack_set_limit(MP_TASK_STACK_SIZE - 1024);
gc_init(mp_task_heap, mp_task_heap + mp_task_heap_size);
mp_init();
mp_obj_list_init(mp_sys_path, 0);
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_));
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib));
mp_obj_list_init(mp_sys_argv, 0);
readline_init0();
// initialise peripherals
machine_pins_init();
// run boot-up scripts
pyexec_frozen_module("_boot.py");
pyexec_file("boot.py");
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
pyexec_file("main.py");
}
for (;;) {
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
vprintf_like_t vprintf_log = esp_log_set_vprintf(vprintf_null);
if (pyexec_raw_repl() != 0) {
break;
}
esp_log_set_vprintf(vprintf_log);
} else {
if (pyexec_friendly_repl() != 0) {
break;
}
}
}
#if MICROPY_PY_THREAD
mp_thread_deinit();
#endif
gc_sweep_all();
mp_hal_stdout_tx_str("PYB: soft reboot\r\n");
// deinitialise peripherals
machine_pins_deinit();
usocket_events_deinit();
mp_deinit();
fflush(stdout);
goto soft_reset;
}
void app_main(void) {
nvs_flash_init();
xTaskCreateStaticPinnedToCore(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY,
&mp_task_stack[0], &mp_task_tcb, 0);
}
void nlr_jump_fail(void *val) {
printf("NLR jump failed, val=%p\n", val);
esp_restart();
}
// modussl_mbedtls uses this function but it's not enabled in ESP IDF
void mbedtls_debug_set_threshold(int threshold) {
(void)threshold;
}

View File

@ -1,25 +0,0 @@
import sys
OFFSET_BOOTLOADER = 0x1000
OFFSET_PARTITIONS = 0x8000
OFFSET_APPLICATION = 0x10000
files_in = [
('bootloader', OFFSET_BOOTLOADER, sys.argv[1]),
('partitions', OFFSET_PARTITIONS, sys.argv[2]),
('application', OFFSET_APPLICATION, sys.argv[3]),
]
file_out = sys.argv[4]
cur_offset = OFFSET_BOOTLOADER
with open(file_out, 'wb') as fout:
for name, offset, file_in in files_in:
assert offset >= cur_offset
fout.write(b'\xff' * (offset - cur_offset))
cur_offset = offset
with open(file_in, 'rb') as fin:
data = fin.read()
fout.write(data)
cur_offset += len(data)
print('%-12s% 8d' % (name, len(data)))
print('%-12s% 8d' % ('total', cur_offset))

View File

@ -1,2 +0,0 @@
// this is needed for extmod/crypto-algorithms/sha256.c
#include <string.h>

View File

@ -1,157 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2015 Paul Sokolovsky
* Copyright (c) 2016 Damien P. George
*
* 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.
*/
#include <stdio.h>
#include "rom/gpio.h"
#include "esp_log.h"
#include "esp_spi_flash.h"
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "drivers/dht/dht.h"
#include "modesp.h"
STATIC mp_obj_t esp_osdebug(size_t n_args, const mp_obj_t *args) {
esp_log_level_t level = LOG_LOCAL_LEVEL;
if (n_args == 2) {
level = mp_obj_get_int(args[1]);
}
if (args[0] == mp_const_none) {
// Disable logging
esp_log_level_set("*", ESP_LOG_ERROR);
} else {
// Enable logging at the given level
// TODO args[0] should set the UART to which debug is sent
esp_log_level_set("*", level);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_osdebug_obj, 1, 2, esp_osdebug);
STATIC mp_obj_t esp_flash_read(mp_obj_t offset_in, mp_obj_t buf_in) {
mp_int_t offset = mp_obj_get_int(offset_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
esp_err_t res = spi_flash_read(offset, bufinfo.buf, bufinfo.len);
if (res != ESP_OK) {
mp_raise_OSError(MP_EIO);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_read_obj, esp_flash_read);
STATIC mp_obj_t esp_flash_write(mp_obj_t offset_in, mp_obj_t buf_in) {
mp_int_t offset = mp_obj_get_int(offset_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
esp_err_t res = spi_flash_write(offset, bufinfo.buf, bufinfo.len);
if (res != ESP_OK) {
mp_raise_OSError(MP_EIO);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_write_obj, esp_flash_write);
STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) {
mp_int_t sector = mp_obj_get_int(sector_in);
esp_err_t res = spi_flash_erase_sector(sector);
if (res != ESP_OK) {
mp_raise_OSError(MP_EIO);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_flash_erase_obj, esp_flash_erase);
STATIC mp_obj_t esp_flash_size(void) {
return mp_obj_new_int_from_uint(spi_flash_get_chip_size());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size);
STATIC mp_obj_t esp_flash_user_start(void) {
return MP_OBJ_NEW_SMALL_INT(0x200000);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_user_start_obj, esp_flash_user_start);
STATIC mp_obj_t esp_gpio_matrix_in(mp_obj_t pin, mp_obj_t sig, mp_obj_t inv) {
gpio_matrix_in(mp_obj_get_int(pin), mp_obj_get_int(sig), mp_obj_get_int(inv));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_gpio_matrix_in_obj, esp_gpio_matrix_in);
STATIC mp_obj_t esp_gpio_matrix_out(size_t n_args, const mp_obj_t *args) {
(void)n_args;
gpio_matrix_out(mp_obj_get_int(args[0]), mp_obj_get_int(args[1]), mp_obj_get_int(args[2]), mp_obj_get_int(args[3]));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_gpio_matrix_out_obj, 4, 4, esp_gpio_matrix_out);
STATIC mp_obj_t esp_neopixel_write_(mp_obj_t pin, mp_obj_t buf, mp_obj_t timing) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
esp_neopixel_write(mp_hal_get_pin_obj(pin),
(uint8_t*)bufinfo.buf, bufinfo.len, mp_obj_get_int(timing));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_neopixel_write_obj, esp_neopixel_write_);
STATIC const mp_rom_map_elem_t esp_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp) },
{ MP_ROM_QSTR(MP_QSTR_osdebug), MP_ROM_PTR(&esp_osdebug_obj) },
{ MP_ROM_QSTR(MP_QSTR_flash_read), MP_ROM_PTR(&esp_flash_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_flash_write), MP_ROM_PTR(&esp_flash_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_flash_erase), MP_ROM_PTR(&esp_flash_erase_obj) },
{ MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&esp_flash_size_obj) },
{ MP_ROM_QSTR(MP_QSTR_flash_user_start), MP_ROM_PTR(&esp_flash_user_start_obj) },
{ MP_ROM_QSTR(MP_QSTR_gpio_matrix_in), MP_ROM_PTR(&esp_gpio_matrix_in_obj) },
{ MP_ROM_QSTR(MP_QSTR_gpio_matrix_out), MP_ROM_PTR(&esp_gpio_matrix_out_obj) },
{ MP_ROM_QSTR(MP_QSTR_neopixel_write), MP_ROM_PTR(&esp_neopixel_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_dht_readinto), MP_ROM_PTR(&dht_readinto_obj) },
// Constants for second arg of osdebug()
{ MP_ROM_QSTR(MP_QSTR_LOG_NONE), MP_ROM_INT((mp_uint_t)ESP_LOG_NONE)},
{ MP_ROM_QSTR(MP_QSTR_LOG_ERROR), MP_ROM_INT((mp_uint_t)ESP_LOG_ERROR)},
{ MP_ROM_QSTR(MP_QSTR_LOG_WARNING), MP_ROM_INT((mp_uint_t)ESP_LOG_WARN)},
{ MP_ROM_QSTR(MP_QSTR_LOG_INFO), MP_ROM_INT((mp_uint_t)ESP_LOG_INFO)},
{ MP_ROM_QSTR(MP_QSTR_LOG_DEBUG), MP_ROM_INT((mp_uint_t)ESP_LOG_DEBUG)},
{ MP_ROM_QSTR(MP_QSTR_LOG_VERBOSE), MP_ROM_INT((mp_uint_t)ESP_LOG_VERBOSE)},
};
STATIC MP_DEFINE_CONST_DICT(esp_module_globals, esp_module_globals_table);
const mp_obj_module_t esp_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&esp_module_globals,
};

View File

@ -1 +0,0 @@
void esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t timing);

View File

@ -1,141 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 "Eric Poulsen" <eric@zyxod.com>
*
* 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.
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "driver/gpio.h"
#include "py/nlr.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "timeutils.h"
#include "modmachine.h"
#include "machine_rtc.h"
#include "modesp32.h"
STATIC mp_obj_t esp32_wake_on_touch(const mp_obj_t wake) {
if (machine_rtc_config.ext0_pin != -1) {
mp_raise_ValueError("no resources");
}
//nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "touchpad wakeup not available for this version of ESP-IDF"));
machine_rtc_config.wake_on_touch = mp_obj_is_true(wake);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_wake_on_touch_obj, esp32_wake_on_touch);
STATIC mp_obj_t esp32_wake_on_ext0(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
if (machine_rtc_config.wake_on_touch) {
mp_raise_ValueError("no resources");
}
enum {ARG_pin, ARG_level};
const mp_arg_t allowed_args[] = {
{ MP_QSTR_pin, MP_ARG_OBJ, {.u_obj = mp_obj_new_int(machine_rtc_config.ext0_pin)} },
{ MP_QSTR_level, MP_ARG_BOOL, {.u_bool = machine_rtc_config.ext0_level} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
if (args[ARG_pin].u_obj == mp_const_none) {
machine_rtc_config.ext0_pin = -1; // "None"
} else {
gpio_num_t pin_id = machine_pin_get_id(args[ARG_pin].u_obj);
if (pin_id != machine_rtc_config.ext0_pin) {
if (!RTC_IS_VALID_EXT_PIN(pin_id)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin"));
}
machine_rtc_config.ext0_pin = pin_id;
}
}
machine_rtc_config.ext0_level = args[ARG_level].u_bool;
machine_rtc_config.ext0_wake_types = MACHINE_WAKE_SLEEP | MACHINE_WAKE_DEEPSLEEP;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_wake_on_ext0_obj, 0, esp32_wake_on_ext0);
STATIC mp_obj_t esp32_wake_on_ext1(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum {ARG_pins, ARG_level};
const mp_arg_t allowed_args[] = {
{ MP_QSTR_pins, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_level, MP_ARG_BOOL, {.u_bool = machine_rtc_config.ext1_level} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
uint64_t ext1_pins = machine_rtc_config.ext1_pins;
// Check that all pins are allowed
if (args[ARG_pins].u_obj != mp_const_none) {
mp_uint_t len = 0;
mp_obj_t *elem;
mp_obj_get_array(args[ARG_pins].u_obj, &len, &elem);
ext1_pins = 0;
for (int i = 0; i < len; i++) {
gpio_num_t pin_id = machine_pin_get_id(elem[i]);
if (!RTC_IS_VALID_EXT_PIN(pin_id)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin"));
break;
}
ext1_pins |= (1ll << pin_id);
}
}
machine_rtc_config.ext1_level = args[ARG_level].u_bool;
machine_rtc_config.ext1_pins = ext1_pins;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_wake_on_ext1_obj, 0, esp32_wake_on_ext1);
STATIC const mp_rom_map_elem_t esp32_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp32) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wake_on_touch), (mp_obj_t)&esp32_wake_on_touch_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wake_on_ext0), (mp_obj_t)&esp32_wake_on_ext0_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wake_on_ext1), (mp_obj_t)&esp32_wake_on_ext1_obj },
{ MP_ROM_QSTR(MP_QSTR_ULP), MP_ROM_PTR(&esp32_ulp_type) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WAKEUP_ALL_LOW), mp_const_false },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WAKEUP_ANY_HIGH), mp_const_true },
};
STATIC MP_DEFINE_CONST_DICT(esp32_module_globals, esp32_module_globals_table);
const mp_obj_module_t esp32_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&esp32_module_globals,
};

View File

@ -1,31 +0,0 @@
#ifndef MICROPY_INCLUDED_ESP32_MODESP32_H
#define MICROPY_INCLUDED_ESP32_MODESP32_H
#define RTC_VALID_EXT_PINS \
( \
(1ll << 0) | \
(1ll << 2) | \
(1ll << 4) | \
(1ll << 12) | \
(1ll << 13) | \
(1ll << 14) | \
(1ll << 15) | \
(1ll << 25) | \
(1ll << 26) | \
(1ll << 27) | \
(1ll << 32) | \
(1ll << 33) | \
(1ll << 34) | \
(1ll << 35) | \
(1ll << 36) | \
(1ll << 37) | \
(1ll << 38) | \
(1ll << 39) \
)
#define RTC_LAST_EXT_PIN 39
#define RTC_IS_VALID_EXT_PIN(pin_id) ((1ll << (pin_id)) & RTC_VALID_EXT_PINS)
extern const mp_obj_type_t esp32_ulp_type;
#endif // MICROPY_INCLUDED_ESP32_MODESP32_H

View File

@ -1,269 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2015 Damien P. George
* Copyright (c) 2016 Paul Sokolovsky
*
* 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.
*/
#include <stdint.h>
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "rom/ets_sys.h"
#include "rom/rtc.h"
#include "esp_system.h"
#include "driver/touch_pad.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "extmod/machine_mem.h"
#include "extmod/machine_signal.h"
#include "extmod/machine_pulse.h"
#include "extmod/machine_i2c.h"
#include "extmod/machine_spi.h"
#include "modmachine.h"
#include "machine_rtc.h"
#if MICROPY_PY_MACHINE
typedef enum {
MP_PWRON_RESET = 1,
MP_HARD_RESET,
MP_WDT_RESET,
MP_DEEPSLEEP_RESET,
MP_SOFT_RESET
} reset_reason_t;
STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
// get
return mp_obj_new_int(ets_get_cpu_frequency() * 1000000);
} else {
// set
mp_int_t freq = mp_obj_get_int(args[0]) / 1000000;
if (freq != 80 && freq != 160 && freq != 240) {
mp_raise_ValueError("frequency can only be either 80Mhz, 160MHz or 240MHz");
}
/*
system_update_cpu_freq(freq);
*/
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq);
STATIC mp_obj_t machine_sleep_helper(wake_type_t wake_type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum {ARG_sleep_ms};
const mp_arg_t allowed_args[] = {
{ MP_QSTR_sleep_ms, MP_ARG_INT, { .u_int = 0 } },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_int_t expiry = args[ARG_sleep_ms].u_int;
if (expiry != 0) {
esp_sleep_enable_timer_wakeup(expiry * 1000);
}
if (machine_rtc_config.ext0_pin != -1 && (machine_rtc_config.ext0_wake_types & wake_type)) {
esp_sleep_enable_ext0_wakeup(machine_rtc_config.ext0_pin, machine_rtc_config.ext0_level ? 1 : 0);
}
if (machine_rtc_config.ext1_pins != 0) {
esp_sleep_enable_ext1_wakeup(
machine_rtc_config.ext1_pins,
machine_rtc_config.ext1_level ? ESP_EXT1_WAKEUP_ANY_HIGH : ESP_EXT1_WAKEUP_ALL_LOW);
}
if (machine_rtc_config.wake_on_touch) {
if (esp_sleep_enable_touchpad_wakeup() != ESP_OK) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "esp_sleep_enable_touchpad_wakeup() failed"));
}
}
switch(wake_type) {
case MACHINE_WAKE_SLEEP:
esp_light_sleep_start();
break;
case MACHINE_WAKE_DEEPSLEEP:
esp_deep_sleep_start();
break;
}
return mp_const_none;
}
STATIC mp_obj_t machine_sleep(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "light sleep not available for this version of ESP-IDF"));
return machine_sleep_helper(MACHINE_WAKE_SLEEP, n_args, pos_args, kw_args);
};
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_sleep_obj, 0, machine_sleep);
STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
return machine_sleep_helper(MACHINE_WAKE_DEEPSLEEP, n_args, pos_args, kw_args);
};
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_deepsleep_obj, 0, machine_deepsleep);
STATIC mp_obj_t machine_reset_cause(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
switch(rtc_get_reset_reason(0)) {
case POWERON_RESET:
return MP_OBJ_NEW_SMALL_INT(MP_PWRON_RESET);
break;
case SW_RESET:
case SW_CPU_RESET:
return MP_OBJ_NEW_SMALL_INT(MP_SOFT_RESET);
break;
case OWDT_RESET:
case TG0WDT_SYS_RESET:
case TG1WDT_SYS_RESET:
case RTCWDT_SYS_RESET:
case RTCWDT_BROWN_OUT_RESET:
case RTCWDT_CPU_RESET:
case RTCWDT_RTC_RESET:
case TGWDT_CPU_RESET:
return MP_OBJ_NEW_SMALL_INT(MP_WDT_RESET);
break;
case DEEPSLEEP_RESET:
return MP_OBJ_NEW_SMALL_INT(MP_DEEPSLEEP_RESET);
break;
case EXT_CPU_RESET:
return MP_OBJ_NEW_SMALL_INT(MP_HARD_RESET);
break;
case NO_MEAN:
case SDIO_RESET:
case INTRUSION_RESET:
default:
return MP_OBJ_NEW_SMALL_INT(0);
break;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_reset_cause_obj, 0, machine_reset_cause);
STATIC mp_obj_t machine_wake_reason(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
return MP_OBJ_NEW_SMALL_INT(esp_sleep_get_wakeup_cause());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_wake_reason_obj, 0, machine_wake_reason);
STATIC mp_obj_t machine_reset(void) {
esp_restart();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
STATIC mp_obj_t machine_unique_id(void) {
uint8_t chipid[6];
esp_efuse_mac_get_default(chipid);
return mp_obj_new_bytes(chipid, 6);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id);
STATIC mp_obj_t machine_idle(void) {
taskYIELD();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
STATIC mp_obj_t machine_disable_irq(void) {
uint32_t state = MICROPY_BEGIN_ATOMIC_SECTION();
return mp_obj_new_int(state);
}
MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq);
STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) {
uint32_t state = mp_obj_get_int(state_in);
MICROPY_END_ATOMIC_SECTION(state);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq);
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
{ MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) },
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
{ MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
{ MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_sleep_obj) },
{ MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) },
{ MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) },
{ MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) },
{ MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) },
{ MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) },
{ MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) },
// wake abilities
{ MP_ROM_QSTR(MP_QSTR_SLEEP), MP_ROM_INT(MACHINE_WAKE_SLEEP) },
{ MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(MACHINE_WAKE_DEEPSLEEP) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
{ MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
{ MP_ROM_QSTR(MP_QSTR_TouchPad), MP_ROM_PTR(&machine_touchpad_type) },
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
{ MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) },
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) },
// Reset reasons
{ MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
{ MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(MP_HARD_RESET) },
{ MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(MP_PWRON_RESET) },
{ MP_ROM_QSTR(MP_QSTR_WDT_RESET), MP_ROM_INT(MP_WDT_RESET) },
{ MP_ROM_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_ROM_INT(MP_DEEPSLEEP_RESET) },
{ MP_ROM_QSTR(MP_QSTR_SOFT_RESET), MP_ROM_INT(MP_SOFT_RESET) },
// Wake reasons
{ MP_ROM_QSTR(MP_QSTR_wake_reason), MP_ROM_PTR(&machine_wake_reason_obj) },
{ MP_ROM_QSTR(MP_QSTR_PIN_WAKE), MP_ROM_INT(ESP_SLEEP_WAKEUP_EXT0) },
{ MP_ROM_QSTR(MP_QSTR_EXT0_WAKE), MP_ROM_INT(ESP_SLEEP_WAKEUP_EXT0) },
{ MP_ROM_QSTR(MP_QSTR_EXT1_WAKE), MP_ROM_INT(ESP_SLEEP_WAKEUP_EXT1) },
{ MP_ROM_QSTR(MP_QSTR_TIMER_WAKE), MP_ROM_INT(ESP_SLEEP_WAKEUP_TIMER) },
{ MP_ROM_QSTR(MP_QSTR_TOUCHPAD_WAKE), MP_ROM_INT(ESP_SLEEP_WAKEUP_TOUCHPAD) },
{ MP_ROM_QSTR(MP_QSTR_ULP_WAKE), MP_ROM_INT(ESP_SLEEP_WAKEUP_ULP) },
};
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
const mp_obj_module_t mp_module_machine = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&machine_module_globals,
};
#endif // MICROPY_PY_MACHINE

View File

@ -1,26 +0,0 @@
#ifndef MICROPY_INCLUDED_ESP32_MODMACHINE_H
#define MICROPY_INCLUDED_ESP32_MODMACHINE_H
#include "py/obj.h"
typedef enum {
//MACHINE_WAKE_IDLE=0x01,
MACHINE_WAKE_SLEEP=0x02,
MACHINE_WAKE_DEEPSLEEP=0x04
} wake_type_t;
extern const mp_obj_type_t machine_timer_type;
extern const mp_obj_type_t machine_wdt_type;
extern const mp_obj_type_t machine_pin_type;
extern const mp_obj_type_t machine_touchpad_type;
extern const mp_obj_type_t machine_adc_type;
extern const mp_obj_type_t machine_dac_type;
extern const mp_obj_type_t machine_pwm_type;
extern const mp_obj_type_t machine_hw_spi_type;
extern const mp_obj_type_t machine_uart_type;
extern const mp_obj_type_t machine_rtc_type;
void machine_pins_init(void);
void machine_pins_deinit(void);
#endif // MICROPY_INCLUDED_ESP32_MODMACHINE_H

View File

@ -1,646 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
* and Mnemote Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2016, 2017 Nick Moore @mnemote
* Copyright (c) 2017 "Eric Poulsen" <eric@zyxod.com>
*
* Based on esp8266/modnetwork.c which is Copyright (c) 2015 Paul Sokolovsky
* And the ESP IDF example code which is Public Domain / CC0
*
* 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.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "py/nlr.h"
#include "py/objlist.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "py/mperrno.h"
#include "netutils.h"
#include "esp_wifi.h"
#include "esp_wifi_types.h"
#include "esp_log.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "lwip/dns.h"
#include "tcpip_adapter.h"
#include "modnetwork.h"
#define MODNETWORK_INCLUDE_CONSTANTS (1)
NORETURN void _esp_exceptions(esp_err_t e) {
switch (e) {
case ESP_ERR_WIFI_NOT_INIT:
mp_raise_msg(&mp_type_OSError, "Wifi Not Initialized");
case ESP_ERR_WIFI_NOT_STARTED:
mp_raise_msg(&mp_type_OSError, "Wifi Not Started");
case ESP_ERR_WIFI_NOT_STOPPED:
mp_raise_msg(&mp_type_OSError, "Wifi Not Stopped");
case ESP_ERR_WIFI_IF:
mp_raise_msg(&mp_type_OSError, "Wifi Invalid Interface");
case ESP_ERR_WIFI_MODE:
mp_raise_msg(&mp_type_OSError, "Wifi Invalid Mode");
case ESP_ERR_WIFI_STATE:
mp_raise_msg(&mp_type_OSError, "Wifi Internal State Error");
case ESP_ERR_WIFI_CONN:
mp_raise_msg(&mp_type_OSError, "Wifi Internal Error");
case ESP_ERR_WIFI_NVS:
mp_raise_msg(&mp_type_OSError, "Wifi Internal NVS Error");
case ESP_ERR_WIFI_MAC:
mp_raise_msg(&mp_type_OSError, "Wifi Invalid MAC Address");
case ESP_ERR_WIFI_SSID:
mp_raise_msg(&mp_type_OSError, "Wifi SSID Invalid");
case ESP_ERR_WIFI_PASSWORD:
mp_raise_msg(&mp_type_OSError, "Wifi Invalid Password");
case ESP_ERR_WIFI_TIMEOUT:
mp_raise_OSError(MP_ETIMEDOUT);
case ESP_ERR_WIFI_WAKE_FAIL:
mp_raise_msg(&mp_type_OSError, "Wifi Wakeup Failure");
case ESP_ERR_WIFI_WOULD_BLOCK:
mp_raise_msg(&mp_type_OSError, "Wifi Would Block");
case ESP_ERR_WIFI_NOT_CONNECT:
mp_raise_msg(&mp_type_OSError, "Wifi Not Connected");
case ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS:
mp_raise_msg(&mp_type_OSError, "TCP/IP Invalid Parameters");
case ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY:
mp_raise_msg(&mp_type_OSError, "TCP/IP IF Not Ready");
case ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED:
mp_raise_msg(&mp_type_OSError, "TCP/IP DHCP Client Start Failed");
case ESP_ERR_TCPIP_ADAPTER_NO_MEM:
mp_raise_OSError(MP_ENOMEM);
default:
nlr_raise(mp_obj_new_exception_msg_varg(
&mp_type_RuntimeError, "Wifi Unknown Error 0x%04x", e
));
}
}
static inline void esp_exceptions(esp_err_t e) {
if (e != ESP_OK) _esp_exceptions(e);
}
#define ESP_EXCEPTIONS(x) do { esp_exceptions(x); } while (0);
typedef struct _wlan_if_obj_t {
mp_obj_base_t base;
int if_id;
} wlan_if_obj_t;
const mp_obj_type_t wlan_if_type;
STATIC const wlan_if_obj_t wlan_sta_obj = {{&wlan_if_type}, WIFI_IF_STA};
STATIC const wlan_if_obj_t wlan_ap_obj = {{&wlan_if_type}, WIFI_IF_AP};
//static wifi_config_t wifi_ap_config = {{{0}}};
static wifi_config_t wifi_sta_config = {{{0}}};
// Set to "true" if esp_wifi_start() was called
static bool wifi_started = false;
// Set to "true" if the STA interface is requested to be connected by the
// user, used for automatic reassociation.
static bool wifi_sta_connect_requested = false;
// Set to "true" if the STA interface is connected to wifi and has IP address.
static bool wifi_sta_connected = false;
// This function is called by the system-event task and so runs in a different
// thread to the main MicroPython task. It must not raise any Python exceptions.
static esp_err_t event_handler(void *ctx, system_event_t *event) {
switch(event->event_id) {
case SYSTEM_EVENT_STA_START:
ESP_LOGI("wifi", "STA_START");
break;
case SYSTEM_EVENT_STA_CONNECTED:
ESP_LOGI("network", "CONNECTED");
break;
case SYSTEM_EVENT_STA_GOT_IP:
ESP_LOGI("network", "GOT_IP");
wifi_sta_connected = true;
break;
case SYSTEM_EVENT_STA_DISCONNECTED: {
// This is a workaround as ESP32 WiFi libs don't currently
// auto-reassociate.
system_event_sta_disconnected_t *disconn = &event->event_info.disconnected;
char *message = "";
switch (disconn->reason) {
case WIFI_REASON_BEACON_TIMEOUT:
// AP has dropped out; try to reconnect.
message = "\nbeacon timeout";
break;
case WIFI_REASON_NO_AP_FOUND:
// AP may not exist, or it may have momentarily dropped out; try to reconnect.
message = "\nno AP found";
break;
case WIFI_REASON_AUTH_FAIL:
message = "\nauthentication failed";
wifi_sta_connect_requested = false;
break;
default:
// Let other errors through and try to reconnect.
break;
}
ESP_LOGI("wifi", "STA_DISCONNECTED, reason:%d%s", disconn->reason, message);
bool reconnected = false;
if (wifi_sta_connect_requested) {
wifi_mode_t mode;
if (esp_wifi_get_mode(&mode) == ESP_OK) {
if (mode & WIFI_MODE_STA) {
// STA is active so attempt to reconnect.
esp_err_t e = esp_wifi_connect();
if (e != ESP_OK) {
ESP_LOGI("wifi", "error attempting to reconnect: 0x%04x", e);
} else {
reconnected = true;
}
}
}
}
if (wifi_sta_connected && !reconnected) {
// If already connected and we fail to reconnect
wifi_sta_connected = false;
}
break;
}
default:
ESP_LOGI("network", "event %d", event->event_id);
break;
}
return ESP_OK;
}
/*void error_check(bool status, const char *msg) {
if (!status) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, msg));
}
}
*/
STATIC void require_if(mp_obj_t wlan_if, int if_no) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(wlan_if);
if (self->if_id != if_no) {
mp_raise_msg(&mp_type_OSError, if_no == WIFI_IF_STA ? "STA required" : "AP required");
}
}
STATIC mp_obj_t get_wlan(size_t n_args, const mp_obj_t *args) {
static int initialized = 0;
if (!initialized) {
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_LOGD("modnetwork", "Initializing WiFi");
ESP_EXCEPTIONS( esp_wifi_init(&cfg) );
ESP_EXCEPTIONS( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
ESP_LOGD("modnetwork", "Initialized");
initialized = 1;
}
int idx = (n_args > 0) ? mp_obj_get_int(args[0]) : WIFI_IF_STA;
if (idx == WIFI_IF_STA) {
return MP_OBJ_FROM_PTR(&wlan_sta_obj);
} else if (idx == WIFI_IF_AP) {
return MP_OBJ_FROM_PTR(&wlan_ap_obj);
} else {
mp_raise_ValueError("invalid WLAN interface identifier");
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 1, get_wlan);
STATIC mp_obj_t esp_initialize() {
static int initialized = 0;
if (!initialized) {
ESP_LOGD("modnetwork", "Initializing TCP/IP");
tcpip_adapter_init();
ESP_LOGD("modnetwork", "Initializing Event Loop");
ESP_EXCEPTIONS( esp_event_loop_init(event_handler, NULL) );
ESP_LOGD("modnetwork", "esp_event_loop_init done");
initialized = 1;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_initialize_obj, esp_initialize);
#if (WIFI_MODE_STA & WIFI_MODE_AP != WIFI_MODE_NULL || WIFI_MODE_STA | WIFI_MODE_AP != WIFI_MODE_APSTA)
#error WIFI_MODE_STA and WIFI_MODE_AP are supposed to be bitfields!
#endif
STATIC mp_obj_t esp_active(size_t n_args, const mp_obj_t *args) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
wifi_mode_t mode;
if (!wifi_started) {
mode = WIFI_MODE_NULL;
} else {
ESP_EXCEPTIONS(esp_wifi_get_mode(&mode));
}
int bit = (self->if_id == WIFI_IF_STA) ? WIFI_MODE_STA : WIFI_MODE_AP;
if (n_args > 1) {
bool active = mp_obj_is_true(args[1]);
mode = active ? (mode | bit) : (mode & ~bit);
if (mode == WIFI_MODE_NULL) {
if (wifi_started) {
ESP_EXCEPTIONS(esp_wifi_stop());
wifi_started = false;
}
} else {
ESP_EXCEPTIONS(esp_wifi_set_mode(mode));
if (!wifi_started) {
ESP_EXCEPTIONS(esp_wifi_start());
wifi_started = true;
}
}
}
return (mode & bit) ? mp_const_true : mp_const_false;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_active_obj, 1, 2, esp_active);
STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *args) {
mp_uint_t len;
const char *p;
if (n_args > 1) {
memset(&wifi_sta_config, 0, sizeof(wifi_sta_config));
p = mp_obj_str_get_data(args[1], &len);
memcpy(wifi_sta_config.sta.ssid, p, MIN(len, sizeof(wifi_sta_config.sta.ssid)));
p = (n_args > 2) ? mp_obj_str_get_data(args[2], &len) : "";
memcpy(wifi_sta_config.sta.password, p, MIN(len, sizeof(wifi_sta_config.sta.password)));
ESP_EXCEPTIONS( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_sta_config) );
}
MP_THREAD_GIL_EXIT();
ESP_EXCEPTIONS( esp_wifi_connect() );
MP_THREAD_GIL_ENTER();
wifi_sta_connect_requested = true;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_connect_obj, 1, 7, esp_connect);
STATIC mp_obj_t esp_disconnect(mp_obj_t self_in) {
wifi_sta_connect_requested = false;
ESP_EXCEPTIONS( esp_wifi_disconnect() );
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_disconnect_obj, esp_disconnect);
STATIC mp_obj_t esp_status(size_t n_args, const mp_obj_t *args) {
if (n_args == 1) {
// no arguments: return None until link status is implemented
return mp_const_none;
}
// one argument: return status based on query parameter
switch ((uintptr_t)args[1]) {
case (uintptr_t)MP_OBJ_NEW_QSTR(MP_QSTR_stations): {
// return list of connected stations, only if in soft-AP mode
require_if(args[0], WIFI_IF_AP);
wifi_sta_list_t station_list;
ESP_EXCEPTIONS(esp_wifi_ap_get_sta_list(&station_list));
wifi_sta_info_t *stations = (wifi_sta_info_t*)station_list.sta;
mp_obj_t list = mp_obj_new_list(0, NULL);
for (int i = 0; i < station_list.num; ++i) {
mp_obj_tuple_t *t = mp_obj_new_tuple(1, NULL);
t->items[0] = mp_obj_new_bytes(stations[i].mac, sizeof(stations[i].mac));
mp_obj_list_append(list, t);
}
return list;
}
default:
mp_raise_ValueError("unknown status param");
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_status_obj, 1, 2, esp_status);
STATIC mp_obj_t esp_scan(mp_obj_t self_in) {
// check that STA mode is active
wifi_mode_t mode;
ESP_EXCEPTIONS(esp_wifi_get_mode(&mode));
if ((mode & WIFI_MODE_STA) == 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "STA must be active"));
}
mp_obj_t list = mp_obj_new_list(0, NULL);
wifi_scan_config_t config = { 0 };
// XXX how do we scan hidden APs (and if we can scan them, are they really hidden?)
MP_THREAD_GIL_EXIT();
esp_err_t status = esp_wifi_scan_start(&config, 1);
MP_THREAD_GIL_ENTER();
if (status == 0) {
uint16_t count = 0;
ESP_EXCEPTIONS( esp_wifi_scan_get_ap_num(&count) );
wifi_ap_record_t *wifi_ap_records = calloc(count, sizeof(wifi_ap_record_t));
ESP_EXCEPTIONS( esp_wifi_scan_get_ap_records(&count, wifi_ap_records) );
for (uint16_t i = 0; i < count; i++) {
mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL);
uint8_t *x = memchr(wifi_ap_records[i].ssid, 0, sizeof(wifi_ap_records[i].ssid));
int ssid_len = x ? x - wifi_ap_records[i].ssid : sizeof(wifi_ap_records[i].ssid);
t->items[0] = mp_obj_new_bytes(wifi_ap_records[i].ssid, ssid_len);
t->items[1] = mp_obj_new_bytes(wifi_ap_records[i].bssid, sizeof(wifi_ap_records[i].bssid));
t->items[2] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].primary);
t->items[3] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].rssi);
t->items[4] = MP_OBJ_NEW_SMALL_INT(wifi_ap_records[i].authmode);
t->items[5] = mp_const_false; // XXX hidden?
mp_obj_list_append(list, MP_OBJ_FROM_PTR(t));
}
free(wifi_ap_records);
}
return list;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_scan_obj, esp_scan);
STATIC mp_obj_t esp_isconnected(mp_obj_t self_in) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->if_id == WIFI_IF_STA) {
return mp_obj_new_bool(wifi_sta_connected);
} else {
wifi_sta_list_t sta;
esp_wifi_ap_get_sta_list(&sta);
return mp_obj_new_bool(sta.num != 0);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_isconnected_obj, esp_isconnected);
STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
tcpip_adapter_ip_info_t info;
tcpip_adapter_dns_info_t dns_info;
tcpip_adapter_get_ip_info(self->if_id, &info);
tcpip_adapter_get_dns_info(self->if_id, TCPIP_ADAPTER_DNS_MAIN, &dns_info);
if (n_args == 1) {
// get
mp_obj_t tuple[4] = {
netutils_format_ipv4_addr((uint8_t*)&info.ip, NETUTILS_BIG),
netutils_format_ipv4_addr((uint8_t*)&info.netmask, NETUTILS_BIG),
netutils_format_ipv4_addr((uint8_t*)&info.gw, NETUTILS_BIG),
netutils_format_ipv4_addr((uint8_t*)&dns_info.ip, NETUTILS_BIG),
};
return mp_obj_new_tuple(4, tuple);
} else {
// set
mp_obj_t *items;
mp_obj_get_array_fixed_n(args[1], 4, &items);
netutils_parse_ipv4_addr(items[0], (void*)&info.ip, NETUTILS_BIG);
if (mp_obj_is_integer(items[1])) {
// allow numeric netmask, i.e.:
// 24 -> 255.255.255.0
// 16 -> 255.255.0.0
// etc...
uint32_t* m = (uint32_t*)&info.netmask;
*m = htonl(0xffffffff << (32 - mp_obj_get_int(items[1])));
} else {
netutils_parse_ipv4_addr(items[1], (void*)&info.netmask, NETUTILS_BIG);
}
netutils_parse_ipv4_addr(items[2], (void*)&info.gw, NETUTILS_BIG);
netutils_parse_ipv4_addr(items[3], (void*)&dns_info.ip, NETUTILS_BIG);
// To set a static IP we have to disable DHCP first
if (self->if_id == WIFI_IF_STA || self->if_id == ESP_IF_ETH) {
esp_err_t e = tcpip_adapter_dhcpc_stop(self->if_id);
if (e != ESP_OK && e != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) _esp_exceptions(e);
ESP_EXCEPTIONS(tcpip_adapter_set_ip_info(self->if_id, &info));
ESP_EXCEPTIONS(tcpip_adapter_set_dns_info(self->if_id, TCPIP_ADAPTER_DNS_MAIN, &dns_info));
} else if (self->if_id == WIFI_IF_AP) {
esp_err_t e = tcpip_adapter_dhcps_stop(WIFI_IF_AP);
if (e != ESP_OK && e != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) _esp_exceptions(e);
ESP_EXCEPTIONS(tcpip_adapter_set_ip_info(WIFI_IF_AP, &info));
ESP_EXCEPTIONS(tcpip_adapter_set_dns_info(WIFI_IF_AP, TCPIP_ADAPTER_DNS_MAIN, &dns_info));
ESP_EXCEPTIONS(tcpip_adapter_dhcps_start(WIFI_IF_AP));
}
return mp_const_none;
}
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig);
STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
if (n_args != 1 && kwargs->used != 0) {
mp_raise_TypeError("either pos or kw args are allowed");
}
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
// get the config for the interface
wifi_config_t cfg;
ESP_EXCEPTIONS(esp_wifi_get_config(self->if_id, &cfg));
if (kwargs->used != 0) {
for (size_t i = 0; i < kwargs->alloc; i++) {
if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) {
int req_if = -1;
#define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x)
switch ((uintptr_t)kwargs->table[i].key) {
case QS(MP_QSTR_mac): {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(kwargs->table[i].value, &bufinfo, MP_BUFFER_READ);
if (bufinfo.len != 6) {
mp_raise_ValueError("invalid buffer length");
}
ESP_EXCEPTIONS(esp_wifi_set_mac(self->if_id, bufinfo.buf));
break;
}
case QS(MP_QSTR_essid): {
req_if = WIFI_IF_AP;
mp_uint_t len;
const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
len = MIN(len, sizeof(cfg.ap.ssid));
memcpy(cfg.ap.ssid, s, len);
cfg.ap.ssid_len = len;
break;
}
case QS(MP_QSTR_hidden): {
req_if = WIFI_IF_AP;
cfg.ap.ssid_hidden = mp_obj_is_true(kwargs->table[i].value);
break;
}
case QS(MP_QSTR_authmode): {
req_if = WIFI_IF_AP;
cfg.ap.authmode = mp_obj_get_int(kwargs->table[i].value);
break;
}
case QS(MP_QSTR_password): {
req_if = WIFI_IF_AP;
mp_uint_t len;
const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
len = MIN(len, sizeof(cfg.ap.password) - 1);
memcpy(cfg.ap.password, s, len);
cfg.ap.password[len] = 0;
break;
}
case QS(MP_QSTR_channel): {
req_if = WIFI_IF_AP;
cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value);
break;
}
case QS(MP_QSTR_dhcp_hostname): {
const char *s = mp_obj_str_get_str(kwargs->table[i].value);
ESP_EXCEPTIONS(tcpip_adapter_set_hostname(self->if_id, s));
break;
}
default:
goto unknown;
}
#undef QS
// We post-check interface requirements to save on code size
if (req_if >= 0) {
require_if(args[0], req_if);
}
}
}
ESP_EXCEPTIONS(esp_wifi_set_config(self->if_id, &cfg));
return mp_const_none;
}
// Get config
if (n_args != 2) {
mp_raise_TypeError("can query only one param");
}
int req_if = -1;
mp_obj_t val;
#define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x)
switch ((uintptr_t)args[1]) {
case QS(MP_QSTR_mac): {
uint8_t mac[6];
ESP_EXCEPTIONS(esp_wifi_get_mac(self->if_id, mac));
return mp_obj_new_bytes(mac, sizeof(mac));
}
case QS(MP_QSTR_essid):
if (self->if_id == WIFI_IF_STA) {
val = mp_obj_new_str((char*)cfg.sta.ssid, strlen((char*)cfg.sta.ssid));
} else {
val = mp_obj_new_str((char*)cfg.ap.ssid, cfg.ap.ssid_len);
}
break;
case QS(MP_QSTR_hidden):
req_if = WIFI_IF_AP;
val = mp_obj_new_bool(cfg.ap.ssid_hidden);
break;
case QS(MP_QSTR_authmode):
req_if = WIFI_IF_AP;
val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode);
break;
case QS(MP_QSTR_channel):
req_if = WIFI_IF_AP;
val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel);
break;
case QS(MP_QSTR_dhcp_hostname): {
const char *s;
ESP_EXCEPTIONS(tcpip_adapter_get_hostname(self->if_id, &s));
val = mp_obj_new_str(s, strlen(s));
break;
}
default:
goto unknown;
}
#undef QS
// We post-check interface requirements to save on code size
if (req_if >= 0) {
require_if(args[0], req_if);
}
return val;
unknown:
mp_raise_ValueError("unknown config param");
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_config_obj, 1, esp_config);
STATIC const mp_rom_map_elem_t wlan_if_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&esp_active_obj) },
{ MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&esp_connect_obj) },
{ MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&esp_disconnect_obj) },
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&esp_status_obj) },
{ MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&esp_scan_obj) },
{ MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&esp_isconnected_obj) },
{ MP_ROM_QSTR(MP_QSTR_config), MP_ROM_PTR(&esp_config_obj) },
{ MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) },
};
STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table);
const mp_obj_type_t wlan_if_type = {
{ &mp_type_type },
.name = MP_QSTR_WLAN,
.locals_dict = (mp_obj_t)&wlan_if_locals_dict,
};
STATIC mp_obj_t esp_phy_mode(size_t n_args, const mp_obj_t *args) {
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_phy_mode_obj, 0, 1, esp_phy_mode);
STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) },
{ MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&esp_initialize_obj) },
{ MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&get_wlan_obj) },
{ MP_ROM_QSTR(MP_QSTR_LAN), MP_ROM_PTR(&get_lan_obj) },
{ MP_ROM_QSTR(MP_QSTR_phy_mode), MP_ROM_PTR(&esp_phy_mode_obj) },
#if MODNETWORK_INCLUDE_CONSTANTS
{ MP_ROM_QSTR(MP_QSTR_STA_IF), MP_ROM_INT(WIFI_IF_STA)},
{ MP_ROM_QSTR(MP_QSTR_AP_IF), MP_ROM_INT(WIFI_IF_AP)},
{ MP_ROM_QSTR(MP_QSTR_MODE_11B), MP_ROM_INT(WIFI_PROTOCOL_11B) },
{ MP_ROM_QSTR(MP_QSTR_MODE_11G), MP_ROM_INT(WIFI_PROTOCOL_11G) },
{ MP_ROM_QSTR(MP_QSTR_MODE_11N), MP_ROM_INT(WIFI_PROTOCOL_11N) },
{ MP_ROM_QSTR(MP_QSTR_AUTH_OPEN), MP_ROM_INT(WIFI_AUTH_OPEN) },
{ MP_ROM_QSTR(MP_QSTR_AUTH_WEP), MP_ROM_INT(WIFI_AUTH_WEP) },
{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA_PSK), MP_ROM_INT(WIFI_AUTH_WPA_PSK) },
{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA2_PSK), MP_ROM_INT(WIFI_AUTH_WPA2_PSK) },
{ MP_ROM_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK), MP_ROM_INT(WIFI_AUTH_WPA_WPA2_PSK) },
{ MP_ROM_QSTR(MP_QSTR_AUTH_MAX), MP_ROM_INT(WIFI_AUTH_MAX) },
{ MP_ROM_QSTR(MP_QSTR_PHY_LAN8720), MP_ROM_INT(PHY_LAN8720) },
{ MP_ROM_QSTR(MP_QSTR_PHY_TLK110), MP_ROM_INT(PHY_TLK110) },
#endif
};
STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table);
const mp_obj_module_t mp_module_network = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&mp_module_network_globals,
};

View File

@ -1,36 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 "Eric Poulsen" <eric@zyxod.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESP32_MODNETWORK_H
#define MICROPY_INCLUDED_ESP32_MODNETWORK_H
enum { PHY_LAN8720, PHY_TLK110 };
MP_DECLARE_CONST_FUN_OBJ_KW(get_lan_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj);
void usocket_events_deinit(void);
#endif

View File

@ -1,702 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
* and Mnemote Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2016, 2017 Nick Moore @mnemote
*
* Based on extmod/modlwip.c
* Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2015 Galen Hazelwood
*
* 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.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "py/runtime0.h"
#include "py/nlr.h"
#include "py/objlist.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "py/stream.h"
#include "py/mperrno.h"
#include "lib/netutils/netutils.h"
#include "tcpip_adapter.h"
#include "modnetwork.h"
#include "lwip/sockets.h"
#include "lwip/netdb.h"
#include "lwip/ip4.h"
#include "lwip/igmp.h"
#include "esp_log.h"
#define SOCKET_POLL_US (100000)
typedef struct _socket_obj_t {
mp_obj_base_t base;
int fd;
uint8_t domain;
uint8_t type;
uint8_t proto;
bool peer_closed;
unsigned int retries;
#if MICROPY_PY_USOCKET_EVENTS
mp_obj_t events_callback;
struct _socket_obj_t *events_next;
#endif
} socket_obj_t;
void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms);
#if MICROPY_PY_USOCKET_EVENTS
// Support for callbacks on asynchronous socket events (when socket becomes readable)
// This divisor is used to reduce the load on the system, so it doesn't poll sockets too often
#define USOCKET_EVENTS_DIVISOR (8)
STATIC uint8_t usocket_events_divisor;
STATIC socket_obj_t *usocket_events_head;
void usocket_events_deinit(void) {
usocket_events_head = NULL;
}
// Assumes the socket is not already in the linked list, and adds it
STATIC void usocket_events_add(socket_obj_t *sock) {
sock->events_next = usocket_events_head;
usocket_events_head = sock;
}
// Assumes the socket is already in the linked list, and removes it
STATIC void usocket_events_remove(socket_obj_t *sock) {
for (socket_obj_t **s = &usocket_events_head;; s = &(*s)->events_next) {
if (*s == sock) {
*s = (*s)->events_next;
return;
}
}
}
// Polls all registered sockets for readability and calls their callback if they are readable
void usocket_events_handler(void) {
if (usocket_events_head == NULL) {
return;
}
if (--usocket_events_divisor) {
return;
}
usocket_events_divisor = USOCKET_EVENTS_DIVISOR;
fd_set rfds;
FD_ZERO(&rfds);
int max_fd = 0;
for (socket_obj_t *s = usocket_events_head; s != NULL; s = s->events_next) {
FD_SET(s->fd, &rfds);
max_fd = MAX(max_fd, s->fd);
}
// Poll the sockets
struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 };
int r = select(max_fd + 1, &rfds, NULL, NULL, &timeout);
if (r <= 0) {
return;
}
// Call the callbacks
for (socket_obj_t *s = usocket_events_head; s != NULL; s = s->events_next) {
if (FD_ISSET(s->fd, &rfds)) {
mp_call_function_1_protected(s->events_callback, s);
}
}
}
#endif // MICROPY_PY_USOCKET_EVENTS
NORETURN static void exception_from_errno(int _errno) {
// Here we need to convert from lwip errno values to MicroPython's standard ones
if (_errno == EINPROGRESS) {
_errno = MP_EINPROGRESS;
}
mp_raise_OSError(_errno);
}
static inline void check_for_exceptions(void) {
mp_handle_pending();
}
static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struct addrinfo **resp) {
const struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
};
mp_obj_t port = portx;
if (MP_OBJ_IS_SMALL_INT(port)) {
// This is perverse, because lwip_getaddrinfo promptly converts it back to an int, but
// that's the API we have to work with ...
port = mp_obj_str_binary_op(MP_BINARY_OP_MODULO, mp_obj_new_str_via_qstr("%s", 2), port);
}
const char *host_str = mp_obj_str_get_str(host);
const char *port_str = mp_obj_str_get_str(port);
if (host_str[0] == '\0') {
// a host of "" is equivalent to the default/all-local IP address
host_str = "0.0.0.0";
}
MP_THREAD_GIL_EXIT();
int res = lwip_getaddrinfo(host_str, port_str, &hints, resp);
MP_THREAD_GIL_ENTER();
return res;
}
int _socket_getaddrinfo(const mp_obj_t addrtuple, struct addrinfo **resp) {
mp_uint_t len = 0;
mp_obj_t *elem;
mp_obj_get_array(addrtuple, &len, &elem);
if (len != 2) return -1;
return _socket_getaddrinfo2(elem[0], elem[1], resp);
}
STATIC mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) {
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
struct addrinfo *res;
_socket_getaddrinfo(arg1, &res);
int r = lwip_bind_r(self->fd, res->ai_addr, res->ai_addrlen);
lwip_freeaddrinfo(res);
if (r < 0) exception_from_errno(errno);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
STATIC mp_obj_t socket_listen(const mp_obj_t arg0, const mp_obj_t arg1) {
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
int backlog = mp_obj_get_int(arg1);
int r = lwip_listen_r(self->fd, backlog);
if (r < 0) exception_from_errno(errno);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen);
STATIC mp_obj_t socket_accept(const mp_obj_t arg0) {
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
struct sockaddr addr;
socklen_t addr_len = sizeof(addr);
int new_fd = -1;
for (int i=0; i<=self->retries; i++) {
MP_THREAD_GIL_EXIT();
new_fd = lwip_accept_r(self->fd, &addr, &addr_len);
MP_THREAD_GIL_ENTER();
if (new_fd >= 0) break;
if (errno != EAGAIN) exception_from_errno(errno);
check_for_exceptions();
}
if (new_fd < 0) mp_raise_OSError(MP_ETIMEDOUT);
// create new socket object
socket_obj_t *sock = m_new_obj_with_finaliser(socket_obj_t);
sock->base.type = self->base.type;
sock->fd = new_fd;
sock->domain = self->domain;
sock->type = self->type;
sock->proto = self->proto;
sock->peer_closed = false;
_socket_settimeout(sock, UINT64_MAX);
// make the return value
uint8_t *ip = (uint8_t*)&((struct sockaddr_in*)&addr)->sin_addr;
mp_uint_t port = lwip_ntohs(((struct sockaddr_in*)&addr)->sin_port);
mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL);
client->items[0] = sock;
client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
return client;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
STATIC mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) {
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
struct addrinfo *res;
_socket_getaddrinfo(arg1, &res);
MP_THREAD_GIL_EXIT();
int r = lwip_connect_r(self->fd, res->ai_addr, res->ai_addrlen);
MP_THREAD_GIL_ENTER();
lwip_freeaddrinfo(res);
if (r != 0) {
exception_from_errno(errno);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) {
(void)n_args; // always 4
socket_obj_t *self = MP_OBJ_TO_PTR(args[0]);
int opt = mp_obj_get_int(args[2]);
switch (opt) {
// level: SOL_SOCKET
case SO_REUSEADDR: {
int val = mp_obj_get_int(args[3]);
int ret = lwip_setsockopt_r(self->fd, SOL_SOCKET, opt, &val, sizeof(int));
if (ret != 0) {
exception_from_errno(errno);
}
break;
}
#if MICROPY_PY_USOCKET_EVENTS
// level: SOL_SOCKET
// special "register callback" option
case 20: {
if (args[3] == mp_const_none) {
if (self->events_callback != MP_OBJ_NULL) {
usocket_events_remove(self);
self->events_callback = MP_OBJ_NULL;
}
} else {
if (self->events_callback == MP_OBJ_NULL) {
usocket_events_add(self);
}
self->events_callback = args[3];
}
break;
}
#endif
// level: IPPROTO_IP
case IP_ADD_MEMBERSHIP: {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ);
if (bufinfo.len != sizeof(ip4_addr_t) * 2) {
mp_raise_ValueError(NULL);
}
// POSIX setsockopt has order: group addr, if addr, lwIP has it vice-versa
err_t err = igmp_joingroup((const ip4_addr_t*)bufinfo.buf + 1, bufinfo.buf);
if (err != ERR_OK) {
mp_raise_OSError(-err);
}
break;
}
default:
mp_printf(&mp_plat_print, "Warning: lwip.setsockopt() option not implemented\n");
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);
void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms) {
// Rather than waiting for the entire timeout specified, we wait sock->retries times
// for SOCKET_POLL_US each, checking for a MicroPython interrupt between timeouts.
// with SOCKET_POLL_MS == 100ms, sock->retries allows for timeouts up to 13 years.
// if timeout_ms == UINT64_MAX, wait forever.
sock->retries = (timeout_ms == UINT64_MAX) ? UINT_MAX : timeout_ms * 1000 / SOCKET_POLL_US;
struct timeval timeout = {
.tv_sec = 0,
.tv_usec = timeout_ms ? SOCKET_POLL_US : 0
};
lwip_setsockopt_r(sock->fd, SOL_SOCKET, SO_SNDTIMEO, (const void *)&timeout, sizeof(timeout));
lwip_setsockopt_r(sock->fd, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(timeout));
lwip_fcntl_r(sock->fd, F_SETFL, timeout_ms ? 0 : O_NONBLOCK);
}
STATIC mp_obj_t socket_settimeout(const mp_obj_t arg0, const mp_obj_t arg1) {
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
if (arg1 == mp_const_none) _socket_settimeout(self, UINT64_MAX);
else _socket_settimeout(self, mp_obj_get_float(arg1) * 1000L);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_settimeout_obj, socket_settimeout);
STATIC mp_obj_t socket_setblocking(const mp_obj_t arg0, const mp_obj_t arg1) {
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
if (mp_obj_is_true(arg1)) _socket_settimeout(self, UINT64_MAX);
else _socket_settimeout(self, 0);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
// XXX this can end up waiting a very long time if the content is dribbled in one character
// at a time, as the timeout resets each time a recvfrom succeeds ... this is probably not
// good behaviour.
STATIC mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size,
struct sockaddr *from, socklen_t *from_len, int *errcode) {
socket_obj_t *sock = MP_OBJ_TO_PTR(self_in);
// If the peer closed the connection then the lwIP socket API will only return "0" once
// from lwip_recvfrom_r and then block on subsequent calls. To emulate POSIX behaviour,
// which continues to return "0" for each call on a closed socket, we set a flag when
// the peer closed the socket.
if (sock->peer_closed) {
return 0;
}
// XXX Would be nicer to use RTC to handle timeouts
for (int i = 0; i <= sock->retries; ++i) {
MP_THREAD_GIL_EXIT();
int r = lwip_recvfrom_r(sock->fd, buf, size, 0, from, from_len);
MP_THREAD_GIL_ENTER();
if (r == 0) {
sock->peer_closed = true;
}
if (r >= 0) {
return r;
}
if (errno != EWOULDBLOCK) {
*errcode = errno;
return MP_STREAM_ERROR;
}
check_for_exceptions();
}
*errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT;
return MP_STREAM_ERROR;
}
mp_obj_t _socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in,
struct sockaddr *from, socklen_t *from_len) {
size_t len = mp_obj_get_int(len_in);
vstr_t vstr;
vstr_init_len(&vstr, len);
int errcode;
mp_uint_t ret = _socket_read_data(self_in, vstr.buf, len, from, from_len, &errcode);
if (ret == MP_STREAM_ERROR) {
exception_from_errno(errcode);
}
vstr.len = ret;
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
return _socket_recvfrom(self_in, len_in, NULL, NULL);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv);
STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
struct sockaddr from;
socklen_t fromlen = sizeof(from);
mp_obj_t tuple[2];
tuple[0] = _socket_recvfrom(self_in, len_in, &from, &fromlen);
uint8_t *ip = (uint8_t*)&((struct sockaddr_in*)&from)->sin_addr;
mp_uint_t port = lwip_ntohs(((struct sockaddr_in*)&from)->sin_port);
tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_BIG);
return mp_obj_new_tuple(2, tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom);
int _socket_send(socket_obj_t *sock, const char *data, size_t datalen) {
int sentlen = 0;
for (int i=0; i<=sock->retries && sentlen < datalen; i++) {
MP_THREAD_GIL_EXIT();
int r = lwip_write_r(sock->fd, data+sentlen, datalen-sentlen);
MP_THREAD_GIL_ENTER();
if (r < 0 && errno != EWOULDBLOCK) exception_from_errno(errno);
if (r > 0) sentlen += r;
check_for_exceptions();
}
if (sentlen == 0) mp_raise_OSError(MP_ETIMEDOUT);
return sentlen;
}
STATIC mp_obj_t socket_send(const mp_obj_t arg0, const mp_obj_t arg1) {
socket_obj_t *sock = MP_OBJ_TO_PTR(arg0);
mp_uint_t datalen;
const char *data = mp_obj_str_get_data(arg1, &datalen);
int r = _socket_send(sock, data, datalen);
return mp_obj_new_int(r);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send);
STATIC mp_obj_t socket_sendall(const mp_obj_t arg0, const mp_obj_t arg1) {
// XXX behaviour when nonblocking (see extmod/modlwip.c)
// XXX also timeout behaviour.
socket_obj_t *sock = MP_OBJ_TO_PTR(arg0);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg1, &bufinfo, MP_BUFFER_READ);
int r = _socket_send(sock, bufinfo.buf, bufinfo.len);
if (r < bufinfo.len) mp_raise_OSError(MP_ETIMEDOUT);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_sendall_obj, socket_sendall);
STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) {
socket_obj_t *self = MP_OBJ_TO_PTR(self_in);
// get the buffer to send
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ);
// create the destination address
struct sockaddr_in to;
to.sin_len = sizeof(to);
to.sin_family = AF_INET;
to.sin_port = lwip_htons(netutils_parse_inet_addr(addr_in, (uint8_t*)&to.sin_addr, NETUTILS_BIG));
// send the data
for (int i=0; i<=self->retries; i++) {
MP_THREAD_GIL_EXIT();
int ret = lwip_sendto_r(self->fd, bufinfo.buf, bufinfo.len, 0, (struct sockaddr*)&to, sizeof(to));
MP_THREAD_GIL_ENTER();
if (ret > 0) return mp_obj_new_int_from_uint(ret);
if (ret == -1 && errno != EWOULDBLOCK) {
exception_from_errno(errno);
}
check_for_exceptions();
}
mp_raise_OSError(MP_ETIMEDOUT);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto);
STATIC mp_obj_t socket_fileno(const mp_obj_t arg0) {
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
return mp_obj_new_int(self->fd);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_fileno_obj, socket_fileno);
STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) {
(void)n_args;
return args[0];
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 3, socket_makefile);
STATIC mp_uint_t socket_stream_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
return _socket_read_data(self_in, buf, size, NULL, NULL, errcode);
}
STATIC mp_uint_t socket_stream_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
socket_obj_t *sock = self_in;
for (int i=0; i<=sock->retries; i++) {
MP_THREAD_GIL_EXIT();
int r = lwip_write_r(sock->fd, buf, size);
MP_THREAD_GIL_ENTER();
if (r > 0) return r;
if (r < 0 && errno != EWOULDBLOCK) { *errcode = errno; return MP_STREAM_ERROR; }
check_for_exceptions();
}
*errcode = sock->retries == 0 ? MP_EWOULDBLOCK : MP_ETIMEDOUT;
return MP_STREAM_ERROR;
}
STATIC mp_uint_t socket_stream_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
socket_obj_t * socket = self_in;
if (request == MP_STREAM_POLL) {
fd_set rfds; FD_ZERO(&rfds);
fd_set wfds; FD_ZERO(&wfds);
fd_set efds; FD_ZERO(&efds);
struct timeval timeout = { .tv_sec = 0, .tv_usec = 0 };
if (arg & MP_STREAM_POLL_RD) FD_SET(socket->fd, &rfds);
if (arg & MP_STREAM_POLL_WR) FD_SET(socket->fd, &wfds);
if (arg & MP_STREAM_POLL_HUP) FD_SET(socket->fd, &efds);
int r = select((socket->fd)+1, &rfds, &wfds, &efds, &timeout);
if (r < 0) {
*errcode = MP_EIO;
return MP_STREAM_ERROR;
}
mp_uint_t ret = 0;
if (FD_ISSET(socket->fd, &rfds)) ret |= MP_STREAM_POLL_RD;
if (FD_ISSET(socket->fd, &wfds)) ret |= MP_STREAM_POLL_WR;
if (FD_ISSET(socket->fd, &efds)) ret |= MP_STREAM_POLL_HUP;
return ret;
} else if (request == MP_STREAM_CLOSE) {
if (socket->fd >= 0) {
#if MICROPY_PY_USOCKET_EVENTS
if (socket->events_callback != MP_OBJ_NULL) {
usocket_events_remove(socket);
socket->events_callback = MP_OBJ_NULL;
}
#endif
int ret = lwip_close_r(socket->fd);
if (ret != 0) {
*errcode = errno;
return MP_STREAM_ERROR;
}
socket->fd = -1;
}
return 0;
}
*errcode = MP_EINVAL;
return MP_STREAM_ERROR;
}
STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_stream_close_obj) },
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_stream_close_obj) },
{ MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) },
{ MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) },
{ MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) },
{ MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) },
{ MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) },
{ MP_ROM_QSTR(MP_QSTR_sendall), MP_ROM_PTR(&socket_sendall_obj) },
{ MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) },
{ MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) },
{ MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) },
{ MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) },
{ MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) },
{ MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
{ MP_ROM_QSTR(MP_QSTR_makefile), MP_ROM_PTR(&socket_makefile_obj) },
{ MP_ROM_QSTR(MP_QSTR_fileno), MP_ROM_PTR(&socket_fileno_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
};
STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
STATIC const mp_stream_p_t socket_stream_p = {
.read = socket_stream_read,
.write = socket_stream_write,
.ioctl = socket_stream_ioctl
};
STATIC const mp_obj_type_t socket_type = {
{ &mp_type_type },
.name = MP_QSTR_socket,
.protocol = &socket_stream_p,
.locals_dict = (mp_obj_t)&socket_locals_dict,
};
STATIC mp_obj_t get_socket(size_t n_args, const mp_obj_t *args) {
socket_obj_t *sock = m_new_obj_with_finaliser(socket_obj_t);
sock->base.type = &socket_type;
sock->domain = AF_INET;
sock->type = SOCK_STREAM;
sock->proto = 0;
sock->peer_closed = false;
if (n_args > 0) {
sock->domain = mp_obj_get_int(args[0]);
if (n_args > 1) {
sock->type = mp_obj_get_int(args[1]);
if (n_args > 2) {
sock->proto = mp_obj_get_int(args[2]);
}
}
}
sock->fd = lwip_socket(sock->domain, sock->type, sock->proto);
if (sock->fd < 0) {
exception_from_errno(errno);
}
_socket_settimeout(sock, UINT64_MAX);
return MP_OBJ_FROM_PTR(sock);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_socket_obj, 0, 3, get_socket);
STATIC mp_obj_t esp_socket_getaddrinfo(size_t n_args, const mp_obj_t *args) {
// TODO support additional args beyond the first two
struct addrinfo *res = NULL;
_socket_getaddrinfo2(args[0], args[1], &res);
mp_obj_t ret_list = mp_obj_new_list(0, NULL);
for (struct addrinfo *resi = res; resi; resi = resi->ai_next) {
mp_obj_t addrinfo_objs[5] = {
mp_obj_new_int(resi->ai_family),
mp_obj_new_int(resi->ai_socktype),
mp_obj_new_int(resi->ai_protocol),
mp_obj_new_str(resi->ai_canonname, strlen(resi->ai_canonname)),
mp_const_none
};
if (resi->ai_family == AF_INET) {
struct sockaddr_in *addr = (struct sockaddr_in *)resi->ai_addr;
// This looks odd, but it's really just a u32_t
ip4_addr_t ip4_addr = { .addr = addr->sin_addr.s_addr };
char buf[16];
ip4addr_ntoa_r(&ip4_addr, buf, sizeof(buf));
mp_obj_t inaddr_objs[2] = {
mp_obj_new_str(buf, strlen(buf)),
mp_obj_new_int(ntohs(addr->sin_port))
};
addrinfo_objs[4] = mp_obj_new_tuple(2, inaddr_objs);
}
mp_obj_list_append(ret_list, mp_obj_new_tuple(5, addrinfo_objs));
}
if (res) lwip_freeaddrinfo(res);
return ret_list;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_socket_getaddrinfo_obj, 2, 6, esp_socket_getaddrinfo);
STATIC mp_obj_t esp_socket_initialize() {
static int initialized = 0;
if (!initialized) {
ESP_LOGI("modsocket", "Initializing");
tcpip_adapter_init();
initialized = 1;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_socket_initialize_obj, esp_socket_initialize);
STATIC const mp_rom_map_elem_t mp_module_socket_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) },
{ MP_ROM_QSTR(MP_QSTR___init__), MP_ROM_PTR(&esp_socket_initialize_obj) },
{ MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&get_socket_obj) },
{ MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&esp_socket_getaddrinfo_obj) },
{ MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(AF_INET) },
{ MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(AF_INET6) },
{ MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(SOCK_STREAM) },
{ MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(SOCK_DGRAM) },
{ MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(SOCK_RAW) },
{ MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(IPPROTO_TCP) },
{ MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(IPPROTO_UDP) },
{ MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(IPPROTO_IP) },
{ MP_ROM_QSTR(MP_QSTR_SOL_SOCKET), MP_ROM_INT(SOL_SOCKET) },
{ MP_ROM_QSTR(MP_QSTR_SO_REUSEADDR), MP_ROM_INT(SO_REUSEADDR) },
{ MP_ROM_QSTR(MP_QSTR_IP_ADD_MEMBERSHIP), MP_ROM_INT(IP_ADD_MEMBERSHIP) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_socket_globals, mp_module_socket_globals_table);
const mp_obj_module_t mp_module_usocket = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&mp_module_socket_globals,
};

View File

@ -1,12 +0,0 @@
import gc
import uos
from flashbdev import bdev
try:
if bdev:
uos.mount(bdev, '/')
except OSError:
import inisetup
vfs = inisetup.setup()
gc.collect()

View File

@ -1,8 +0,0 @@
# APA106driver for MicroPython on ESP32
# MIT license; Copyright (c) 2016 Damien P. George
from neopixel import NeoPixel
class APA106(NeoPixel):
ORDER = (0, 1, 2, 3)

View File

@ -1 +0,0 @@
../../../drivers/dht/dht.py

View File

@ -1 +0,0 @@
../../esp8266/modules/ds18x20.py

View File

@ -1,34 +0,0 @@
import esp
class FlashBdev:
SEC_SIZE = 4096
START_SEC = esp.flash_user_start() // SEC_SIZE
def __init__(self, blocks):
self.blocks = blocks
def readblocks(self, n, buf):
#print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf)))
esp.flash_read((n + self.START_SEC) * self.SEC_SIZE, buf)
def writeblocks(self, n, buf):
#print("writeblocks(%s, %x(%d))" % (n, id(buf), len(buf)))
#assert len(buf) <= self.SEC_SIZE, len(buf)
esp.flash_erase(n + self.START_SEC)
esp.flash_write((n + self.START_SEC) * self.SEC_SIZE, buf)
def ioctl(self, op, arg):
#print("ioctl(%d, %r)" % (op, arg))
if op == 4: # BP_IOCTL_SEC_COUNT
return self.blocks
if op == 5: # BP_IOCTL_SEC_SIZE
return self.SEC_SIZE
size = esp.flash_size()
if size < 1024*1024:
# flash too small for a filesystem
bdev = None
else:
# for now we use a fixed size for the filesystem
bdev = FlashBdev(2048 * 1024 // FlashBdev.SEC_SIZE)

View File

@ -1,42 +0,0 @@
import uos
from flashbdev import bdev
def check_bootsec():
buf = bytearray(bdev.SEC_SIZE)
bdev.readblocks(0, buf)
empty = True
for b in buf:
if b != 0xff:
empty = False
break
if empty:
return True
fs_corrupted()
def fs_corrupted():
import time
while 1:
print("""\
FAT filesystem appears to be corrupted. If you had important data there, you
may want to make a flash snapshot to try to recover it. Otherwise, perform
factory reprogramming of MicroPython firmware (completely erase flash, followed
by firmware programming).
""")
time.sleep(3)
def setup():
check_bootsec()
print("Performing initial setup")
uos.VfsFat.mkfs(bdev)
vfs = uos.VfsFat(bdev)
uos.mount(vfs, '/flash')
uos.chdir('/flash')
with open("boot.py", "w") as f:
f.write("""\
# This file is executed on every boot (including wake-boot from deepsleep)
#import esp
#esp.osdebug(None)
#import webrepl
#webrepl.start()
""")
return vfs

View File

@ -1,33 +0,0 @@
# NeoPixel driver for MicroPython on ESP32
# MIT license; Copyright (c) 2016 Damien P. George
from esp import neopixel_write
class NeoPixel:
ORDER = (1, 0, 2, 3)
def __init__(self, pin, n, bpp=3, timing=0):
self.pin = pin
self.n = n
self.bpp = bpp
self.buf = bytearray(n * bpp)
self.pin.init(pin.OUT)
self.timing = timing
def __setitem__(self, index, val):
offset = index * self.bpp
for i in range(self.bpp):
self.buf[offset + self.ORDER[i]] = val[i]
def __getitem__(self, index):
offset = index * self.bpp
return tuple(self.buf[offset + self.ORDER[i]]
for i in range(self.bpp))
def fill(self, color):
for i in range(self.n):
self[i] = color
def write(self):
neopixel_write(self.pin, self.buf, self.timing)

View File

@ -1 +0,0 @@
../../esp8266/modules/ntptime.py

View File

@ -1 +0,0 @@
../../esp8266/modules/onewire.py

View File

@ -1 +0,0 @@
../../../../../micropython-lib/umqtt.robust/umqtt/robust.py

View File

@ -1 +0,0 @@
../../../../../micropython-lib/umqtt.simple/umqtt/simple.py

View File

@ -1 +0,0 @@
../../../tools/upip.py

View File

@ -1 +0,0 @@
../../../tools/upip_utarfile.py

View File

@ -1 +0,0 @@
../../../../micropython-lib/upysh/upysh.py

View File

@ -1 +0,0 @@
../../../../micropython-lib/urequests/urequests.py

View File

@ -1 +0,0 @@
../../esp8266/modules/webrepl.py

View File

@ -1 +0,0 @@
../../esp8266/modules/webrepl_setup.py

View File

@ -1 +0,0 @@
../../esp8266/modules/websocket_helper.py

View File

@ -1,134 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2015 Josef Gajdusek
* Copyright (c) 2016 Damien P. George
*
* 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.
*/
#include <string.h>
#include "esp_system.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "extmod/misc.h"
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
#include "genhdr/mpversion.h"
extern const mp_obj_type_t mp_fat_vfs_type;
STATIC const qstr os_uname_info_fields[] = {
MP_QSTR_sysname, MP_QSTR_nodename,
MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine
};
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM);
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM);
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, MICROPY_VERSION_STRING);
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE);
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
STATIC MP_DEFINE_ATTRTUPLE(
os_uname_info_obj,
os_uname_info_fields,
5,
(mp_obj_t)&os_uname_info_sysname_obj,
(mp_obj_t)&os_uname_info_nodename_obj,
(mp_obj_t)&os_uname_info_release_obj,
(mp_obj_t)&os_uname_info_version_obj,
(mp_obj_t)&os_uname_info_machine_obj
);
STATIC mp_obj_t os_uname(void) {
return (mp_obj_t)&os_uname_info_obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname);
STATIC mp_obj_t os_urandom(mp_obj_t num) {
mp_int_t n = mp_obj_get_int(num);
vstr_t vstr;
vstr_init_len(&vstr, n);
uint32_t r = 0;
for (int i = 0; i < n; i++) {
if ((i & 3) == 0) {
r = esp_random(); // returns 32-bit hardware random number
}
vstr.buf[i] = r;
r >>= 8;
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
#if MICROPY_PY_OS_DUPTERM
STATIC mp_obj_t os_dupterm_notify(mp_obj_t obj_in) {
(void)obj_in;
for (;;) {
int c = mp_uos_dupterm_rx_chr();
if (c < 0) {
break;
}
ringbuf_put(&stdin_ringbuf, c);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_dupterm_notify_obj, os_dupterm_notify);
#endif
STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },
{ MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) },
{ MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) },
#if MICROPY_PY_OS_DUPTERM
{ MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) },
{ MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&os_dupterm_notify_obj) },
#endif
#if MICROPY_VFS
{ MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) },
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) },
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) },
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) },
{ MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) },
{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) },
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) },
#if MICROPY_VFS_FAT
{ MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
#endif
#endif
};
STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
const mp_obj_module_t uos_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&os_module_globals,
};

View File

@ -1,106 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* 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.
*/
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include "py/runtime.h"
#include "lib/timeutils/timeutils.h"
#include "extmod/utime_mphal.h"
STATIC mp_obj_t time_localtime(size_t n_args, const mp_obj_t *args) {
timeutils_struct_time_t tm;
mp_int_t seconds;
if (n_args == 0 || args[0] == mp_const_none) {
struct timeval tv;
gettimeofday(&tv, NULL);
seconds = tv.tv_sec;
} else {
seconds = mp_obj_get_int(args[0]);
}
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
mp_obj_t tuple[8] = {
tuple[0] = mp_obj_new_int(tm.tm_year),
tuple[1] = mp_obj_new_int(tm.tm_mon),
tuple[2] = mp_obj_new_int(tm.tm_mday),
tuple[3] = mp_obj_new_int(tm.tm_hour),
tuple[4] = mp_obj_new_int(tm.tm_min),
tuple[5] = mp_obj_new_int(tm.tm_sec),
tuple[6] = mp_obj_new_int(tm.tm_wday),
tuple[7] = mp_obj_new_int(tm.tm_yday),
};
return mp_obj_new_tuple(8, tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
size_t len;
mp_obj_t *elem;
mp_obj_get_array(tuple, &len, &elem);
// localtime generates a tuple of len 8. CPython uses 9, so we accept both.
if (len < 8 || len > 9) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "mktime needs a tuple of length 8 or 9 (%d given)", len));
}
return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]),
mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]),
mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5])));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime);
STATIC mp_obj_t time_time(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
return mp_obj_new_int(tv.tv_sec);
}
MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
STATIC const mp_rom_map_elem_t time_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) },
{ MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) },
{ MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) },
{ MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) },
{ MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) },
{ MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) },
{ MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) },
{ MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) },
{ MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) },
{ MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) },
{ MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) },
{ MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) },
};
STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);
const mp_obj_module_t utime_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&time_module_globals,
};

View File

@ -1,268 +0,0 @@
// Options to control how MicroPython is built for this port,
// overriding defaults in py/mpconfig.h.
#include <stdint.h>
#include <alloca.h>
#include "rom/ets_sys.h"
// object representation and NLR handling
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A)
#define MICROPY_NLR_SETJMP (1)
// memory allocation policies
#define MICROPY_ALLOC_PATH_MAX (128)
// emitters
#define MICROPY_PERSISTENT_CODE_LOAD (1)
// compiler configuration
#define MICROPY_COMP_MODULE_CONST (1)
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1)
// optimisations
#define MICROPY_OPT_COMPUTED_GOTO (1)
#define MICROPY_OPT_MPZ_BITWISE (1)
// Python internal features
#define MICROPY_READER_VFS (1)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_ENABLE_FINALISER (1)
#define MICROPY_STACK_CHECK (1)
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
#define MICROPY_KBD_EXCEPTION (1)
#define MICROPY_HELPER_REPL (1)
#define MICROPY_REPL_EMACS_KEYS (1)
#define MICROPY_REPL_AUTO_INDENT (1)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
#define MICROPY_ENABLE_SOURCE_LINE (1)
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL)
#define MICROPY_WARNINGS (1)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
#define MICROPY_PY_BUILTINS_COMPLEX (1)
#define MICROPY_CPYTHON_COMPAT (1)
#define MICROPY_STREAMS_NON_BLOCK (1)
#define MICROPY_STREAMS_POSIX_API (1)
#define MICROPY_MODULE_BUILTIN_INIT (1)
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_MODULE_FROZEN_STR (0)
#define MICROPY_MODULE_FROZEN_MPY (1)
#define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
#define MICROPY_USE_INTERNAL_ERRNO (1)
#define MICROPY_USE_INTERNAL_PRINTF (0) // ESP32 SDK requires its own printf
#define MICROPY_ENABLE_SCHEDULER (1)
#define MICROPY_SCHEDULER_DEPTH (8)
#define MICROPY_VFS (1)
#define MICROPY_VFS_FAT (1)
// control over Python builtins
#define MICROPY_PY_FUNCTION_ATTRS (1)
#define MICROPY_PY_DESCRIPTORS (1)
#define MICROPY_PY_STR_BYTES_CMP_WARN (1)
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
#define MICROPY_PY_BUILTINS_STR_CENTER (1)
#define MICROPY_PY_BUILTINS_STR_PARTITION (1)
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1)
#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
#define MICROPY_PY_BUILTINS_SET (1)
#define MICROPY_PY_BUILTINS_SLICE (1)
#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1)
#define MICROPY_PY_BUILTINS_FROZENSET (1)
#define MICROPY_PY_BUILTINS_PROPERTY (1)
#define MICROPY_PY_BUILTINS_RANGE_ATTRS (1)
#define MICROPY_PY_BUILTINS_ROUND_INT (1)
#define MICROPY_PY_BUILTINS_TIMEOUTERROR (1)
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
#define MICROPY_PY_BUILTINS_COMPILE (1)
#define MICROPY_PY_BUILTINS_ENUMERATE (1)
#define MICROPY_PY_BUILTINS_EXECFILE (1)
#define MICROPY_PY_BUILTINS_FILTER (1)
#define MICROPY_PY_BUILTINS_REVERSED (1)
#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1)
#define MICROPY_PY_BUILTINS_INPUT (1)
#define MICROPY_PY_BUILTINS_MIN_MAX (1)
#define MICROPY_PY_BUILTINS_POW3 (1)
#define MICROPY_PY_BUILTINS_HELP (1)
#define MICROPY_PY_BUILTINS_HELP_TEXT esp32_help_text
#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
#define MICROPY_PY___FILE__ (1)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
#define MICROPY_PY_ARRAY (1)
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
#define MICROPY_PY_ATTRTUPLE (1)
#define MICROPY_PY_COLLECTIONS (1)
#define MICROPY_PY_COLLECTIONS_DEQUE (1)
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
#define MICROPY_PY_MATH (1)
#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1)
#define MICROPY_PY_CMATH (1)
#define MICROPY_PY_GC (1)
#define MICROPY_PY_IO (1)
#define MICROPY_PY_IO_IOBASE (1)
#define MICROPY_PY_IO_FILEIO (1)
#define MICROPY_PY_IO_BYTESIO (1)
#define MICROPY_PY_IO_BUFFEREDWRITER (1)
#define MICROPY_PY_STRUCT (1)
#define MICROPY_PY_SYS (1)
#define MICROPY_PY_SYS_MAXSIZE (1)
#define MICROPY_PY_SYS_MODULES (1)
#define MICROPY_PY_SYS_EXIT (1)
#define MICROPY_PY_SYS_STDFILES (1)
#define MICROPY_PY_SYS_STDIO_BUFFER (1)
#define MICROPY_PY_UERRNO (1)
#define MICROPY_PY_USELECT (1)
#define MICROPY_PY_UTIME_MP_HAL (1)
#define MICROPY_PY_THREAD (1)
#define MICROPY_PY_THREAD_GIL (1)
#define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32)
// extended modules
#define MICROPY_PY_UCTYPES (1)
#define MICROPY_PY_UZLIB (1)
#define MICROPY_PY_UJSON (1)
#define MICROPY_PY_URE (1)
#define MICROPY_PY_UHEAPQ (1)
#define MICROPY_PY_UTIMEQ (1)
#define MICROPY_PY_UHASHLIB (1)
#define MICROPY_PY_UHASHLIB_SHA1 (1)
#define MICROPY_PY_UHASHLIB_SHA256 (1)
#define MICROPY_PY_UBINASCII (1)
#define MICROPY_PY_UBINASCII_CRC32 (1)
#define MICROPY_PY_URANDOM (1)
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
#define MICROPY_PY_OS_DUPTERM (1)
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MICROPY_PY_MACHINE_PULSE (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_SPI (1)
#define MICROPY_PY_MACHINE_SPI_MSB (0)
#define MICROPY_PY_MACHINE_SPI_LSB (1)
#define MICROPY_PY_MACHINE_SPI_MAKE_NEW machine_hw_spi_make_new
#define MICROPY_HW_SOFTSPI_MIN_DELAY (0)
#define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (ets_get_cpu_frequency() * 1000000 / 200) // roughly
#define MICROPY_PY_USSL (1)
#define MICROPY_SSL_MBEDTLS (1)
#define MICROPY_PY_USSL_FINALISER (1)
#define MICROPY_PY_WEBSOCKET (1)
#define MICROPY_PY_WEBREPL (1)
#define MICROPY_PY_FRAMEBUF (1)
#define MICROPY_PY_USOCKET_EVENTS (MICROPY_PY_WEBREPL)
// fatfs configuration
#define MICROPY_FATFS_ENABLE_LFN (1)
#define MICROPY_FATFS_RPATH (2)
#define MICROPY_FATFS_MAX_SS (4096)
#define MICROPY_FATFS_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
#define mp_type_fileio mp_type_vfs_fat_fileio
#define mp_type_textio mp_type_vfs_fat_textio
// use vfs's functions for import stat and builtin open
#define mp_import_stat mp_vfs_import_stat
#define mp_builtin_open mp_vfs_open
#define mp_builtin_open_obj mp_vfs_open_obj
// extra built in names to add to the global namespace
#define MICROPY_PORT_BUILTINS \
{ MP_OBJ_NEW_QSTR(MP_QSTR_input), (mp_obj_t)&mp_builtin_input_obj }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
// extra built in modules to add to the list of known ones
extern const struct _mp_obj_module_t esp_module;
extern const struct _mp_obj_module_t esp32_module;
extern const struct _mp_obj_module_t utime_module;
extern const struct _mp_obj_module_t uos_module;
extern const struct _mp_obj_module_t mp_module_usocket;
extern const struct _mp_obj_module_t mp_module_machine;
extern const struct _mp_obj_module_t mp_module_network;
extern const struct _mp_obj_module_t mp_module_onewire;
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_esp32), (mp_obj_t)&esp32_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&utime_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&uos_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR__onewire), (mp_obj_t)&mp_module_onewire }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \
#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
{ MP_OBJ_NEW_QSTR(MP_QSTR_binascii), (mp_obj_t)&mp_module_ubinascii }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_collections), (mp_obj_t)&mp_module_collections }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_errno), (mp_obj_t)&mp_module_uerrno }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_hashlib), (mp_obj_t)&mp_module_uhashlib }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_heapq), (mp_obj_t)&mp_module_uheapq }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_io), (mp_obj_t)&mp_module_io }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&uos_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&mp_module_urandom }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_re), (mp_obj_t)&mp_module_ure }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_select), (mp_obj_t)&mp_module_uselect }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&mp_module_usocket }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_ssl), (mp_obj_t)&mp_module_ussl }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&mp_module_ustruct }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&utime_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_zlib), (mp_obj_t)&mp_module_uzlib }, \
#define MP_STATE_PORT MP_STATE_VM
#define MICROPY_PORT_ROOT_POINTERS \
const char *readline_hist[8]; \
mp_obj_t machine_pin_irq_handler[40]; \
// type definitions for the specific machine
#define BYTES_PER_WORD (4)
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p)))
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
#define MP_SSIZE_MAX (0x7fffffff)
// Note: these "critical nested" macros do not ensure cross-CPU exclusion,
// the only disable interrupts on the current CPU. To full manage exclusion
// one should use portENTER_CRITICAL/portEXIT_CRITICAL instead.
#include "freertos/FreeRTOS.h"
#define MICROPY_BEGIN_ATOMIC_SECTION() portENTER_CRITICAL_NESTED()
#define MICROPY_END_ATOMIC_SECTION(state) portEXIT_CRITICAL_NESTED(state)
#if MICROPY_PY_USOCKET_EVENTS
#define MICROPY_PY_USOCKET_EVENTS_HANDLER extern void usocket_events_handler(void); usocket_events_handler();
#else
#define MICROPY_PY_USOCKET_EVENTS_HANDLER
#endif
#if MICROPY_PY_THREAD
#define MICROPY_EVENT_POLL_HOOK \
do { \
extern void mp_handle_pending(void); \
mp_handle_pending(); \
MICROPY_PY_USOCKET_EVENTS_HANDLER \
MP_THREAD_GIL_EXIT(); \
MP_THREAD_GIL_ENTER(); \
} while (0);
#else
#define MICROPY_EVENT_POLL_HOOK \
do { \
extern void mp_handle_pending(void); \
mp_handle_pending(); \
MICROPY_PY_USOCKET_EVENTS_HANDLER \
asm("waiti 0"); \
} while (0);
#endif
#define UINT_FMT "%u"
#define INT_FMT "%d"
typedef int32_t mp_int_t; // must be pointer size
typedef uint32_t mp_uint_t; // must be pointer size
typedef long mp_off_t;
// ssize_t, off_t as required by POSIX-signatured functions in stream.h
#include <sys/types.h>
// board specifics
#define MICROPY_HW_BOARD_NAME "ESP32 module"
#define MICROPY_HW_MCU_NAME "ESP32"
#define MICROPY_PY_SYS_PLATFORM "esp32"

View File

@ -1,156 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Damien P. George
*
* 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.
*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "rom/uart.h"
#include "py/obj.h"
#include "py/mpstate.h"
#include "py/mphal.h"
#include "extmod/misc.h"
#include "lib/utils/pyexec.h"
STATIC uint8_t stdin_ringbuf_array[256];
ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array)};
int mp_hal_stdin_rx_chr(void) {
for (;;) {
int c = ringbuf_get(&stdin_ringbuf);
if (c != -1) {
return c;
}
MICROPY_EVENT_POLL_HOOK
vTaskDelay(1);
}
}
void mp_hal_stdout_tx_str(const char *str) {
mp_hal_stdout_tx_strn(str, strlen(str));
}
void mp_hal_stdout_tx_strn(const char *str, uint32_t len) {
MP_THREAD_GIL_EXIT();
for (uint32_t i = 0; i < len; ++i) {
uart_tx_one_char(str[i]);
}
MP_THREAD_GIL_ENTER();
mp_uos_dupterm_tx_strn(str, len);
}
// Efficiently convert "\n" to "\r\n"
void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {
const char *last = str;
while (len--) {
if (*str == '\n') {
if (str > last) {
mp_hal_stdout_tx_strn(last, str - last);
}
mp_hal_stdout_tx_strn("\r\n", 2);
++str;
last = str;
} else {
++str;
}
}
if (str > last) {
mp_hal_stdout_tx_strn(last, str - last);
}
}
uint32_t mp_hal_ticks_ms(void) {
return esp_timer_get_time() / 1000;
}
uint32_t mp_hal_ticks_us(void) {
return esp_timer_get_time();
}
void mp_hal_delay_ms(uint32_t ms) {
uint64_t us = ms * 1000;
uint64_t dt;
uint64_t t0 = esp_timer_get_time();
for (;;) {
uint64_t t1 = esp_timer_get_time();
dt = t1 - t0;
if (dt + portTICK_PERIOD_MS * 1000 >= us) {
// doing a vTaskDelay would take us beyond requested delay time
break;
}
MICROPY_EVENT_POLL_HOOK
vTaskDelay(1);
}
if (dt < us) {
// do the remaining delay accurately
mp_hal_delay_us(us - dt);
}
}
void mp_hal_delay_us(uint32_t us) {
// these constants are tested for a 240MHz clock
const uint32_t this_overhead = 5;
const uint32_t pend_overhead = 150;
// return if requested delay is less than calling overhead
if (us < this_overhead) {
return;
}
us -= this_overhead;
uint64_t t0 = esp_timer_get_time();
for (;;) {
uint64_t dt = esp_timer_get_time() - t0;
if (dt >= us) {
return;
}
if (dt + pend_overhead < us) {
// we have enough time to service pending events
// (don't use MICROPY_EVENT_POLL_HOOK because it also yields)
mp_handle_pending();
}
}
}
// this function could do with improvements (eg use ets_delay_us)
void mp_hal_delay_us_fast(uint32_t us) {
uint32_t delay = ets_get_cpu_frequency() / 19;
while (--us) {
for (volatile uint32_t i = delay; i; --i) {
}
}
}
/*
extern int mp_stream_errno;
int *__errno() {
return &mp_stream_errno;
}
*/

View File

@ -1,86 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef INCLUDED_MPHALPORT_H
#define INCLUDED_MPHALPORT_H
#include "py/ringbuf.h"
#include "lib/utils/interrupt_char.h"
extern ringbuf_t stdin_ringbuf;
uint32_t mp_hal_ticks_us(void);
__attribute__((always_inline)) static inline uint32_t mp_hal_ticks_cpu(void) {
uint32_t ccount;
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
return ccount;
}
void mp_hal_delay_us(uint32_t);
void mp_hal_delay_us_fast(uint32_t);
void mp_hal_set_interrupt_char(int c);
uint32_t mp_hal_get_cpu_freq(void);
#define mp_hal_quiet_timing_enter() MICROPY_BEGIN_ATOMIC_SECTION()
#define mp_hal_quiet_timing_exit(irq_state) MICROPY_END_ATOMIC_SECTION(irq_state)
// C-level pin HAL
#include "py/obj.h"
#include "driver/gpio.h"
#define MP_HAL_PIN_FMT "%u"
#define mp_hal_pin_obj_t gpio_num_t
mp_hal_pin_obj_t machine_pin_get_id(mp_obj_t pin_in);
#define mp_hal_get_pin_obj(o) machine_pin_get_id(o)
#define mp_obj_get_pin(o) machine_pin_get_id(o) // legacy name; only to support esp8266/modonewire
#define mp_hal_pin_name(p) (p)
static inline void mp_hal_pin_input(mp_hal_pin_obj_t pin) {
gpio_pad_select_gpio(pin);
gpio_set_direction(pin, GPIO_MODE_INPUT);
}
static inline void mp_hal_pin_output(mp_hal_pin_obj_t pin) {
gpio_pad_select_gpio(pin);
gpio_set_direction(pin, GPIO_MODE_INPUT_OUTPUT);
}
static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin) {
gpio_pad_select_gpio(pin);
gpio_set_direction(pin, GPIO_MODE_INPUT_OUTPUT_OD);
}
static inline void mp_hal_pin_od_low(mp_hal_pin_obj_t pin) {
gpio_set_level(pin, 0);
}
static inline void mp_hal_pin_od_high(mp_hal_pin_obj_t pin) {
gpio_set_level(pin, 1);
}
static inline int mp_hal_pin_read(mp_hal_pin_obj_t pin) {
return gpio_get_level(pin);
}
static inline void mp_hal_pin_write(mp_hal_pin_obj_t pin, int v) {
gpio_set_level(pin, v);
}
#endif // INCLUDED_MPHALPORT_H

View File

@ -1,226 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd
* Copyright (c) 2017 Pycom Limited
*
* 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.
*/
#include "stdio.h"
#include "py/mpconfig.h"
#include "py/mpstate.h"
#include "py/gc.h"
#include "py/mpthread.h"
#include "mpthreadport.h"
#include "esp_task.h"
#if MICROPY_PY_THREAD
#define MP_THREAD_MIN_STACK_SIZE (4 * 1024)
#define MP_THREAD_DEFAULT_STACK_SIZE (MP_THREAD_MIN_STACK_SIZE + 1024)
#define MP_THREAD_PRIORITY (ESP_TASK_PRIO_MIN + 1)
// this structure forms a linked list, one node per active thread
typedef struct _thread_t {
TaskHandle_t id; // system id of thread
int ready; // whether the thread is ready and running
void *arg; // thread Python args, a GC root pointer
void *stack; // pointer to the stack
StaticTask_t *tcb; // pointer to the Task Control Block
size_t stack_len; // number of words in the stack
struct _thread_t *next;
} thread_t;
// the mutex controls access to the linked list
STATIC mp_thread_mutex_t thread_mutex;
STATIC thread_t thread_entry0;
STATIC thread_t *thread; // root pointer, handled by mp_thread_gc_others
void mp_thread_init(void *stack, uint32_t stack_len) {
mp_thread_set_state(&mp_state_ctx.thread);
// create the first entry in the linked list of all threads
thread = &thread_entry0;
thread->id = xTaskGetCurrentTaskHandle();
thread->ready = 1;
thread->arg = NULL;
thread->stack = stack;
thread->stack_len = stack_len;
thread->next = NULL;
mp_thread_mutex_init(&thread_mutex);
}
void mp_thread_gc_others(void) {
mp_thread_mutex_lock(&thread_mutex, 1);
for (thread_t *th = thread; th != NULL; th = th->next) {
gc_collect_root((void**)&th, 1);
gc_collect_root(&th->arg, 1); // probably not needed
if (th->id == xTaskGetCurrentTaskHandle()) {
continue;
}
if (!th->ready) {
continue;
}
gc_collect_root(th->stack, th->stack_len); // probably not needed
}
mp_thread_mutex_unlock(&thread_mutex);
}
mp_state_thread_t *mp_thread_get_state(void) {
return pvTaskGetThreadLocalStoragePointer(NULL, 1);
}
void mp_thread_set_state(void *state) {
vTaskSetThreadLocalStoragePointer(NULL, 1, state);
}
void mp_thread_start(void) {
mp_thread_mutex_lock(&thread_mutex, 1);
for (thread_t *th = thread; th != NULL; th = th->next) {
if (th->id == xTaskGetCurrentTaskHandle()) {
th->ready = 1;
break;
}
}
mp_thread_mutex_unlock(&thread_mutex);
}
STATIC void *(*ext_thread_entry)(void*) = NULL;
STATIC void freertos_entry(void *arg) {
if (ext_thread_entry) {
ext_thread_entry(arg);
}
vTaskDelete(NULL);
for (;;);
}
void mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *stack_size, int priority, char *name) {
// store thread entry function into a global variable so we can access it
ext_thread_entry = entry;
if (*stack_size == 0) {
*stack_size = MP_THREAD_DEFAULT_STACK_SIZE; // default stack size
} else if (*stack_size < MP_THREAD_MIN_STACK_SIZE) {
*stack_size = MP_THREAD_MIN_STACK_SIZE; // minimum stack size
}
// allocate TCB, stack and linked-list node (must be outside thread_mutex lock)
StaticTask_t *tcb = m_new(StaticTask_t, 1);
StackType_t *stack = m_new(StackType_t, *stack_size / sizeof(StackType_t));
thread_t *th = m_new_obj(thread_t);
mp_thread_mutex_lock(&thread_mutex, 1);
// create thread
TaskHandle_t id = xTaskCreateStaticPinnedToCore(freertos_entry, name, *stack_size / sizeof(StackType_t), arg, priority, stack, tcb, 0);
if (id == NULL) {
mp_thread_mutex_unlock(&thread_mutex);
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread"));
}
// adjust the stack_size to provide room to recover from hitting the limit
*stack_size -= 1024;
// add thread to linked list of all threads
th->id = id;
th->ready = 0;
th->arg = arg;
th->stack = stack;
th->tcb = tcb;
th->stack_len = *stack_size / sizeof(StackType_t);
th->next = thread;
thread = th;
mp_thread_mutex_unlock(&thread_mutex);
}
void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
mp_thread_create_ex(entry, arg, stack_size, MP_THREAD_PRIORITY, "mp_thread");
}
void mp_thread_finish(void) {
mp_thread_mutex_lock(&thread_mutex, 1);
for (thread_t *th = thread; th != NULL; th = th->next) {
if (th->id == xTaskGetCurrentTaskHandle()) {
th->ready = 0;
break;
}
}
mp_thread_mutex_unlock(&thread_mutex);
}
void vPortCleanUpTCB(void *tcb) {
thread_t *prev = NULL;
mp_thread_mutex_lock(&thread_mutex, 1);
for (thread_t *th = thread; th != NULL; prev = th, th = th->next) {
// unlink the node from the list
if (th->tcb == tcb) {
if (prev != NULL) {
prev->next = th->next;
} else {
// move the start pointer
thread = th->next;
}
// explicitly release all its memory
m_del(StaticTask_t, th->tcb, 1);
m_del(StackType_t, th->stack, th->stack_len);
m_del(thread_t, th, 1);
break;
}
}
mp_thread_mutex_unlock(&thread_mutex);
}
void mp_thread_mutex_init(mp_thread_mutex_t *mutex) {
mutex->handle = xSemaphoreCreateMutexStatic(&mutex->buffer);
}
int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) {
return (pdTRUE == xSemaphoreTake(mutex->handle, wait ? portMAX_DELAY : 0));
}
void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) {
xSemaphoreGive(mutex->handle);
}
void mp_thread_deinit(void) {
mp_thread_mutex_lock(&thread_mutex, 1);
for (thread_t *th = thread; th != NULL; th = th->next) {
// don't delete the current task
if (th->id == xTaskGetCurrentTaskHandle()) {
continue;
}
vTaskDelete(th->id);
}
mp_thread_mutex_unlock(&thread_mutex);
// allow FreeRTOS to clean-up the threads
vTaskDelay(2);
}
#else
void vPortCleanUpTCB(void *tcb) {
}
#endif // MICROPY_PY_THREAD

View File

@ -1,45 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd
* Copyright (c) 2017 Pycom Limited
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESP32_MPTHREADPORT_H
#define MICROPY_INCLUDED_ESP32_MPTHREADPORT_H
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
typedef struct _mp_thread_mutex_t {
SemaphoreHandle_t handle;
StaticSemaphore_t buffer;
} mp_thread_mutex_t;
void mp_thread_init(void *stack, uint32_t stack_len);
void mp_thread_gc_others(void);
void mp_thread_deinit(void);
#endif // MICROPY_INCLUDED_ESP32_MPTHREADPORT_H

View File

@ -1,203 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2017 "Eric Poulsen" <eric@zyxod.com>
*
* Based on the ESP IDF example code which is Public Domain / CC0
*
* 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.
*/
#include "py/runtime.h"
#include "py/mphal.h"
#include "eth_phy/phy.h"
#include "eth_phy/phy_tlk110.h"
#include "eth_phy/phy_lan8720.h"
#include "tcpip_adapter.h"
#include "modnetwork.h"
typedef struct _lan_if_obj_t {
mp_obj_base_t base;
int if_id; // MUST BE FIRST to match wlan_if_obj_t
bool initialized;
bool active;
uint8_t mdc_pin;
uint8_t mdio_pin;
int8_t phy_power_pin;
uint8_t phy_addr;
uint8_t phy_type;
eth_phy_check_link_func link_func;
eth_phy_power_enable_func power_func;
} lan_if_obj_t;
const mp_obj_type_t lan_if_type;
STATIC lan_if_obj_t lan_obj = {{&lan_if_type}, ESP_IF_ETH, false, false};
STATIC void phy_power_enable(bool enable) {
lan_if_obj_t* self = &lan_obj;
if (self->phy_power_pin != -1) {
if (!enable) {
// Do the PHY-specific power_enable(false) function before powering down
self->power_func(false);
}
gpio_pad_select_gpio(self->phy_power_pin);
gpio_set_direction(self->phy_power_pin, GPIO_MODE_OUTPUT);
if (enable) {
gpio_set_level(self->phy_power_pin, 1);
} else {
gpio_set_level(self->phy_power_pin, 0);
}
// Allow the power up/down to take effect, min 300us
vTaskDelay(1);
if (enable) {
// Run the PHY-specific power on operations now the PHY has power
self->power_func(true);
}
}
}
STATIC void init_lan_rmii() {
lan_if_obj_t* self = &lan_obj;
phy_rmii_configure_data_interface_pins();
phy_rmii_smi_configure_pins(self->mdc_pin, self->mdio_pin);
}
STATIC mp_obj_t get_lan(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
lan_if_obj_t* self = &lan_obj;
if (self->initialized) {
return MP_OBJ_FROM_PTR(&lan_obj);
}
enum { ARG_id, ARG_mdc, ARG_mdio, ARG_power, ARG_phy_addr, ARG_phy_type };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_mdc, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_mdio, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_power, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_phy_addr, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_phy_type, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
if (args[ARG_id].u_obj != mp_const_none) {
if (mp_obj_get_int(args[ARG_id].u_obj) != 0) {
mp_raise_ValueError("invalid LAN interface identifier");
}
}
self->mdc_pin = machine_pin_get_id(args[ARG_mdc].u_obj);
self->mdio_pin = machine_pin_get_id(args[ARG_mdio].u_obj);
self->phy_power_pin = args[ARG_power].u_obj == mp_const_none ? -1 : machine_pin_get_id(args[ARG_power].u_obj);
if (args[ARG_phy_addr].u_int < 0x00 || args[ARG_phy_addr].u_int > 0x1f) {
mp_raise_ValueError("invalid phy address");
}
if (args[ARG_phy_type].u_int != PHY_LAN8720 && args[ARG_phy_type].u_int != PHY_TLK110) {
mp_raise_ValueError("invalid phy type");
}
eth_config_t config;
switch (args[ARG_phy_type].u_int) {
case PHY_TLK110:
config = phy_tlk110_default_ethernet_config;
break;
case PHY_LAN8720:
config = phy_lan8720_default_ethernet_config;
break;
}
self->link_func = config.phy_check_link;
// Replace default power func with our own
self->power_func = config.phy_power_enable;
config.phy_power_enable = phy_power_enable;
config.phy_addr = args[ARG_phy_addr].u_int;
config.gpio_config = init_lan_rmii;
config.tcpip_input = tcpip_adapter_eth_input;
if (esp_eth_init(&config) == ESP_OK) {
self->active = false;
self->initialized = true;
} else {
mp_raise_msg(&mp_type_OSError, "esp_eth_init() failed");
}
return MP_OBJ_FROM_PTR(&lan_obj);
}
MP_DEFINE_CONST_FUN_OBJ_KW(get_lan_obj, 0, get_lan);
STATIC mp_obj_t lan_active(size_t n_args, const mp_obj_t *args) {
lan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (n_args > 1) {
if (mp_obj_is_true(args[1])) {
self->active = (esp_eth_enable() == ESP_OK);
if (!self->active) {
mp_raise_msg(&mp_type_OSError, "ethernet enable failed");
}
} else {
self->active = !(esp_eth_disable() == ESP_OK);
if (self->active) {
mp_raise_msg(&mp_type_OSError, "ethernet disable failed");
}
}
}
return mp_obj_new_bool(self->active);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lan_active_obj, 1, 2, lan_active);
STATIC mp_obj_t lan_status(mp_obj_t self_in) {
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_status_obj, lan_status);
STATIC mp_obj_t lan_isconnected(mp_obj_t self_in) {
lan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
return self->active ? mp_obj_new_bool(self->link_func()) : mp_const_false;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(lan_isconnected_obj, lan_isconnected);
STATIC const mp_rom_map_elem_t lan_if_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&lan_active_obj) },
{ MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&lan_isconnected_obj) },
{ MP_ROM_QSTR(MP_QSTR_status), MP_ROM_PTR(&lan_status_obj) },
{ MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&esp_ifconfig_obj) },
};
STATIC MP_DEFINE_CONST_DICT(lan_if_locals_dict, lan_if_locals_dict_table);
const mp_obj_type_t lan_if_type = {
{ &mp_type_type },
.name = MP_QSTR_LAN,
.locals_dict = (mp_obj_dict_t*)&lan_if_locals_dict,
};

View File

@ -1,5 +0,0 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 0x180000,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
3 nvs, data, nvs, 0x9000, 0x6000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 0x180000,

View File

@ -1,30 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Damien P. George
*
* 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.
*/
// qstrs specific to this port, only needed if they aren't auto-generated
// Entries for sys.path
Q(/lib)

View File

@ -1,191 +0,0 @@
/* Start bootloader config */
#define CONFIG_FLASHMODE_DIO 1
#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1
/* End bootloader config */
#define CONFIG_TRACEMEM_RESERVE_DRAM 0x0
#define CONFIG_BT_RESERVE_DRAM 0x0
#define CONFIG_ULP_COPROC_RESERVE_MEM 2040
#define CONFIG_PHY_DATA_OFFSET 0xf000
#define CONFIG_APP_OFFSET 0x10000
#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1
#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS 1
#define CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS 4
#define CONFIG_BROWNOUT_DET 1
#define CONFIG_BROWNOUT_DET_LVL 0
#define CONFIG_BROWNOUT_DET_LVL_SEL_0 1
#define CONFIG_TCPIP_TASK_STACK_SIZE 2560
#define CONFIG_TCPIP_RECVMBOX_SIZE 32
#define CONFIG_ESP32_APPTRACE_DEST_NONE 1
#define CONFIG_ESP32_PHY_MAX_TX_POWER 20
#define CONFIG_ESP32_PANIC_PRINT_REBOOT 1
#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC 1
#define CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES 100
#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1
#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 240
#define CONFIG_ESP32_DEFAULT_CPU_FREQ_240 1
#define CONFIG_ESP32_DEBUG_OCDAWARE 1
#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000
#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1
#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1
#define CONFIG_ESP32_WIFI_AMPDU_ENABLED 1
#define CONFIG_ESP32_WIFI_NVS_ENABLED 1
#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10
#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 0
#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1
#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1
#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32
#define CONFIG_ESP32_WIFI_RX_BA_WIN 6
#define CONFIG_ESP32_WIFI_TX_BA_WIN 6
#define CONFIG_ESP32_XTAL_FREQ_AUTO 1
#define CONFIG_ESP32_XTAL_FREQ 0
#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024
#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT 5
#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT 2048
#if CONFIG_SPIRAM_SUPPORT
#define CONFIG_SPIRAM_TYPE_ESPPSRAM32 1
#define CONFIG_SPIRAM_SIZE 4194304
#define CONFIG_SPIRAM_SPEED_40M 1
#define CONFIG_SPIRAM_CACHE_WORKAROUND 1
#define CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL 16384
#define CONFIG_SPIRAM_BOOT_INIT 1
#define CONFIG_SPIRAM_MEMTEST 1
#define CONFIG_SPIRAM_USE_MALLOC 1
#define CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL 32768
#define CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY 1
#endif
#define CONFIG_FOUR_MAC_ADDRESS_FROM_EFUSE 1
#define CONFIG_DMA_RX_BUF_NUM 10
#define CONFIG_DMA_TX_BUF_NUM 10
#define CONFIG_EMAC_TASK_PRIORITY 20
#define CONFIG_INT_WDT 1
#define CONFIG_INT_WDT_TIMEOUT_MS 300
#define CONFIG_INT_WDT_CHECK_CPU1 0
#define CONFIG_TASK_WDT 1
#define CONFIG_TASK_WDT_PANIC 1
#define CONFIG_TASK_WDT_TIMEOUT_S 5
#define CONFIG_TASK_WDT_CHECK_IDLE_TASK 0
#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 0
#define CONFIG_FREERTOS_UNICORE 1
#define CONFIG_FREERTOS_CORETIMER_0 1
#define CONFIG_FREERTOS_HZ 100
#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1
#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1
#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE 1
#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 2
#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1024
#define CONFIG_FREERTOS_ISR_STACKSIZE 1536
#define CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG 1
#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16
#define CONFIG_SUPPORT_STATIC_ALLOCATION 1
#define CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK 1
#define CONFIG_MAIN_TASK_STACK_SIZE 4096
#define CONFIG_IPC_TASK_STACK_SIZE 1024
#define CONFIG_BTC_TASK_STACK_SIZE 3072
#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE 4096
#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE 32
#define CONFIG_TIMER_TASK_STACK_SIZE 4096
#define CONFIG_TIMER_TASK_PRIORITY 1
#define CONFIG_TIMER_TASK_STACK_DEPTH 2048
#define CONFIG_TIMER_QUEUE_LENGTH 10
#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1
#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1
#define CONFIG_PHY_ENABLED 1
#define CONFIG_WIFI_ENABLED 1
#define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1
#define CONFIG_MEMMAP_SMP 1
#define CONFIG_PARTITION_TABLE_SINGLE_APP 1
#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv"
#define CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET 0x10000
#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv"
#define CONFIG_CONSOLE_UART_BAUDRATE 115200
#define CONFIG_CONSOLE_UART_NUM 0
#define CONFIG_CONSOLE_UART_DEFAULT 1
#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1
#define CONFIG_LOG_BOOTLOADER_LEVEL_WARN 1
#define CONFIG_LOG_DEFAULT_LEVEL 3
#define CONFIG_LOG_COLORS 1
#define CONFIG_LOG_BOOTLOADER_LEVEL 2
#define CONFIG_LWIP_THREAD_LOCAL_STORAGE_INDEX 0
#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1
#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1
#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60
#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8
#define CONFIG_LWIP_MAX_ACTIVE_TCP 16
#define CONFIG_LWIP_MAX_SOCKETS 8
#define CONFIG_LWIP_SO_REUSE 1
#define CONFIG_LWIP_ETHARP_TRUST_IP_MAC 1
#define CONFIG_IP_LOST_TIMER_INTERVAL 120
#define CONFIG_UDP_RECVMBOX_SIZE 6
#define CONFIG_TCP_MAXRTX 12
#define CONFIG_TCP_SYNMAXRTX 6
#define CONFIG_TCP_MSL 60000
#define CONFIG_TCP_MSS 1436
#define CONFIG_TCP_SND_BUF_DEFAULT 5744
#define CONFIG_TCP_WND_DEFAULT 5744
#define CONFIG_TCP_QUEUE_OOSEQ 1
#define CONFIG_TCP_OVERSIZE_MSS 1
#define CONFIG_TCP_RECVMBOX_SIZE 6
#define CONFIG_MBEDTLS_AES_C 1
#define CONFIG_MBEDTLS_CCM_C 1
#define CONFIG_MBEDTLS_ECDH_C 1
#define CONFIG_MBEDTLS_ECDSA_C 1
#define CONFIG_MBEDTLS_ECP_C 1
#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1
#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1
#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1
#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1
#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1
#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1
#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1
#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1
#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1
#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1
#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1
#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1
#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1
#define CONFIG_MBEDTLS_GCM_C 1
#define CONFIG_MBEDTLS_HARDWARE_AES 1
#define CONFIG_MBEDTLS_HAVE_TIME 1
#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1
#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1
#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1
#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1
#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1
#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1
#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1
#define CONFIG_MBEDTLS_PEM_PARSE_C 1
#define CONFIG_MBEDTLS_PEM_WRITE_C 1
#define CONFIG_MBEDTLS_RC4_DISABLED 1
#define CONFIG_MBEDTLS_SSL_ALPN 1
#define CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN 16384
#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1
#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1
#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1
#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1
#define CONFIG_MBEDTLS_SSL_SESSION_TICKETS 1
#define CONFIG_MBEDTLS_TLS_CLIENT 1
#define CONFIG_MBEDTLS_TLS_ENABLED 1
#define CONFIG_MBEDTLS_TLS_SERVER 1
#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1
#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1
#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1
#define CONFIG_MAKE_WARN_UNDEFINED_VARIABLES 1
#define CONFIG_TOOLPREFIX "xtensa-esp32-elf-"
#define CONFIG_PYTHON "python2"

View File

@ -1,65 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* 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.
*/
#include <stdio.h>
#include "driver/uart.h"
#include "py/mpstate.h"
#include "py/mphal.h"
STATIC void uart_irq_handler(void *arg);
void uart_init(void) {
uart_isr_handle_t handle;
uart_isr_register(UART_NUM_0, uart_irq_handler, NULL, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, &handle);
uart_enable_rx_intr(UART_NUM_0);
}
// all code executed in ISR must be in IRAM, and any const data must be in DRAM
STATIC void IRAM_ATTR uart_irq_handler(void *arg) {
volatile uart_dev_t *uart = &UART0;
uart->int_clr.rxfifo_full = 1;
uart->int_clr.frm_err = 1;
uart->int_clr.rxfifo_tout = 1;
while (uart->status.rxfifo_cnt) {
uint8_t c = uart->fifo.rw_byte;
if (c == mp_interrupt_char) {
// inline version of mp_keyboard_interrupt();
MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
#if MICROPY_ENABLE_SCHEDULER
if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
}
#endif
} else {
// this is an inline function so will be in IRAM
ringbuf_put(&stdin_ringbuf, c);
}
}
}

View File

@ -1,33 +0,0 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* Development of the code in this file was sponsored by Microbric Pty Ltd
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_ESP32_UART_H
#define MICROPY_INCLUDED_ESP32_UART_H
void uart_init(void);
#endif // MICROPY_INCLUDED_ESP32_UART_H