esp32: Add new port to Espressif ESP32 SoC.

This commit is a combination of 216 commits from the initial stages of
development of this port, up to and including the point where the code was
moved to the ports/esp32 directory.  These commits were mostly concerned
with setting up the build system and getting a reliable port working with
basic features.  The following is a digest of the original commits in their
original order (most recent listed first), grouped where possible per
author.  The list is here to give credit for the work and provide some
level of traceability and accountability.  For the full history of
development please consult the original repository.

All code is MIT licensed and the relevant copyright holders are listed in
the comment-header of each file.

Damien George <damien.p.george@gmail.com>
  esp32: Update to latest ESP IDF.
  esp32: Update module symlinks now that code lives under the ports dir.
  esp32: Update to compile with new ports/esp32 directory structure.
  esp32: Move it to the ports/ directory.
  esp32/machine_uart: Don't save baudrate but compute it instead.
  esp32/modsocket: Add socket.readinto() method.
  esp32/modesp: Add esp.gpio_matrix_in and esp.gpio_matrix_out functions.
  esp32/machine_uart: Wait for all data to be tx'd before changing config.

NyxCode <moritz.bischof1@gmail.com>
  esp32: Add note to README.md about updating the submodules of ESP IDF.

Anthony Briggs <anthony.briggs@gmail.com>
  esp32: Update README.md installation and flashing instructions.

Javier Candeira <javier@candeira.com>
  esp32: Raise error when setting input-only pin to output.

  With help from Adrian Smith (fon@thefon.net)

Javier Candeira <javier@candeira.com>
  esp32: Replace exception raising with corresponding mp_raise_XXX funcs.

Tisham Dhar <whatnickd@gmail.com>
  esp32: Add some specific notes about building on Windows using WSL.

Ben Gamari <ben@smart-cactus.org>
  esp32: Provide machine.Signal class.

Damien George <damien.p.george@gmail.com>
  esp32/modnetwork: Implement AP version of network.isconnected().

Eric Poulsen <eric@zyxod.com>
  esp32/README.md: Add note about btree submodule initialization.

Damien George <damien.p.george@gmail.com>
  esp32: Make firmware.bin start at 0x1000 to allow flash size autodetect.
  esp32: Changes to follow latest version of upstream uPy.
  esp32/Makefile: Separate ESP-specific inc dirs to avoid header clashes.
  esp32: Enable "btree" database module.
  esp32: Update to latest ESP IDF.

Roosted7 <thomasroos@live.nl>
  esp32: Update to latest ESP-IDF.

Alex King <alex_w_king@yahoo.com>
  esp32/machine_timer: Add support for esp32 hardware timer.

  Code lineage:
  Timer() is based loosely on the version in esp8266, although the
  implementation is differs significantly because of the change in
  the underlying platform.

Damien George <damien.p.george@gmail.com>
  esp32/machine_uart: Increase UART TX buffer size to 64.
  esp32/modules: Update dht symlink.
  esp32/mpconfigport.h: Enable utimeq module, needed for uasyncio.
  esp32: Changes to follow latest version of upstream uPy.
  esp32: Update to latest ESP-IDF.
  esp32/machine_uart: Add uart.any() method.
  esp32/machine_uart: Uninstall the UART driver before installing it.

Thomas Roos <mail@thomasroos.nl>
  esp32: Update to latest ESP-IDF.

Eric Poulsen <eric@zyxod.com>
  esp32/modsocket: Make read/write return None when in non-blocking mode.
  esp32/modsocket.c: Fix send/sendto/write for non-blocking sockets.

Odd Stråbø <oddstr13@openshell.no>
  esp32: Initial working implementation of machine.UART.

  Code lineage (as seen by previous commits): I copied the ESP8266 code,
  renamed pyb -> machine, and used esp-idf as a reference while implementing
  minimal functionality.  I provide all of my changes under the MIT license.

Odd Stråbø <oddstr13@openshell.no>
  esp32/machine_uart: Rename pyb to machine.
  esp32: Copy machine_uart.c from esp8266 port.

Damien George <damien.p.george@gmail.com>
  esp32/moduos: Add uos.ilistdir() function.
  esp32: Mount filesystem at the root of the VFS, following esp8266.

Andy Valencia <vandyswa@gmail.com>
  esp32: Add hardware SHA1/SHA256 support via mbedtls API.

  Code lineage: a copy of extmod/moduhashlib with the API invocation details
  edited.  Total derivative work.

Andy Valencia <vandyswa@gmail.com>
  esp32: Add PWM support via machine.PWM class.

  Code lineage:
  I started by copying the esp8266 machine_pwm.c. I used information from the
  ESP32 Technical Reference Manual, the esp-idf documentation, and the SDK's
  sample ledc example code (but I did not copy that code, just studied it to
  understand the SDK's API for PWM). So aside from the code copied from the
  esp8266 PWM support, everything else you see is just new code I wrote.

  I wasn't an employee of anybody when I wrote it, and I wrote it with the
  understanding and intention that it's simply a derivative work of the
  existing micropython code. I freely and willingly contribute it to the
  project and intend that it not change the legal status of the micropython
  code base in any way, even if it is included in that base in whole or part.

Damien George <damien.p.george@gmail.com>
  esp32/modules: Add symlinks for upysh and upip.

Eric Poulsen <eric@zyxod.com>
  esp32/modmachine: Add unique_id() function to machine module.

Damien George <damien.p.george@gmail.com>
  esp32: Change dac_out_voltage to dac_output_voltage for new IDF API.
  esp32: Update esp32.custom_common.ld to align with changes in ESP IDF.

Eric Poulsen <eric@zyxod.com>
  esp32: Update to latest ESP IDF.

Damien George <damien.p.george@gmail.com>
  esp32/modsocket: When resolving IP addr handle the case of host=''.
  esp32: Update to latest ESP IDF.

Eric Poulsen <eric@zyxod.com>
  esp32/Makefile: Change default FLASH_MODE to dio for WROOM-32 module.
  esp32: Move FAT FS to start at 0x200000 and increase size to 2MiB.

Damien George <damien.p.george@gmail.com>
  esp32: Remove enable_irq/disable_irq and use ATOMIC_SECTION instead.
  esp32/mpconfigport.h: Provide ATOMIC_SECTION macros.
  esp32/main: Restart the MCU if there is a failed NLR jump.

Daniel Campora <daniel@pycom.io>
  esp32: Enable threading; be sure to exit GIL when a thread will block.
  esp32: Trace the registers when doing a gc collect. Also make it thread ready.
  esp32: Add threading implementation, disabled for the time being.

Damien George <damien.p.george@gmail.com>
  esp32: Update to latest ESP IDF.
  esp32/uart: Use high-level function to install UART0 RX ISR handler.
  esp32/Makefile: Make FreeRTOS private include dir really private.

Eric Poulsen <eric@zyxod.com>
  esp32: Add support for hardware SPI peripheral (block 1 and 2).

Sergio Conde Gómez <skgsergio@gmail.com>
  esp32/modules/inisetup.py: Mount filesystem at /flash like ESP8266

Damien George <damien.p.george@gmail.com>
  esp32: Convert to use core-provided KeyboardInterrupt exception.
  esp32: Pump the event loop while waiting for rx-chr or delay_ms.
  esp32: Implement Pin.irq() using "soft" scheduled interrupts.
  esp32: Update to latest ESP IDF version.

Eric Poulsen <eric@zyxod.com>
  esp32/README: Add troubleshooting section to the end.

tyggerjai <tyggerjai@gmail.com>
  esp32: Add support for WS2812 and APA106 RGB LEDs.

Damien George <damien.p.george@gmail.com>
  esp32: Add makeimg.py script to build full firmware; use it in Makefile.
  esp32/modsocket: Make socket.read return when socket closes.
  esp32/modsocket: Initialise the timeout on an accepted socket.
  esp32/mphalport: Provide proper implementations of disable_/enable_irq.
  esp32/modmachine: Add disable_irq/enable_irq functions.

Nick Moore <nick@zoic.org>
  esp32/modsocket.c: add comment explaining timeout behaviour
  esp32/modsocket.c: clean up send methods for retries too
  esp32/modsocket.c: sockets always nonblocking, accept timeout in modsocket
  esp32: Update to latest ESP IDF version.
  esp32/modsocket.c: remove MSG_PEEK workaround on select ioctl.
  esp32/modsocket.c: Initialize tcp when modsocket loads.

Damien George <damien.p.george@gmail.com>
  esp32/main: Bump heap size from 64k to 96k.
  esp32/modutime: Add time.time() function.
  esp32/modsocket: Convert lwip errnos to uPy ones.
  esp32/modules: Provide symlink to ds18x20 module.
  esp32: Add support for onewire protocol via OneWire module.
  esp32: Add support for DHT11 and DHT22 sensors.
  esp32/mphalport: Improve delay and ticks functions.
  esp32: Update to latest ESP IDF.
  esp32/modules: Provide symlink to urequests from micropython-lib.
  esp32: Populate sys.path.

Nick Moore <nick@zoic.org>
  esp32/machine_dac.c: implement DAC pins as well
  esp32/machine_adc.c: also machine.ADC
  esp32/machine_touchpad.c: add support for touchpad

Damien George <damien.p.george@gmail.com>
  esp32/README: Add hint about using GNUmakefile on case-insensitive FS.
  esp32/mpconfigport.h: Enable maximum speed software SPI.
  esp32: Provide improved version of mp_hal_delay_us_fast.
  esp32/mpconfigport.h: Enable MICROPY_PY_BUILTINS_POW3 option.
  esp32: Update to latest ESP IDF.
  esp32: Convert to use new oofatfs library and generic VFS sub-system.
  esp32: Enable help('modules') to list builtin modules.
  esp32: Convert to use new builtin help function.

Aaron Kelly <AaronKelly@email.com>
  esp32/README: Add comment about ESP-IDF version

Damien George <damien.p.george@gmail.com>
  esp32: Consistently use size_t instead of mp_uint_t.
  esp32: Change "Micro Python" to "MicroPython" in license comments.
  esp32/Makefile: Use -C argument to git instead of cd'ing.
  esp32/help: Add section to help about using the network module.
  esp32/README: Add section about configuring and using an ESP32 board.
  esp32/README: Remove paragraph about buggy toolchain, it's now fixed.
  esp32/modnetwork: Change network init logging from info to debug.
  esp32/modnetwork: Don't start AP automatically when init'ing wifi.
  esp32/modsocket: Implement socket.setsockopt, to support SO_REUSEADDR.
  esp32: Update to latest ESP IDF.
  esp32/sdkconfig.h: Remove unused CONFIG_ESPTOOLPY_xxx config settings.
  esp32/modsocket: Add support for DGRAM and RAW, and sendto/recvfrom.
  esp32/modsocket: Fix return value of "port" in socket.accept.
  esp32/modsocket: Make socket.recv take exactly 2 args.
  esp32: Enable ussl module, using mbedtls component from ESP IDF.
  esp32/modsocket: Rename "socket" module to "usocket".
  esp32/sdkconfig: Increase max number of open sockets from 4 to 8.
  esp32/modsocket: Add error checking for creating and closing sockets.
  esp32/modsocket: Use _r (re-entrant) versions of LWIP socket API funcs.
  esp32/modsocket: Raise an exception if socket.connect did not succeed.
  esp32/modsocket: Make socket.accept return a tuple: (client, addr).
  esp32/modsocket: Use m_new_obj_with_finaliser instead of calloc.
  esp32/Makefile: Add check for IDF version, and warn if not supported.
  esp32/esp32.custom_common.ld: Update to follow changes in IDF.
  esp32: Update to latest ESP IDF.

nubcore <x@nubcore.com>
  esp32: add #define CONFIG_ESP32_WIFI_RX_BUFFER_NUM 25

Nick Moore <nick@zoic.org>
  esp32/modsocket.c: add in sendall and makefile methods #10
  esp32/modsocket.c: fixups for #10
  esp32/modsocket.c: fix copyright, socket_recv gets param and exception
  esp32/modnetwork.c: fix copyright, network.active param to bool

Damien George <damien.p.george@gmail.com>
  esp32/modnetwork: Implement wlan.isconnected() method.
  esp32/modnetwork: Add initial implementation of wlan.config().
  esp32/modnetwork: Simplify event_handler messages.

Nick Moore <nick@zoic.org>
  esp32/modsocket.c: support for ioctl, settimeout, setblocking, getaddrinfo

Damien George <damien.p.george@gmail.com>
  esp32/README: Add comment about FLASH_MODE being dio.
  esp32: Update to latest ESP IDF.
  esp32/modnetwork: Remove unnecessary indirection variable for scan list.
  esp32/modnetwork: Check that STA is active before trying to scan.
  esp32/mphalport: Replace portTICK_RATE_MS with portTICK_PERIOD_MS.
  esp32/README: Add comment about using $(HOME) in makefile.
  esp32/modnetwork: Use memset instead of bzero, the latter is deprecated.
  esp32/modnetwork: Improve error handling when STA is connecting to AP.
  esp32/Makefile: Use tab instead of spaces, and use shorter variable.

Nick Moore <nick@zoic.org>
  esp32/modsocket.c: AF_*, SOCK_* and IPPROTO_* constants
  esp32/modsocket.c: socket.settimeout implementation

Damien George <damien.p.george@gmail.com>
  esp32/Makefile: Update to latest ESP IDF.

Nick Moore <nick@zoic.org>
  esp32/modsocket.c: use mp streams for sockets
  esp32: network.WLAN.ifconfig based on esp8266 version
  esp32: Fix up exception handling
  esp32: sketchy modsocket ... revisit this once modnetwork is sorted
  esp32: First cut at modnetwork, manually rebased from prev. version

Damien George <damien.p.george@gmail.com>
  esp32/help: Update help text.
  esp32: Add info about Microbric Pty Ltd being the sponsor of this port.
  esp32: Add README.md file.
  esp32/mpconfigport.h: Add weak links to many of the builtin modules.
  esp32: Enable soft implementation of machine.SPI class.
  esp32/Makefile: Simplify APP_LD_ARGS by using OBJ variable.
  esp32/Makefile: Reorganise Makefile and add some comments.
  esp32/Makefile: Clean up CFLAGS for ESP IDF components.
  esp32/Makefile: Tidy up names of ESP IDF components, to match dir name.
  esp32/Makefile: Define and use ESPCOMP variable.
  esp32: Update to latest ESP IDF.
  esp32/main: Enable filesystem support.
  esp32: Use custom ld script to ensure correct code get placed in iram.
  esp32: Update to latest ESP IDF.
  esp32/main: Pin the uPy task to core 0.
  esp32: Update to use latest ESP IDF.
  esp32: Disable boot-up scripts, spi_flash_erase_sector no longer works.
  esp32: Add scripts to init and mount filesystem.
  esp32: Enable frozen bytecode, with scripts stored in "modules/" dir.
  esp32/modesp: Increase flash_user_start position to 1Mbyte.
  esp32/Makefile: Add "erase" target for convenient erasure.
  esp32/sdkconfig: Reorder config settings to put common things together.
  esp32/sdkconfig: Change to use single core only.
  esp32: Add esp module.
  esp32/uart.c: Make sure uart ISR handler is all in iram.
  esp32/main.c: Use ESP_TASK_PRIO_MIN + 1 for mp_task's priority.
  esp32/Makefile: Use only bare-minimum flags when compiling .S files.
  esp32/Makefile: Rename "firmware" to "application".
  esp32: Update ESP IDF version.
  esp32/Makefile: Add declarations to build bootloader and partitions.
  esp32/Makefile: When deploying, write the application last.
  esp32/Makefile: Use $(INC) variable instead of listing include dirs.
  esp32/Makefile: Use locally built versions of freertos and newlib libs.
  esp32: Add low-level uart handler with ISR and ringbuf for stdin.
  esp32: Add machine.idle() function.
  esp32: Add machine.I2C class.
  esp32: Enable machine.time_pulse_us.
  esp32: Add initial implementation of machine.Pin class.
  esp32: Prepare main.c for using xTaskCreateStatic.
  esp32: Clean up mphalport.h.
  esp32: Add initial uos module.
  esp32: Clean up mpconfigport.h, enable more features.
  esp32: Use new reset function.
  esp32: Update to latest ESP IDF.
  esp32: Add idf-version target to Makefile, to track IDF commit.
  esp32: Initial port to ESP32.
pull/3461/head
Damien George 2016-12-06 12:20:10 +11:00
rodzic f1c9e7760d
commit bc08c884a2
50 zmienionych plików z 6463 dodań i 0 usunięć

Wyświetl plik

@ -0,0 +1,719 @@
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-
# paths to ESP IDF and its components
ifeq ($(ESPIDF),)
$(error Please configure the ESPIDF variable)
endif
ESPCOMP = $(ESPIDF)/components
ESPTOOL ?= $(ESPCOMP)/esptool_py/esptool/esptool.py
# verify the ESP IDF version
ESPIDF_SUPHASH := 9a26296a0e88a4c3ae27e9c848be970946fff87e
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/include
INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include
INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/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
CFLAGS_BASE = -std=gnu99 -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 -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H -DESP_PLATFORM
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 -fno-exceptions -fno-rtti -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 $(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.rom.spiram_incompatible_fns.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
################################################################################
# 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 \
modsocket.c \
modesp.c \
moduhashlib.c \
espneopixel.c \
machine_hw_spi.c \
mpthreadport.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/,\
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/,\
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 \
)
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 \
)
ESPIDF_CXX_O = $(addprefix $(ESPCOMP)/cxx/,\
cxx_guards.o \
)
ESPIDF_ETHERNET_O = $(addprefix $(ESPCOMP)/ethernet/,\
emac_dev.o \
emac_main.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 \
)
# 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
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/,\
library/cJSON.o \
port/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_NEWLIB_O = $(addprefix $(ESPCOMP)/newlib/,\
time.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_SPI_FLASH_O = $(addprefix $(ESPCOMP)/spi_flash/,\
flash_mmap.o \
partition.o \
spi_flash_rom_patch.o \
cache_utils.o \
flash_ops.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 \
)
ESPIDF_MBEDTLS_O = $(addprefix $(ESPCOMP)/mbedtls/,\
library/entropy.o \
library/pkcs12.o \
library/ccm.o \
library/pk.o \
library/sha1.o \
library/x509_csr.o \
library/ssl_cli.o \
library/ecp.o \
library/blowfish.o \
library/x509.o \
library/ecp_curves.o \
library/error.o \
library/ssl_ticket.o \
library/entropy_poll.o \
library/cipher.o \
library/version_features.o \
library/ripemd160.o \
library/rsa.o \
library/md.o \
library/md_wrap.o \
library/sha256.o \
library/dhm.o \
library/ssl_cache.o \
library/pkwrite.o \
library/base64.o \
library/asn1parse.o \
library/ssl_tls.o \
library/hmac_drbg.o \
library/pem.o \
library/version.o \
library/gcm.o \
library/memory_buffer_alloc.o \
library/md2.o \
library/ecdsa.o \
library/ssl_srv.o \
library/x509_crt.o \
library/ecdh.o \
library/asn1write.o \
library/md4.o \
library/debug.o \
library/x509_create.o \
library/ecjpake.o \
library/oid.o \
library/md5.o \
library/ssl_ciphersuites.o \
library/sha512.o \
library/xtea.o \
library/aes.o \
library/cipher_wrap.o \
library/arc4.o \
library/bignum.o \
library/pkparse.o \
library/padlock.o \
library/threading.o \
library/x509_crl.o \
library/pkcs11.o \
library/aesni.o \
library/timing.o \
library/certs.o \
library/pkcs5.o \
library/ssl_cookie.o \
library/camellia.o \
library/havege.o \
library/des.o \
library/x509write_csr.o \
library/platform.o \
library/ctr_drbg.o \
library/x509write_crt.o \
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 -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_NGHTTP_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NVS_FLASH_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_OPENSSL_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_SPI_FLASH_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 += $(ESPCOMP)/newlib/lib/libc.a
APP_LD_ARGS += $(ESPCOMP)/newlib/lib/libm.a
APP_LD_ARGS += $(ESPCOMP)/esp32/libhal.a
APP_LD_ARGS += -L$(ESPCOMP)/esp32/lib -lcore -lnet80211 -lphy -lrtc -lpp -lwpa -lsmartconfig -lcoexist
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_flash.o \
bootloader_support/src/bootloader_random.o \
bootloader_support/src/bootloader_sha.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 \
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_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 = $(ESPCOMP)/partition_table/partitions_singleapp.csv
$(BUILD)/partitions.bin: $(PART_SRC)
$(ECHO) "Create $@"
$(Q)$(PYTHON2) $(ESPCOMP)/partition_table/gen_esp32part.py -q $< $@
################################################################################
include $(TOP)/py/mkrules.mk

Wyświetl plik

@ -0,0 +1,199 @@
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 64k 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 256k in size).
- The machine module with basic GPIO and bit-banging I2C, SPI 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)
Instructions for setting up both of these components are provided by the
ESP-IDF itself, which is found at https://github.com/espressif/esp-idf .
Follow the guide "Setting Up ESP-IDF", for Windows, Mac or Linux. You
only need to perform up to "Step 2" of the guide, by which stage you
should have installed the cross-compile and cloned the ESP-IDF repository.
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](http://esp-idf.readthedocs.io/en/latest/get-started/linux-setup.html)
for the ESP-IDF instead of the Windows ones.
Be advised that the ESP-IDF is still undergoing changes and only some
versions are supported. To find which build is compatible refer to the line
in the makefile containing the following:
```
ESPIDF_SUPHASH := <Current supported ESP-IDF commit hash>
```
After finishing "Step 2" you can roll back your current build of
the ESP-IDF (and update the submodules accordingly) using:
```
$ git checkout <Current supported ESP-IDF commit hash>
$ git submodule update --recursive
```
Note that you will get a warning when building the code if the ESP-IDF
version is incorrect.
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 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-
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.

Wyświetl plik

@ -0,0 +1,215 @@
/* 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
/* 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.*)
*esp32/app_trace.o(.literal .text .literal.* .text.*)
*libphy.a:(.literal .text .literal.* .text.*)
*librtc.a:(.literal .text .literal.* .text.*)
*libsoc.a:(.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.*)
*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.*)
*app_trace/app_trace.o:(.rodata .rodata.*)
*heap/multi_heap.o(.rodata .rodata.*)
*heap/multi_heap_poisoning.o(.rodata .rodata.*)
_data_end = ABSOLUTE(.);
. = ALIGN(4);
} >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(.);
_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);
} >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
}

Wyświetl plik

@ -0,0 +1,53 @@
// 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);
}

Wyświetl plik

@ -0,0 +1,80 @@
/*
* 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);
}

Wyświetl plik

@ -0,0 +1,46 @@
/*
* 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 "py/obj.h"
#include "lib/oofatfs/ff.h"
#include "timeutils.h"
//#include "modmachine.h"
DWORD get_fattime(void) {
// TODO: Optimize division (there's no HW division support on ESP8266,
// so it's expensive).
//uint32_t secs = (uint32_t)(pyb_rtc_get_us_since_2000() / 1000000);
uint32_t secs = 0;
timeutils_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(secs, &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));
}

Wyświetl plik

@ -0,0 +1,66 @@
/*
* 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();
}

Wyświetl plik

@ -0,0 +1,42 @@
/*
* 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);

65
ports/esp32/help.c 100644
Wyświetl plik

@ -0,0 +1,65 @@
/*
* 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"
;

Wyświetl plik

@ -0,0 +1,132 @@
/*
* 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,
};

Wyświetl plik

@ -0,0 +1,97 @@
/*
* 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,
};

Wyświetl plik

@ -0,0 +1,370 @@
/*
* 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"
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);
int bits_to_send = len * self->bits;
bool shortMsg = len <= 4;
if (self->state == MACHINE_HW_SPI_STATE_DEINIT) {
mp_raise_msg(&mp_type_OSError, "transfer on deinitialized SPI");
return;
}
struct spi_transaction_t transaction = {
.flags = 0,
.length = bits_to_send,
.tx_buffer = NULL,
.rx_buffer = NULL,
};
if (shortMsg) {
if (src != NULL) {
memcpy(&transaction.tx_data, src, len);
}
transaction.flags |= (SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA);
} else {
transaction.tx_buffer = src;
transaction.rx_buffer = dest;
}
spi_device_transmit(self->spi, &transaction);
if (shortMsg && dest != NULL) {
memcpy(dest, &transaction.rx_data, len);
}
}
/******************************************************************************/
// 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,
};

Wyświetl plik

@ -0,0 +1,375 @@
/*
* 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"
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_hard };
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} },
};
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;
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) },
};
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,
};

Wyświetl plik

@ -0,0 +1,277 @@
/*
* 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;
}
// 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;
self->channel = channel;
}
// 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,
};

Wyświetl plik

@ -0,0 +1,192 @@
/*
* 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_map_elem_t machine_timer_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), (mp_obj_t)&machine_timer_deinit_obj },
{ MP_ROM_QSTR(MP_QSTR_deinit), (mp_obj_t)&machine_timer_deinit_obj },
{ MP_ROM_QSTR(MP_QSTR_init), (mp_obj_t)&machine_timer_init_obj },
{ MP_ROM_QSTR(MP_QSTR_value), (mp_obj_t)&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,
};

Wyświetl plik

@ -0,0 +1,110 @@
/*
* 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,
};

Wyświetl plik

@ -0,0 +1,359 @@
/*
* 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"};
QueueHandle_t UART_QUEUE[UART_NUM_MAX] = {};
/******************************************************************************/
// 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, 10, &UART_QUEUE[self->uart_num], 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,
};

131
ports/esp32/main.c 100644
Wyświetl plik

@ -0,0 +1,131 @@
/*
* 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 "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_task.h"
#include "soc/cpu.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 "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))
#define MP_TASK_HEAP_SIZE (96 * 1024)
STATIC StaticTask_t mp_task_tcb;
STATIC StackType_t mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8)));
STATIC uint8_t mp_task_heap[MP_TASK_HEAP_SIZE];
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();
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 + sizeof(mp_task_heap));
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) {
if (pyexec_raw_repl() != 0) {
break;
}
} else {
if (pyexec_friendly_repl() != 0) {
break;
}
}
}
#if MICROPY_PY_THREAD
mp_thread_deinit();
#endif
mp_hal_stdout_tx_str("PYB: soft reboot\r\n");
// deinitialise peripherals
machine_pins_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;
}

Wyświetl plik

@ -0,0 +1,25 @@
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))

Wyświetl plik

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

Wyświetl plik

@ -0,0 +1,129 @@
/*
* 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_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_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_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) },
};
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,
};

Wyświetl plik

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

Wyświetl plik

@ -0,0 +1,135 @@
/*
* 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 "esp_system.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"
#if MICROPY_PY_MACHINE
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_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_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_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_SPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) },
};
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

Wyświetl plik

@ -0,0 +1,18 @@
#ifndef MICROPY_INCLUDED_ESP32_MODMACHINE_H
#define MICROPY_INCLUDED_ESP32_MODMACHINE_H
#include "py/obj.h"
extern const mp_obj_type_t machine_timer_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;
void machine_pins_init(void);
void machine_pins_deinit(void);
#endif // MICROPY_INCLUDED_ESP32_MODMACHINE_H

Wyświetl plik

@ -0,0 +1,561 @@
/*
* 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 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"
#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_CONN:
mp_raise_msg(&mp_type_OSError, "Wifi Internal Error");
case ESP_ERR_WIFI_SSID:
mp_raise_msg(&mp_type_OSError, "Wifi SSID Invalid");
case ESP_ERR_WIFI_FAIL:
mp_raise_msg(&mp_type_OSError, "Wifi Internal Failure");
case ESP_ERR_WIFI_IF:
mp_raise_msg(&mp_type_OSError, "Wifi Invalid Interface");
case ESP_ERR_WIFI_MAC:
mp_raise_msg(&mp_type_OSError, "Wifi Invalid MAC Address");
case ESP_ERR_WIFI_ARG:
mp_raise_msg(&mp_type_OSError, "Wifi Invalid Argument");
case ESP_ERR_WIFI_MODE:
mp_raise_msg(&mp_type_OSError, "Wifi Invalid Mode");
case ESP_ERR_WIFI_PASSWORD:
mp_raise_msg(&mp_type_OSError, "Wifi Invalid Password");
case ESP_ERR_WIFI_NVS:
mp_raise_msg(&mp_type_OSError, "Wifi Internal NVS Error");
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_WIFI_TIMEOUT:
mp_raise_OSError(MP_ETIMEDOUT);
case ESP_ERR_TCPIP_ADAPTER_NO_MEM:
case ESP_ERR_WIFI_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 the STA interface is requested to be connected by the
// user, used for automatic reassociation.
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_GOT_IP:
ESP_LOGI("wifi", "GOT_IP");
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;
ESP_LOGI("wifi", "STA_DISCONNECTED, reason:%d", disconn->reason);
switch (disconn->reason) {
case WIFI_REASON_AUTH_FAIL:
mp_printf(MP_PYTHON_PRINTER, "authentication failed");
wifi_sta_connected = false;
break;
default:
// Let other errors through and try to reconnect.
break;
}
if (wifi_sta_connected) {
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) {
mp_printf(MP_PYTHON_PRINTER, "error attempting to reconnect: 0x%04x", e);
}
}
}
}
break;
}
default:
ESP_LOGI("wifi", "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) {
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");
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");
ESP_EXCEPTIONS( esp_wifi_set_mode(0) );
ESP_EXCEPTIONS( esp_wifi_start() );
ESP_LOGD("modnetwork", "Started");
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;
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);
ESP_EXCEPTIONS( esp_wifi_set_mode(mode) );
}
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_connected = 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_connected = 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(mp_obj_t self_in) {
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_status_obj, 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) {
tcpip_adapter_ip_info_t info;
tcpip_adapter_get_ip_info(WIFI_IF_STA, &info);
return mp_obj_new_bool(info.ip.addr != 0);
} 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;
ip_addr_t dns_addr;
tcpip_adapter_get_ip_info(self->if_id, &info);
if (n_args == 1) {
// get
dns_addr = dns_getserver(0);
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_addr, 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_addr, NETUTILS_BIG);
// To set a static IP we have to disable DHCP first
if (self->if_id == WIFI_IF_STA) {
esp_err_t e = tcpip_adapter_dhcpc_stop(WIFI_IF_STA);
if (e != ESP_OK && e != ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED) _esp_exceptions(e);
ESP_EXCEPTIONS(tcpip_adapter_set_ip_info(WIFI_IF_STA, &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_dhcps_start(WIFI_IF_AP));
}
return mp_const_none;
}
}
STATIC 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;
}
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):
req_if = WIFI_IF_AP;
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;
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_map_elem_t wlan_if_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_active), (mp_obj_t)&esp_active_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&esp_connect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disconnect), (mp_obj_t)&esp_disconnect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_status), (mp_obj_t)&esp_status_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&esp_scan_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_isconnected), (mp_obj_t)&esp_isconnected_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_config), (mp_obj_t)&esp_config_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ifconfig), (mp_obj_t)&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_map_elem_t mp_module_network_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) },
{ MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&esp_initialize_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&get_wlan_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_phy_mode), (mp_obj_t)&esp_phy_mode_obj },
#if MODNETWORK_INCLUDE_CONSTANTS
{ MP_OBJ_NEW_QSTR(MP_QSTR_STA_IF),
MP_OBJ_NEW_SMALL_INT(WIFI_IF_STA)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_AP_IF),
MP_OBJ_NEW_SMALL_INT(WIFI_IF_AP)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_11B),
MP_OBJ_NEW_SMALL_INT(WIFI_PROTOCOL_11B) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_11G),
MP_OBJ_NEW_SMALL_INT(WIFI_PROTOCOL_11G) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_11N),
MP_OBJ_NEW_SMALL_INT(WIFI_PROTOCOL_11N) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_OPEN),
MP_OBJ_NEW_SMALL_INT(WIFI_AUTH_OPEN) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_WEP),
MP_OBJ_NEW_SMALL_INT(WIFI_AUTH_WEP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_WPA_PSK),
MP_OBJ_NEW_SMALL_INT(WIFI_AUTH_WPA_PSK) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_WPA2_PSK),
MP_OBJ_NEW_SMALL_INT(WIFI_AUTH_WPA2_PSK) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK),
MP_OBJ_NEW_SMALL_INT(WIFI_AUTH_WPA_WPA2_PSK) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_MAX),
MP_OBJ_NEW_SMALL_INT(WIFI_AUTH_MAX) },
#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,
};

Wyświetl plik

@ -0,0 +1,570 @@
/*
* 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 "lwip/sockets.h"
#include "lwip/netdb.h"
#include "lwip/ip4.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;
unsigned int retries;
} socket_obj_t;
void _socket_settimeout(socket_obj_t *sock, uint64_t timeout_ms);
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);
}
void check_for_exceptions() {
mp_obj_t exc = MP_STATE_VM(mp_pending_exception);
if (exc != MP_OBJ_NULL) {
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
nlr_raise(exc);
}
}
STATIC mp_obj_t socket_close(const mp_obj_t arg0) {
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
if (self->fd >= 0) {
int ret = lwip_close_r(self->fd);
if (ret != 0) {
exception_from_errno(errno);
}
self->fd = -1;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close);
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;
_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 level = mp_obj_get_int(args[1]);
if (level != SOL_SOCKET) {
mp_raise_ValueError("unsupported level");
}
// only "int" arguments are supported at the moment
int opt = mp_obj_get_int(args[2]);
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);
}
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);
mp_obj_t _socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in,
struct sockaddr *from, socklen_t *from_len) {
socket_obj_t *sock = MP_OBJ_TO_PTR(self_in);
size_t len = mp_obj_get_int(len_in);
vstr_t vstr;
vstr_init_len(&vstr, len);
// 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, vstr.buf, len, 0, from, from_len);
MP_THREAD_GIL_ENTER();
if (r >= 0) { vstr.len = r; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); }
if (errno != EWOULDBLOCK) exception_from_errno(errno);
check_for_exceptions();
}
mp_raise_OSError(MP_ETIMEDOUT);
}
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);
// 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_stream_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
socket_obj_t *sock = self_in;
// 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, NULL, NULL);
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_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;
}
*errcode = MP_EINVAL;
return MP_STREAM_ERROR;
}
STATIC const mp_map_elem_t socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&socket_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&socket_bind_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&socket_listen_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&socket_accept_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&socket_connect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendall), (mp_obj_t)&socket_sendall_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&socket_sendto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&socket_recvfrom_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&socket_setsockopt_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_settimeout), (mp_obj_t)&socket_settimeout_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_setblocking), (mp_obj_t)&socket_setblocking_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_makefile), (mp_obj_t)&socket_makefile_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_fileno), (mp_obj_t)&socket_fileno_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&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;
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(const mp_obj_t host, const mp_obj_t port) {
struct addrinfo *res = NULL;
_socket_getaddrinfo2(host, port, &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_2(esp_socket_getaddrinfo_obj, 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_map_elem_t mp_module_socket_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usocket) },
{ MP_OBJ_NEW_QSTR(MP_QSTR___init__), (mp_obj_t)&esp_socket_initialize_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&get_socket_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_socket_getaddrinfo_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(AF_INET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET6), MP_OBJ_NEW_SMALL_INT(AF_INET6) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(SOCK_STREAM) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(SOCK_DGRAM) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_RAW), MP_OBJ_NEW_SMALL_INT(SOCK_RAW) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(IPPROTO_TCP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(IPPROTO_UDP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOL_SOCKET), MP_OBJ_NEW_SMALL_INT(SOL_SOCKET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SO_REUSEADDR), MP_OBJ_NEW_SMALL_INT(SO_REUSEADDR) },
};
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,
};

Wyświetl plik

@ -0,0 +1,142 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2014 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 "py/runtime.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha1.h"
union sha_ctxs {
mbedtls_sha256_context sha256;
mbedtls_sha1_context sha1;
};
typedef struct _mp_obj_hash_t {
mp_obj_base_t base;
union sha_ctxs state;
} mp_obj_hash_t;
STATIC mp_obj_t sha256_update(mp_obj_t self_in, mp_obj_t arg);
STATIC mp_obj_t sha1_update(mp_obj_t self_in, mp_obj_t arg);
STATIC mp_obj_t sha256_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, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(union sha_ctxs));
o->base.type = type;
mbedtls_sha256_init(&o->state.sha256);
if (n_args == 1) {
sha256_update(MP_OBJ_FROM_PTR(o), args[0]);
}
return MP_OBJ_FROM_PTR(o);
}
STATIC mp_obj_t sha1_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, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(union sha_ctxs));
o->base.type = type;
mbedtls_sha1_init(&o->state.sha1);
if (n_args == 1) {
sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
}
return MP_OBJ_FROM_PTR(o);
}
STATIC mp_obj_t sha256_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
mbedtls_sha256_update(&self->state.sha256, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(sha256_update_obj, sha256_update);
STATIC mp_obj_t sha1_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
mbedtls_sha1_update(&self->state.sha1, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(sha1_update_obj, sha1_update);
STATIC mp_obj_t sha256_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
vstr_t vstr;
vstr_init_len(&vstr, 32);
mbedtls_sha256_finish(&self->state.sha256, (unsigned char *)vstr.buf);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
MP_DEFINE_CONST_FUN_OBJ_1(sha256_digest_obj, sha256_digest);
STATIC mp_obj_t sha1_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
vstr_t vstr;
vstr_init_len(&vstr, 20);
mbedtls_sha1_finish(&self->state.sha1, (unsigned char *)vstr.buf);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
MP_DEFINE_CONST_FUN_OBJ_1(sha1_digest_obj, sha1_digest);
STATIC const mp_rom_map_elem_t sha256_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&sha256_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&sha256_digest_obj) },
};
STATIC MP_DEFINE_CONST_DICT(sha256_locals_dict, sha256_locals_dict_table);
STATIC const mp_obj_type_t sha256_type = {
{ &mp_type_type },
.name = MP_QSTR_sha256,
.make_new = sha256_make_new,
.locals_dict = (void*)&sha256_locals_dict,
};
STATIC const mp_rom_map_elem_t sha1_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&sha1_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&sha1_digest_obj) },
};
STATIC MP_DEFINE_CONST_DICT(sha1_locals_dict, sha1_locals_dict_table);
STATIC const mp_obj_type_t sha1_type = {
{ &mp_type_type },
.name = MP_QSTR_sha1,
.make_new = sha1_make_new,
.locals_dict = (void*)&sha1_locals_dict,
};
STATIC const mp_rom_map_elem_t mp_module_hashlib_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uhashlib) },
{ MP_ROM_QSTR(MP_QSTR_sha256), MP_ROM_PTR(&sha256_type) },
{ MP_ROM_QSTR(MP_QSTR_sha1), MP_ROM_PTR(&sha1_type) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_hashlib_globals,
mp_module_hashlib_globals_table);
const mp_obj_module_t mp_module_uhashlib = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&mp_module_hashlib_globals,
};

Wyświetl plik

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

Wyświetl plik

@ -0,0 +1,8 @@
# 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)

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -0,0 +1,34 @@
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)

Wyświetl plik

@ -0,0 +1,38 @@
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)
""")
return vfs

Wyświetl plik

@ -0,0 +1,33 @@
# 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)

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -0,0 +1,128 @@
/*
* 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/mpconfig.h"
#include "py/obj.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "py/mperrno.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;
mp_hal_signal_dupterm_input();
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,
};

Wyświetl plik

@ -0,0 +1,61 @@
/*
* 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 "extmod/utime_mphal.h"
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_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,
};

Wyświetl plik

@ -0,0 +1,248 @@
// 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_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_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_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_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 (0) // We use the ESP32 version
#define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL && MICROPY_SSL_AXTLS)
#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_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_PY_MACHINE_SPI_MIN_DELAY (0)
#define MICROPY_PY_MACHINE_SPI_MAX_BAUDRATE (ets_get_cpu_frequency() * 1000000 / 200) // roughly
#define MICROPY_PY_USSL (1)
#define MICROPY_SSL_MBEDTLS (1)
#define MICROPY_PY_WEBSOCKET (0)
#define MICROPY_PY_FRAMEBUF (1)
// 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 fatfs_type_fileio
#define mp_type_textio fatfs_type_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 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_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 }, \
#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_THREAD
#define MICROPY_EVENT_POLL_HOOK \
do { \
extern void mp_handle_pending(void); \
mp_handle_pending(); \
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(); \
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"

Wyświetl plik

@ -0,0 +1,139 @@
/*
* 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 <sys/time.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_char(char c) {
uart_tx_one_char(c);
//mp_uos_dupterm_tx_strn(&c, 1);
}
void mp_hal_stdout_tx_str(const char *str) {
MP_THREAD_GIL_EXIT();
while (*str) {
mp_hal_stdout_tx_char(*str++);
}
MP_THREAD_GIL_ENTER();
}
void mp_hal_stdout_tx_strn(const char *str, uint32_t len) {
MP_THREAD_GIL_EXIT();
while (len--) {
mp_hal_stdout_tx_char(*str++);
}
MP_THREAD_GIL_ENTER();
}
void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len) {
MP_THREAD_GIL_EXIT();
while (len--) {
if (*str == '\n') {
mp_hal_stdout_tx_char('\r');
}
mp_hal_stdout_tx_char(*str++);
}
MP_THREAD_GIL_ENTER();
}
uint32_t mp_hal_ticks_ms(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
uint32_t mp_hal_ticks_us(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000000 + tv.tv_usec;
}
void mp_hal_delay_ms(uint32_t ms) {
struct timeval tv_start;
struct timeval tv_end;
uint64_t dt;
gettimeofday(&tv_start, NULL);
for (;;) {
gettimeofday(&tv_end, NULL);
dt = (tv_end.tv_sec - tv_start.tv_sec) * 1000 + (tv_end.tv_usec - tv_start.tv_usec) / 1000;
if (dt + portTICK_PERIOD_MS >= ms) {
// doing a vTaskDelay would take us beyound requested delay time
break;
}
MICROPY_EVENT_POLL_HOOK
vTaskDelay(1);
}
if (dt < ms) {
// do the remaining delay accurately
ets_delay_us((ms - dt) * 1000);
}
}
void mp_hal_delay_us(uint32_t us) {
ets_delay_us(us);
}
// 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;
}
*/

Wyświetl plik

@ -0,0 +1,83 @@
/*
* 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_set_direction(pin, GPIO_MODE_INPUT);
}
static inline void mp_hal_pin_output(mp_hal_pin_obj_t pin) {
gpio_set_direction(pin, GPIO_MODE_INPUT_OUTPUT);
}
static inline void mp_hal_pin_open_drain(mp_hal_pin_obj_t 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

Wyświetl plik

@ -0,0 +1,226 @@
/*
* 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

Wyświetl plik

@ -0,0 +1,45 @@
/*
* 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

Wyświetl plik

@ -0,0 +1,30 @@
/*
* 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)

Wyświetl plik

@ -0,0 +1,162 @@
#define CONFIG_TRACEMEM_RESERVE_DRAM 0x0
#define CONFIG_BT_RESERVE_DRAM 0x0
#define CONFIG_ULP_COPROC_RESERVE_MEM 0
#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_TCPIP_TASK_STACK_SIZE 2560
#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_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 0
#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
#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_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_MAX_SOCKETS 8
#define CONFIG_LWIP_SO_REUSE 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"

65
ports/esp32/uart.c 100644
Wyświetl plik

@ -0,0 +1,65 @@
/*
* 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);
}
}
}

33
ports/esp32/uart.h 100644
Wyświetl plik

@ -0,0 +1,33 @@
/*
* 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