Merge tag 'v1.8.6'
ESP8266 port uses SDK 2.0, has more heap, has support for 512k devices This release brings some code size reductions to the core as well as more tests and improved coverage which is now at 94.3%. The time.ticks_diff(a, b) function has changed: the order of the arguments has been swapped so that it behaves like "a - b", and it can now return a negative number if "a" came before "b" (modulo the period of the ticks functions). For the ESP8266 port the Espressif SDK has been updated to 2.0.0, the heap has been increased from 28k to 36k, and there is support for 512k devices via "make 512k". upip is included by default as frozen bytecode. The network module now allows access-point reconnection without WiFi credentials, and exposes configuration for the station DHCP hostname. The DS18B20 driver now handles negative temperatures, and NeoPixel and APA102 drivers handle 4 bytes-per-pixel LEDs. For the CC3200 port there is now support for loading of precompiled .mpy files and threading now works properly with interrupts. A detailed list of changes follows. py core: - py.mk: automatically add frozen.c to source list if FROZEN_DIR is defined - be more specific with MP_DECLARE_CONST_FUN_OBJ macros - specialise builtin funcs to use separate type for fixed arg count - {modbuiltins,obj}: use MP_PYTHON_PRINTER where possible - modbuiltins: add builtin "slice", pointing to existing slice type - add "delattr" builtin, conditional on MICROPY_CPYTHON_COMPAT - sequence: fix reverse slicing of lists - fix null pointer dereference in mpz.c, fix missing va_end in warning.c - remove asserts that are always true in emitbc.c - fix wrong assumption that m_renew will not move if shrinking - change config default so m_malloc0 uses memset if GC not enabled - add MICROPY_FLOAT_CONST macro for defining float constants - move frozen bytecode Makefile rules from ports to common mk files - strip leading dirs from frozen mpy files, so any path can be used extmod: - vfs_fat_file: check fatfs f_sync() and f_close() returns for errors - vfs_fat_file: make file.close() a no-op if file already closed - utime_mphal: ticks_diff(): switch arg order, return signed value - utime_mphal: add MP_THREAD_GIL_EXIT/ENTER warppers for sleep functions - utime_mphal: implement ticks_add(), add to all maintained ports - utime_mphal: allow ticks functions period be configurable by a port lib: - utils/pyhelp.c: use mp_printf() instead of printf() - utils/pyexec: add mp_hal_set_interrupt_char() prototype - libm: move Thumb-specific sqrtf function to separate file drivers: - add "from micropython import const" when const is used tools: - upgrade upip to 1.1.4: fix error on unix when installing to non-existing absolute path - pip-micropython: remove deprecated wrapper tool - check_code_size.sh: code size validation script for CI - replace upip tarball with just source file, to make its inclusion as frozen modules in multiple ports less magic tests: - extmod/vfs_fat: improve VFS test coverage - basics/builtin_slice: add test for "slice" builtin name - basics: add test for builtin "delattr" - extmod/vfs_fat_fsusermount: improve fsusermount test coverage - extmod/vfs_fat_oldproto: test old block device protocol - basics/gc1: garbage collector threshold() coverage - extmod/uhashlib_sha1: coverage for SHA1 algorithm - extmod/uhashlib_sha256: rename sha256.py test - btree1: fix out of memory error running on esp8266 - extmod/ticks_diff: test for new semantics of ticks_diff() - extmod/framebuf1: test framebuffer pixel clear, and text function minimal port: - Makefile: split rule for firmware.bin generation unix port: - Makefile: remove references to deprecated pip-micropython - modtime: use ticks_diff() implementation from extmod/utime_mphal.c - mphalport.h: add warning of mp_hal_delay_ms() implementation - modtime: switch ticks/sleep_ms/us() to utime_mphal - fix symbol references for x86 Mac - replace upip tarball with just source file windows port: - enable utime_mphal following unix, define mp_hal_ticks_* - fix utime_mphal compilation for msvc - implement mp_hal_ticks_cpu in terms of QueryPerformanceCounter qemu-arm port: - exclude ticks_diff test for qemu-arm port - exclude extmod/vfs_fat_fileio.py test - exclude new vfs_fat tests - enable software floating point support, and float tests stmhal port: - modutime: refactor to use extmod's version of ticks_cpu - refactor pin usage to use mp_hal_pin API - led: refactor LED to use mp_hal_pin_output() init function - Makefile: use standard rules for frozen module generation - modutime: consistently convert to MP_ROM_QSTR/MP_ROM_PTR - enable SD power save (disable CLK on idle) cc3200 port: - use mp_raise_XXX helper functions to reduce code size - mods/pybspi: allow "write" arg of read/readinto to be positional - enable loading of precompiled .mpy files - fix thread mutex's so threading works with interrupts teensy port: - update to provide new mp_hal_pin_XXX functions following stmhal esp8266 port: - Makefile: use latest esptool.py flash size auto-detection - esp_init_data: auto-initialize system params with vendor SDK 2.0.0 - esp8266.ld: move help.o to iROM - esp8266.ld: move modmachine.o to iROM - esp8266.ld: move main.o to iROM - add MP_FASTCODE modifier to put a function to iRAM - main: mark nlr_jump_fail() as MP_FASTCODE - modules/webrepl: enforce only one concurrent WebREPL connection - etshal.h: add few more ESP8266 vendor lib prototypes - modesp: add flash_user_start() function - add support for building firmware version for 512K modules - scripts: make neopixel/apa102 handle 4bpp LEDs with common code - modutime: consistently convert to MP_ROM_QSTR/MP_ROM_PTR - modnetwork: config(): fix copy-paste error in setting "mac" - scripts/port_diag: add descriptions for esf_buf types - modnetwork.c: allows AP reconnection without WiFi credentials - main: bump heap size to 36K - etshal.h: add prototypes for SPIRead/SPIWrite/SPIEraseSector - etshal.h: adjust size of MD5_CTX structure - modules: fix negative temperature in ds18x20 driver - rename "machine" module implementation to use contemporary naming - rework webrepl_setup to run over wired REPL - espneopixel.c: solve glitching LED issues with cpu at 80MHz - include upip as a standard frozen bytecode module - update docs for esptool 1.2.1/SDK 2.0 (--flash_size=detect) - modnetwork.c: expose configuration for station DHCP hostname zephyr port: - implement utime module - use board/SoC values for startup banner based on Zephyr config - initial implementation of machine.Pin - zephyr_getchar: update for recent Zephyr refactor of console hooks - support time -> utime module "weaklink" - README: update for the current featureset, add more info - mpconfigport.h: move less important params to the bottom - Makefile: allow to adjust heap size from make command line - Makefile: update comments to the current state of affairs - Makefile: allow to override Zephyr config from make command line - Makefile: add minimal port - Makefile: add -fomit-frame-pointer to reduce code size - mphalport.h: update for new "unified" kernal API (sleep functions) docs: - machine.SPI: bring up to date with Hardware API, make vendor-neutral - machine.SPI: improve descriptions of xfer methods - library/builtins: add docs for delattr and slice - library/network: reword intro paragraph - library/network: typo fixes, consistent acronym capitalization - library/index: update TOCs so builtins sorted before modules - utime: document ticks_cpu() in more detail - utime: describe new semantics of ticks_diff() (signed ring arithmetics) - utime: add docs for ticks_add(), improvements for other ticks_*() - esp8266: update for new WebREPL setup procedure - */quickref.rst: use new semantics of ticks_diff() - library/machine.Pin: update Pin docs to align with new HW API travis: - integrate tools/check_code_size.sh - minimal: Use CROSS=1, for binary size check examples: - http_server_simplistic: add "not suitable for real use" note - hwapi: example showing best practices for HW API usage in apps - hwapi: add hwconfig for DragonBoard 410c
This commit is contained in:
commit
bd36873362
10
.travis.yml
10
.travis.yml
|
@ -3,6 +3,9 @@ dist: trusty
|
|||
language: c
|
||||
compiler:
|
||||
- gcc
|
||||
cache:
|
||||
directories:
|
||||
- "${HOME}/persist"
|
||||
|
||||
before_script:
|
||||
# Extra CPython versions
|
||||
|
@ -29,7 +32,12 @@ script:
|
|||
- make -C atmel-samd BOARD=feather_m0_adalogger
|
||||
- make -C atmel-samd BOARD=feather_m0_basic
|
||||
- make -C atmel-samd BOARD=metro_m0_flash
|
||||
- make -C minimal test
|
||||
- make -C minimal CROSS=1 build/firmware.bin
|
||||
- ls -l minimal/build/firmware.bin
|
||||
- tools/check_code_size.sh
|
||||
- mkdir -p ${HOME}/persist
|
||||
# Save new firmware for reference, but only if building a main branch, not a pull request
|
||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then cp minimal/build/firmware.bin ${HOME}/persist/; fi'
|
||||
- make -C unix deplibs
|
||||
- make -C unix
|
||||
- make -C unix nanbox
|
||||
|
|
|
@ -1448,7 +1448,7 @@ indicating that they also supported the first campaign.
|
|||
* 902 B Stevens
|
||||
903 Cptnslick, US
|
||||
904 janlj@me.com
|
||||
905 São Caetano do Sul, SP, Brazil
|
||||
905 Fabricio Biazzotto
|
||||
906 Lenz Hirsch
|
||||
907 SerSher, RU
|
||||
908 Florian, DE
|
||||
|
|
|
@ -27,15 +27,6 @@ BOSSAC := tools/bossac_osx
|
|||
|
||||
HAL_DIR=hal/$(MCU_SERIES)
|
||||
|
||||
# Frozen bytecode configuration. Any .py files placed in the modules subdirectory
|
||||
# will be frozen into .mpy files and embedded in the firmware (like the ESP8266
|
||||
# port).
|
||||
MPY_CROSS = ../mpy-cross/mpy-cross
|
||||
MPY_TOOL = ../tools/mpy-tool.py
|
||||
FROZEN_MPY_DIR = modules
|
||||
FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py')
|
||||
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
|
||||
|
||||
INC += -I.
|
||||
INC += -I..
|
||||
INC += -I../lib/mp-readline
|
||||
|
@ -114,6 +105,19 @@ else
|
|||
CFLAGS += -Os -DNDEBUG
|
||||
endif
|
||||
|
||||
ifneq ($(FROZEN_DIR),)
|
||||
# To use frozen source modules, put your .py files in a subdirectory (eg scripts/)
|
||||
# and then invoke make with FROZEN_DIR=scripts (be sure to build from scratch).
|
||||
CFLAGS += -DMICROPY_MODULE_FROZEN_STR
|
||||
endif
|
||||
|
||||
ifneq ($(FROZEN_MPY_DIR),)
|
||||
# To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and
|
||||
# then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch).
|
||||
CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
|
||||
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY
|
||||
endif
|
||||
|
||||
LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
|
||||
LIBM_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-file-name=libm.a)
|
||||
LDFLAGS = -Lasf/thirdparty/CMSIS/Lib/GCC/ -L $(dir $(LIBGCC_FILE_NAME)) -L $(dir $(LIBM_FILE_NAME)) -nostdlib -T $(LD_FILE) -Map=$@.map --cref --gc-sections
|
||||
|
@ -200,12 +204,8 @@ SRC_BINDINGS = \
|
|||
SRC_BINDINGS_EXPANDED = $(addprefix shared-bindings/, $(SRC_BINDINGS)) \
|
||||
$(addprefix common-hal/, $(SRC_BINDINGS))
|
||||
|
||||
SRC_AUTOGEN = \
|
||||
$(BUILD)/frozen_mpy.c \
|
||||
|
||||
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_ASF:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_AUTOGEN:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_BINDINGS_EXPANDED:.c=.o))
|
||||
|
||||
|
@ -213,17 +213,6 @@ SRC_QSTR += $(SRC_C) $(SRC_BINDINGS_EXPANDED) $(STM_SRC_C)
|
|||
|
||||
all: $(BUILD)/firmware.bin
|
||||
|
||||
# to build .mpy files from .py files
|
||||
$(BUILD)/$(FROZEN_MPY_DIR)/%.mpy: $(FROZEN_MPY_DIR)/%.py
|
||||
@$(ECHO) "MPY $<"
|
||||
$(Q)$(MKDIR) -p $(dir $@)
|
||||
$(Q)$(MPY_CROSS) -o $@ -s $(^:$(FROZEN_MPY_DIR)/%=%) $^
|
||||
|
||||
# to build frozen_mpy.c from all .mpy files
|
||||
$(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h
|
||||
@$(ECHO) "Creating $@"
|
||||
$(Q)$(PYTHON) $(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h -mlongint-impl=none $(FROZEN_MPY_MPY_FILES) > $@
|
||||
|
||||
$(BUILD)/firmware.elf: $(OBJ)
|
||||
$(ECHO) "LINK $@"
|
||||
$(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
|
|
|
@ -101,7 +101,7 @@ extern const mp_obj_type_t pin_cpu_pins_obj_type;
|
|||
extern const mp_obj_dict_t pin_cpu_pins_locals_dict;
|
||||
extern const mp_obj_dict_t pin_board_pins_locals_dict;
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(pin_init_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(pin_init_obj);
|
||||
|
||||
void pin_init0(void);
|
||||
uint32_t pin_get_mode(const pin_obj_t *pin);
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
// options to control how Micro Python is built
|
||||
|
||||
#define MICROPY_QSTR_BYTES_IN_HASH (1)
|
||||
#define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool
|
||||
#define MICROPY_ALLOC_PATH_MAX (256)
|
||||
#define MICROPY_ALLOC_PARSE_CHUNK_INIT (16)
|
||||
// TODO(tannewt): Reduce this number if we want the REPL to function under 512
|
||||
|
@ -57,7 +56,6 @@
|
|||
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
|
||||
#define MICROPY_PY_STRUCT (1)
|
||||
#define MICROPY_PY_SYS (1)
|
||||
#define MICROPY_MODULE_FROZEN_MPY (1)
|
||||
#define MICROPY_CPYTHON_COMPAT (0)
|
||||
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
|
||||
|
|
|
@ -61,7 +61,6 @@ typedef long mp_off_t;
|
|||
#define MP_PLAT_PRINT_STRN(str, len) (void)0
|
||||
|
||||
// extra built in names to add to the global namespace
|
||||
extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
|
||||
#define MICROPY_PORT_BUILTINS \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
|
||||
|
||||
|
|
|
@ -30,6 +30,6 @@
|
|||
void rng_init0 (void);
|
||||
uint32_t rng_get (void);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(machine_rng_get_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(machine_rng_get_obj);
|
||||
|
||||
#endif // __RANDOM_H
|
||||
|
|
2
conf.py
2
conf.py
|
@ -69,7 +69,7 @@ copyright = '2014-2016, MicroPython contributors (https://github.com/adafruit/mi
|
|||
# The short X.Y version.
|
||||
version = '1.8'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.8.5'
|
||||
release = '1.8.6'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
|
@ -71,13 +71,16 @@ and developers, who can diagnose themselves any issues arising from
|
|||
modifying the standard process).
|
||||
|
||||
Once the filesystem is mounted, ``boot.py`` is executed from it. The standard
|
||||
version of this file is created during first-time module set up and by
|
||||
default starts up a WebREPL daemon to handle incoming connections. This
|
||||
file is customizable by end users (for example, you may want to disable
|
||||
WebREPL for extra security, or add other services which should be run on
|
||||
version of this file is created during first-time module set up and has
|
||||
commands to start a WebREPL daemon (disabled by default, configurable
|
||||
with ``webrepl_setup`` module), etc. This
|
||||
file is customizable by end users (for example, you may want to set some
|
||||
parameters or add other services which should be run on
|
||||
a module start-up). But keep in mind that incorrect modifications to boot.py
|
||||
may still lead to boot loops or lock ups, requiring to reflash a module
|
||||
from scratch.
|
||||
from scratch. (In particular, it's recommended that you use either
|
||||
``webrepl_setup`` module or manual editing to configure WebREPL, but not
|
||||
both).
|
||||
|
||||
As a final step of boot procedure, ``main.py`` is executed from filesystem,
|
||||
if exists. This file is a hook to start up a user application each time
|
||||
|
|
|
@ -83,7 +83,7 @@ Use the :mod:`time <utime>` module::
|
|||
time.sleep_ms(500) # sleep for 500 milliseconds
|
||||
time.sleep_us(10) # sleep for 10 microseconds
|
||||
start = time.ticks_ms() # get millisecond counter
|
||||
delta = time.ticks_diff(start, time.ticks_ms()) # compute time difference
|
||||
delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference
|
||||
|
||||
Timers
|
||||
------
|
||||
|
@ -336,29 +336,27 @@ WebREPL (web browser interactive prompt)
|
|||
WebREPL (REPL over WebSockets, accessible via a web browser) is an
|
||||
experimental feature available in ESP8266 port. Download web client
|
||||
from https://github.com/micropython/webrepl (hosted version available
|
||||
at http://micropython.org/webrepl), and start the daemon on a device
|
||||
using::
|
||||
at http://micropython.org/webrepl), and configure it by executing::
|
||||
|
||||
import webrepl_setup
|
||||
|
||||
and following on-screen instructions. After reboot, it will be available
|
||||
for connection. If you disabled automatic start-up on boot, you may
|
||||
run configured daemon on demand using::
|
||||
|
||||
import webrepl
|
||||
webrepl.start()
|
||||
|
||||
(Release versions have it started on boot by default.)
|
||||
|
||||
On a first connection, you will be prompted to set password for future
|
||||
sessions to use.
|
||||
|
||||
The supported way to use WebREPL is by connecting to ESP8266 access point,
|
||||
but the daemon is also started on STA interface if it is active, so if your
|
||||
router is set up and works correctly, you may also use WebREPL while connected
|
||||
to your normal Internet access point (use the ESP8266 AP connection method
|
||||
if you face any issues).
|
||||
|
||||
WebREPL is an experimental feature and a work in progress, and has known
|
||||
issues.
|
||||
Besides terminal/command prompt access, WebREPL also has provision for file
|
||||
transfer (both upload and download). Web client has buttons for the
|
||||
corresponding functions, or you can use command-line client ``webrepl_cli.py``
|
||||
from the repository above.
|
||||
|
||||
There's also provision to transfer (both upload and download)
|
||||
files over WebREPL connection, but it has even more experimental status
|
||||
than the WebREPL terminal mode. It is still a practical way to
|
||||
get script files onto ESP8266, so give it a try using ``webrepl_cli.py``
|
||||
from the repository above. See the MicroPython forum for other
|
||||
community-supported alternatives to transfer files to ESP8266.
|
||||
See the MicroPython forum for other community-supported alternatives
|
||||
to transfer files to ESP8266.
|
||||
|
|
|
@ -64,7 +64,6 @@ device starts up.
|
|||
Accessing the filesystem via WebREPL
|
||||
------------------------------------
|
||||
|
||||
You can access the filesystem over WebREPL using the provided command-line
|
||||
tool. This tool is found at `<https://github.com/micropython/webrepl>`__
|
||||
and is called webrepl_cli.py. Please refer to that program for information
|
||||
on how to use it.
|
||||
You can access the filesystem over WebREPL using the web client in a browser
|
||||
or via the command-line tool. Please refer to Quick Reference and Tutorial
|
||||
sections for more information about WebREPL.
|
||||
|
|
|
@ -54,7 +54,7 @@ device before putting on new MicroPython firmware.
|
|||
|
||||
Currently we only support esptool.py to copy across the firmware. You can find
|
||||
this tool here: `<https://github.com/themadinventor/esptool/>`__, or install it
|
||||
using pip::
|
||||
using pip (at least version 1.2.1 is required)::
|
||||
|
||||
pip install esptool
|
||||
|
||||
|
@ -69,7 +69,7 @@ Using esptool.py you can erase the flash with the command::
|
|||
|
||||
And then deploy the new firmware using::
|
||||
|
||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=8m 0 esp8266-2016-05-03-v1.8.bin
|
||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-2016-05-03-v1.8.bin
|
||||
|
||||
You might need to change the "port" setting to something else relevant for your
|
||||
PC. You may also need to reduce the baudrate if you get errors when flashing
|
||||
|
@ -80,7 +80,7 @@ For some boards with a particular FlashROM configuration (e.g. some variants of
|
|||
a NodeMCU board) you may need to use the following command to deploy
|
||||
the firmware (note the ``-fm dio`` option)::
|
||||
|
||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=8m -fm dio 0 esp8266-2016-05-03-v1.8.bin
|
||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect -fm dio 0 esp8266-2016-05-03-v1.8.bin
|
||||
|
||||
If the above commands run without error then MicroPython should be installed on
|
||||
your board!
|
||||
|
@ -138,6 +138,8 @@ after it, here are troubleshooting recommendations:
|
|||
* If lower baud rate didn't help, you may want to try older version of
|
||||
esptool.py, which had a different programming algorithm::
|
||||
pip install esptool==1.0.1
|
||||
This version doesn't support ``--flash_size=detect`` option, so you will
|
||||
need to specify FlashROM size explicitly (in megabits).
|
||||
|
||||
* The ``--flash_size`` option in the commands above is mandatory. Omitting
|
||||
it will lead to a corrupted firmware.
|
||||
|
|
|
@ -41,6 +41,18 @@ For your convenience, WebREPL client is hosted at
|
|||
locally from the the GitHub repository
|
||||
`<https://github.com/micropython/webrepl>`__ .
|
||||
|
||||
Before connecting to WebREPL, you should set a password and enable it via
|
||||
a normal serial connection. Initial versions of MicroPython for ESP8266
|
||||
came with WebREPL automatically enabled on the boot and with the
|
||||
ability to set a password via WiFi on the first connection, but as WebREPL
|
||||
was becoming more widely known and popular, the initial setup has switched
|
||||
to a wired connection for improved security::
|
||||
|
||||
import webrepl_setup
|
||||
|
||||
Follow the on-screen instructions and prompts. To make any changes active,
|
||||
you will need to reboot your device.
|
||||
|
||||
To use WebREPL connect your computer to the ESP8266's access point
|
||||
(MicroPython-xxxxxx, see the previous section about this). If you have
|
||||
already reconfigured your ESP8266 to connect to a router then you can
|
||||
|
@ -49,19 +61,11 @@ skip this part.
|
|||
Once you are on the same network as the ESP8266 you click the "Connect" button
|
||||
(if you are connecting via a router then you may need to change the IP address,
|
||||
by default the IP address is correct when connected to the ESP8266's access
|
||||
point). If the connection succeeds then you should see a welcome message.
|
||||
point). If the connection succeeds then you should see a password prompt.
|
||||
|
||||
On the first connection you need to set a password. Make sure that the
|
||||
terminal widget is selected by clicking on it, and then follow prompts to
|
||||
type in your password twice (they should match each other). Then ESP8266
|
||||
will then reboot with the password applied (the WiFi will go down but come
|
||||
back up again). Note that some modules may have troubles rebooting
|
||||
automatically and need reset button press or power cycle (do this if
|
||||
you don't see ESP8266 access point appearing in a minute or so).
|
||||
|
||||
You should then click the "Connect" button again, and enter your password
|
||||
to connect. If you type in the correct password you should get a prompt
|
||||
looking like ``>>>``. You can now start typing Python commands!
|
||||
Once you type the password configured at the setup step above, press Enter once
|
||||
more and you should get a prompt looking like ``>>>``. You can now start
|
||||
typing Python commands!
|
||||
|
||||
Using the REPL
|
||||
--------------
|
||||
|
|
|
@ -28,6 +28,11 @@ All builtin functions are described here. They are also available via
|
|||
|
||||
.. class:: complex()
|
||||
|
||||
.. function:: delattr(obj, name)
|
||||
|
||||
The argument *name* should be a string, and this function deletes the named
|
||||
attribute from the object given by *obj*.
|
||||
|
||||
.. class:: dict()
|
||||
|
||||
.. function:: dir()
|
||||
|
@ -110,6 +115,10 @@ All builtin functions are described here. They are also available via
|
|||
|
||||
.. function:: setattr()
|
||||
|
||||
.. class:: slice()
|
||||
|
||||
The *slice* builtin is the type that slice objects have.
|
||||
|
||||
.. function:: sorted()
|
||||
|
||||
.. function:: staticmethod()
|
||||
|
|
|
@ -51,8 +51,8 @@ library.
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
array.rst
|
||||
builtins.rst
|
||||
array.rst
|
||||
cmath.rst
|
||||
gc.rst
|
||||
math.rst
|
||||
|
@ -76,8 +76,8 @@ library.
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
array.rst
|
||||
builtins.rst
|
||||
array.rst
|
||||
cmath.rst
|
||||
gc.rst
|
||||
math.rst
|
||||
|
@ -101,8 +101,8 @@ library.
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
array.rst
|
||||
builtins.rst
|
||||
array.rst
|
||||
gc.rst
|
||||
select.rst
|
||||
sys.rst
|
||||
|
@ -119,8 +119,8 @@ library.
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
array.rst
|
||||
builtins.rst
|
||||
array.rst
|
||||
gc.rst
|
||||
math.rst
|
||||
sys.rst
|
||||
|
|
|
@ -3,16 +3,44 @@
|
|||
class Pin -- control I/O pins
|
||||
=============================
|
||||
|
||||
A pin is the basic object to control I/O pins (also known as GPIO -
|
||||
general-purpose input/output). It has methods to set
|
||||
the mode of the pin (input, output, etc) and methods to get and set the
|
||||
digital logic level. For analog control of a pin, see the ADC class.
|
||||
A pin object is used to control I/O pins (also known as GPIO - general-purpose
|
||||
input/output). Pin objects are commonly associated with a physical pin that can
|
||||
drive an output voltage and read input voltages. The pin class has methods to set the mode of
|
||||
the pin (IN, OUT, etc) and methods to get and set the digital logic level.
|
||||
For analog control of a pin, see the :class:`ADC` class.
|
||||
|
||||
Usage Model:
|
||||
A pin object is constructed by using an identifier which unambiguously
|
||||
specifies a certain I/O pin. The allowed forms of the identifier and the
|
||||
physical pin that the identifier maps to are port-specific. Possibilities
|
||||
for the identifier are an integer, a string or a tuple with port and pin
|
||||
number.
|
||||
|
||||
Usage Model::
|
||||
|
||||
from machine import Pin
|
||||
|
||||
# create an output pin on pin #0
|
||||
p0 = Pin(0, Pin.OUT)
|
||||
|
||||
# set the value low then high
|
||||
p0.value(0)
|
||||
p0.value(1)
|
||||
|
||||
# create an input pin on pin #2, with a pull up resistor
|
||||
p2 = Pin(2, Pin.IN, Pin.PULL_UP)
|
||||
|
||||
# read and print the pin value
|
||||
print(p2.value())
|
||||
|
||||
# reconfigure pin #0 in input mode
|
||||
p0.mode(p0.IN)
|
||||
|
||||
# configure an irq callback
|
||||
p0.irq(lambda p:print(p))
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
Board pins are identified by their string id::
|
||||
On the WiPy board the pins are identified by their string id::
|
||||
|
||||
from machine import Pin
|
||||
g = machine.Pin('GP9', mode=Pin.OUT, pull=None, drive=Pin.MED_POWER, alt=-1)
|
||||
|
@ -40,174 +68,224 @@ Usage Model:
|
|||
All pin objects go through the pin mapper to come up with one of the
|
||||
gpio pins.
|
||||
|
||||
.. only:: port_esp8266
|
||||
For the ``drive`` parameter the strengths are:
|
||||
|
||||
::
|
||||
- ``Pin.LOW_POWER`` - 2mA drive capability.
|
||||
- ``Pin.MED_POWER`` - 4mA drive capability.
|
||||
- ``Pin.HIGH_POWER`` - 6mA drive capability.
|
||||
|
||||
from machine import Pin
|
||||
For the ``alt`` parameter please refer to the pinout and alternate functions
|
||||
table at <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
|
||||
for the specific alternate functions that each pin supports.
|
||||
|
||||
# create an output pin on GPIO0
|
||||
p0 = Pin(0, Pin.OUT)
|
||||
p0.value(0)
|
||||
p0.value(1)
|
||||
For interrupts, the ``priority`` can take values in the range 1-7. And the
|
||||
``wake`` parameter has the following properties:
|
||||
|
||||
# create an input pin on GPIO2
|
||||
p2 = Pin(2, Pin.IN, Pin.PULL_UP)
|
||||
print(p2.value())
|
||||
- If ``wake_from=machine.Sleep.ACTIVE`` any pin can wake the board.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, GP17`` or ``GP24`` can wake the board. Note that only 1
|
||||
of this pins can be enabled as a wake source at the same time, so, only
|
||||
the last enabled pin as a ``machine.Sleep.SUSPENDED`` wake source will have effect.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, ``GP17`` and ``GP24`` can wake the board. In this case all of the
|
||||
6 pins can be enabled as a ``machine.Sleep.HIBERNATE`` wake source at the same time.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: Pin(id, ...)
|
||||
.. class:: Pin(id, mode=-1, pull=-1, \*, value, drive, alt)
|
||||
|
||||
Create a new Pin object associated with the id. If additional arguments are given,
|
||||
they are used to initialise the pin. See :meth:`Pin.init`.
|
||||
Access the pin peripheral (GPIO pin) associated with the given ``id``. If
|
||||
additional arguments are given in the constructor then they are used to initialise
|
||||
the pin. Any settings that are not specified will remain in their previous state.
|
||||
|
||||
The arguments are:
|
||||
|
||||
- ``id`` is mandatory and can be an arbitrary object. Among possible value
|
||||
types are: int (an internal Pin identifier), str (a Pin name), and tuple
|
||||
(pair of [port, pin]).
|
||||
|
||||
- ``mode`` specifies the pin mode, which can be one of:
|
||||
|
||||
- ``Pin.IN`` - Pin is configured for input. If viewed as an output the pin
|
||||
is in high-impedance state.
|
||||
|
||||
- ``Pin.OUT`` - Pin is configured for (normal) output.
|
||||
|
||||
- ``Pin.OPEN_DRAIN`` - Pin is configured for open-drain output. Open-drain
|
||||
output works in the following way: if the output value is set to 0 the pin
|
||||
is active at a low level; if the output value is 1 the pin is in a high-impedance
|
||||
state. Not all ports implement this mode, or some might only on certain pins.
|
||||
|
||||
- ``Pin.ALT`` - Pin is configured to perform an alternative function, which is
|
||||
port specific. For a pin configured in such a way any other Pin methods
|
||||
(except :meth:`Pin.init`) are not applicable (calling them will lead to undefined,
|
||||
or a hardware-specific, result). Not all ports implement this mode.
|
||||
|
||||
- ``Pin.ALT_OPEN_DRAIN`` - The Same as ``Pin.ALT``, but the pin is configured as
|
||||
open-drain. Not all ports implement this mode.
|
||||
|
||||
- ``pull`` specifies if the pin has a (weak) pull resistor attached, and can be
|
||||
one of:
|
||||
|
||||
- ``None`` - No pull up or down resistor.
|
||||
- ``Pin.PULL_UP`` - Pull up resistor enabled.
|
||||
- ``Pin.PULL_DOWN`` - Pull down resistor enabled.
|
||||
|
||||
- ``value`` is valid only for Pin.OUT and Pin.OPEN_DRAIN modes and specifies initial
|
||||
output pin value if given, otherwise the state of the pin peripheral remains
|
||||
unchanged.
|
||||
|
||||
- ``drive`` specifies the output power of the pin and can be one of: ``Pin.LOW_POWER``,
|
||||
``Pin.MED_POWER`` or ``Pin.HIGH_POWER``. The actual current driving capabilities
|
||||
are port dependent. Not all ports implement this argument.
|
||||
|
||||
- ``alt`` specifies an alternate function for the pin and the values it can take are
|
||||
port dependent. This argument is valid only for ``Pin.ALT`` and ``Pin.ALT_OPEN_DRAIN``
|
||||
modes. It may be used when a pin supports more than one alternate function. If only
|
||||
one pin alternate function is supported the this argument is not required. Not all
|
||||
ports implement this argument.
|
||||
|
||||
As specified above, the Pin class allows to set an alternate function for a particular
|
||||
pin, but it does not specify any further operations on such a pin. Pins configured in
|
||||
alternate-function mode are usually not used as GPIO but are instead driven by other
|
||||
hardware peripherals. The only operation supported on such a pin is re-initialising,
|
||||
by calling the constructor or :meth:`Pin.init` method. If a pin that is configured in
|
||||
alternate-function mode is re-initialised with ``Pin.IN``, ``Pin.OUT``, or
|
||||
``Pin.OPEN_DRAIN``, the alternate function will be removed from the pin.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. only:: port_wipy
|
||||
.. method:: Pin.init(mode=-1, pull=-1, \*, value, drive, alt)
|
||||
|
||||
.. method:: Pin.init(mode, pull, \*, drive, alt)
|
||||
|
||||
Initialise the pin:
|
||||
Re-initialise the pin using the given parameters. Only those arguments that
|
||||
are specified will be set. The rest of the pin peripheral state will remain
|
||||
unchanged. See the constructor documentation for details of the arguments.
|
||||
|
||||
- ``mode`` can be one of:
|
||||
Returns ``None``.
|
||||
|
||||
- ``Pin.IN`` - input pin.
|
||||
- ``Pin.OUT`` - output pin in push-pull mode.
|
||||
- ``Pin.OPEN_DRAIN`` - output pin in open-drain mode.
|
||||
- ``Pin.ALT`` - pin mapped to an alternate function.
|
||||
- ``Pin.ALT_OPEN_DRAIN`` - pin mapped to an alternate function in open-drain mode.
|
||||
.. method:: Pin.value([x])
|
||||
|
||||
- ``pull`` can be one of:
|
||||
This method allows to set and get the value of the pin, depending on whether
|
||||
the argument ``x`` is supplied or not.
|
||||
|
||||
- ``None`` - no pull up or down resistor.
|
||||
- ``Pin.PULL_UP`` - pull up resistor enabled.
|
||||
- ``Pin.PULL_DOWN`` - pull down resistor enabled.
|
||||
If the argument is omitted then this method gets the digital logic level of
|
||||
the pin, returning 0 or 1 corresponding to low and high voltage signals
|
||||
respectively. The behaviour of this method depends on the mode of the pin:
|
||||
|
||||
- ``drive`` can be one of:
|
||||
- ``Pin.IN`` - The method returns the actual input value currently present
|
||||
on the pin.
|
||||
- ``Pin.OUT`` - The behaviour and return value of the method is undefined.
|
||||
- ``Pin.OPEN_DRAIN`` - If the pin is in state '0' then the behaviour and
|
||||
return value of the method is undefined. Otherwise, if the pin is in
|
||||
state '1', the method returns the actual input value currently present
|
||||
on the pin.
|
||||
|
||||
- ``Pin.LOW_POWER`` - 2mA drive capability.
|
||||
- ``Pin.MED_POWER`` - 4mA drive capability.
|
||||
- ``Pin.HIGH_POWER`` - 6mA drive capability.
|
||||
If the argument is supplied then this method sets the digital logic level of
|
||||
the pin. The argument ``x`` can be anything that converts to a boolean.
|
||||
If it converts to ``True``, the pin is set to state '1', otherwise it is set
|
||||
to state '0'. The behaviour of this method depends on the mode of the pin:
|
||||
|
||||
- ``alt`` is the number of the alternate function. Please refer to the
|
||||
`pinout and alternate functions table. <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
|
||||
for the specific alternate functions that each pin supports.
|
||||
- ``Pin.IN`` - The value is stored in the output buffer for the pin. The
|
||||
pin state does not change, it remains in the high-impedance state. The
|
||||
stored value will become active on the pin as soon as it is changed to
|
||||
``Pin.OUT`` or ``Pin.OPEN_DRAIN`` mode.
|
||||
- ``Pin.OUT`` - The output buffer is set to the given value immediately.
|
||||
- ``Pin.OPEN_DRAIN`` - If the value is '0' the pin is set to a low voltage
|
||||
state. Otherwise the pin is set to high-impedance state.
|
||||
|
||||
Returns: ``None``.
|
||||
When setting the value this method returns ``None``.
|
||||
|
||||
.. method:: Pin.id()
|
||||
.. method:: Pin.out_value()
|
||||
|
||||
Get the pin id.
|
||||
Return the value stored in the output buffer of a pin, regardless of its mode.
|
||||
|
||||
.. only:: port_esp8266
|
||||
Not all ports implement this method.
|
||||
|
||||
.. method:: Pin.init(mode, pull=None, \*, value)
|
||||
.. method:: Pin.__call__([x])
|
||||
|
||||
Initialise the pin:
|
||||
Pin objects are callable. The call method provides a (fast) shortcut to set
|
||||
and get the value of the pin. It is equivalent to Pin.value([x]).
|
||||
See :meth:`Pin.value` for more details.
|
||||
|
||||
- `mode` can be one of:
|
||||
.. method:: Pin.toggle()
|
||||
|
||||
- ``Pin.IN`` - input pin.
|
||||
- ``Pin.OUT`` - output pin in push-pull mode.
|
||||
Toggle the output value of the pin. Equivalent to ``pin.value(not pin.out_value())``.
|
||||
Returns ``None``.
|
||||
|
||||
- `pull` can be one of:
|
||||
Not all ports implement this method.
|
||||
|
||||
- ``None`` - no pull up or down resistor.
|
||||
- ``Pin.PULL_UP`` - pull up resistor enabled.
|
||||
Availability: WiPy.
|
||||
|
||||
- if `value` is given then it is the output value to set the pin
|
||||
if it is in output mode.
|
||||
.. method:: Pin.id()
|
||||
|
||||
.. method:: Pin.value([value])
|
||||
Get the pin identifier. This may return the ``id`` as specified in the
|
||||
constructor. Or it may return a canonical software-specific pin id.
|
||||
|
||||
Get or set the digital logic level of the pin:
|
||||
.. method:: Pin.mode([mode])
|
||||
|
||||
- With no argument, return 0 or 1 depending on the logic level of the pin.
|
||||
- With ``value`` given, set the logic level of the pin. ``value`` can be
|
||||
anything that converts to a boolean. If it converts to ``True``, the pin
|
||||
is set high, otherwise it is set low.
|
||||
Get or set the pin mode.
|
||||
See the constructor documentation for details of the ``mode`` argument.
|
||||
|
||||
.. method:: Pin.__call__([value])
|
||||
.. method:: Pin.pull([pull])
|
||||
|
||||
Pin objects are callable. The call method provides a (fast) shortcut to set and get the value of the pin.
|
||||
See :func:`Pin.value` for more details.
|
||||
Get or set the pin pull state.
|
||||
See the constructor documentation for details of the ``pull`` argument.
|
||||
|
||||
.. method:: Pin.alt_list()
|
||||
.. method:: Pin.drive([drive])
|
||||
|
||||
Returns a list of the alternate functions supported by the pin. List items are
|
||||
a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
|
||||
Get or set the pin drive strength.
|
||||
See the constructor documentation for details of the ``drive`` argument.
|
||||
|
||||
Availability: WiPy.
|
||||
Not all ports implement this method.
|
||||
|
||||
Availability: WiPy.
|
||||
|
||||
.. method:: Pin.irq(handler=None, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING), \*, priority=1, wake=None)
|
||||
|
||||
Configure an interrupt handler to be called when the trigger source of the
|
||||
pin is active. If the pin mode is ``Pin.IN`` then the trigger source is
|
||||
the external value on the pin. If the pin mode is ``Pin.OUT`` then the
|
||||
trigger source is the output buffer of the pin. Otherwise, if the pin mode
|
||||
is ``Pin.OPEN_DRAIN`` then the trigger source is the output buffer for
|
||||
state '0' and the external pin value for state '1'.
|
||||
|
||||
The arguments are:
|
||||
|
||||
- ``handler`` is an optional function to be called when the interrupt
|
||||
triggers.
|
||||
|
||||
- ``trigger`` configures the event which can generate an interrupt.
|
||||
Possible values are:
|
||||
|
||||
- ``Pin.IRQ_FALLING`` interrupt on falling edge.
|
||||
- ``Pin.IRQ_RISING`` interrupt on rising edge.
|
||||
- ``Pin.IRQ_LOW_LEVEL`` interrupt on low level.
|
||||
- ``Pin.IRQ_HIGH_LEVEL`` interrupt on high level.
|
||||
|
||||
These values can be OR'ed together to trigger on multiple events.
|
||||
|
||||
- ``priority`` sets the priority level of the interrupt. The values it
|
||||
can take are port-specific, but higher values always represent higher
|
||||
priorities.
|
||||
|
||||
- ``wake`` selects the power mode in which this interrupt can wake up the
|
||||
system. It can be ``machine.IDLE``, ``machine.SLEEP`` or ``machine.DEEPSLEEP``.
|
||||
These values can also be OR'ed together to make a pin generate interrupts in
|
||||
more than one power mode.
|
||||
|
||||
This method returns a callback object.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. method:: Pin.toggle()
|
||||
.. method:: Pin.alt_list()
|
||||
|
||||
Toggle the value of the pin.
|
||||
Returns a list of the alternate functions supported by the pin. List items are
|
||||
a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
|
||||
|
||||
.. method:: Pin.mode([mode])
|
||||
Availability: WiPy.
|
||||
|
||||
Get or set the pin mode.
|
||||
|
||||
.. method:: Pin.pull([pull])
|
||||
|
||||
Get or set the pin pull.
|
||||
|
||||
.. method:: Pin.drive([drive])
|
||||
|
||||
Get or set the pin drive strength.
|
||||
|
||||
.. method:: Pin.irq(\*, trigger, priority=1, handler=None, wake=None)
|
||||
|
||||
Create a callback to be triggered when the input level at the pin changes.
|
||||
|
||||
- ``trigger`` configures the pin level which can generate an interrupt. Possible values are:
|
||||
|
||||
- ``Pin.IRQ_FALLING`` interrupt on falling edge.
|
||||
- ``Pin.IRQ_RISING`` interrupt on rising edge.
|
||||
- ``Pin.IRQ_LOW_LEVEL`` interrupt on low level.
|
||||
- ``Pin.IRQ_HIGH_LEVEL`` interrupt on high level.
|
||||
|
||||
The values can be *ORed* together, for instance mode=Pin.IRQ_FALLING | Pin.IRQ_RISING
|
||||
|
||||
- ``priority`` level of the interrupt. Can take values in the range 1-7.
|
||||
Higher values represent higher priorities.
|
||||
- ``handler`` is an optional function to be called when new characters arrive.
|
||||
- ``wakes`` selects the power mode in which this interrupt can wake up the
|
||||
board. Please note:
|
||||
|
||||
- If ``wake_from=machine.Sleep.ACTIVE`` any pin can wake the board.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, GP17`` or ``GP24`` can wake the board. Note that only 1
|
||||
of this pins can be enabled as a wake source at the same time, so, only
|
||||
the last enabled pin as a ``machine.Sleep.SUSPENDED`` wake source will have effect.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, ``GP17`` and ``GP24`` can wake the board. In this case all of the
|
||||
6 pins can be enabled as a ``machine.Sleep.HIBERNATE`` wake source at the same time.
|
||||
- Values can be ORed to make a pin generate interrupts in more than one power
|
||||
mode.
|
||||
|
||||
Returns a callback object.
|
||||
|
||||
.. only:: port_esp8266
|
||||
|
||||
.. method:: Pin.irq(\*, trigger, handler=None)
|
||||
|
||||
Create a callback to be triggered when the input level at the pin changes.
|
||||
|
||||
- ``trigger`` configures the pin level which can generate an interrupt. Possible values are:
|
||||
|
||||
- ``Pin.IRQ_FALLING`` interrupt on falling edge.
|
||||
- ``Pin.IRQ_RISING`` interrupt on rising edge.
|
||||
|
||||
The values can be OR'ed together to trigger on multiple events.
|
||||
|
||||
- ``handler`` is an optional function to be called when the interrupt triggers.
|
||||
|
||||
Returns a callback object.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
|
@ -239,7 +317,8 @@ not all constants are available on all ports.
|
|||
.. data:: Pin.PULL_UP
|
||||
Pin.PULL_DOWN
|
||||
|
||||
Selects the whether there is a pull up/down resistor.
|
||||
Selects whether there is a pull up/down resistor. Use the value
|
||||
``None`` for no pull.
|
||||
|
||||
.. data:: Pin.LOW_POWER
|
||||
Pin.MED_POWER
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
.. currentmodule:: machine
|
||||
|
||||
class SPI -- a Serial Peripheral Interface bus protocol
|
||||
=======================================================
|
||||
class SPI -- a Serial Peripheral Interface bus protocol (master side)
|
||||
=====================================================================
|
||||
|
||||
SPI is a serial protocol that is driven by a master. At the physical level,
|
||||
bus consistens of 3 lines: SCK, MOSI, MISO. Multiple devices can share the
|
||||
same bus. Each device should have a separate, 4th signal, SS (Slave Select),
|
||||
to select a particualr device on a bus with which communication takes place.
|
||||
Management of an SS signal should happen in user code (via machine.Pin class).
|
||||
SPI is a synchronous serial protocol that is driven by a master. At the
|
||||
physical level, a bus consists of 3 lines: SCK, MOSI, MISO. Multiple devices
|
||||
can share the same bus. Each device should have a separate, 4th signal,
|
||||
SS (Slave Select), to select a particualr device on a bus with which
|
||||
communication takes place. Management of an SS signal should happen in
|
||||
user code (via machine.Pin class).
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
|
@ -39,7 +40,7 @@ Constructors
|
|||
Methods
|
||||
-------
|
||||
|
||||
.. method:: SPI.init(baudrate=1000000, \*, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, pins=(CLK, MOSI, MISO), sck=None, mosi=None, miso=None)
|
||||
.. method:: SPI.init(baudrate=1000000, \*, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=None, mosi=None, miso=None, pins=(SCK, MOSI, MISO))
|
||||
|
||||
Initialise the SPI bus with the given parameters:
|
||||
|
||||
|
@ -47,14 +48,15 @@ Methods
|
|||
- ``polarity`` can be 0 or 1, and is the level the idle clock line sits at.
|
||||
- ``phase`` can be 0 or 1 to sample data on the first or second clock edge
|
||||
respectively.
|
||||
- ``bits`` is the width in bits of each transfer. Only 8 of is guaranteed to be supported by all hardware.
|
||||
- ``bits`` is the width in bits of each transfer. Only 8 is guaranteed to be supported by all hardware.
|
||||
- ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``.
|
||||
- ``pins`` is an optional tuple with the pins to assign to the SPI bus (deprecated, only for WiPy).
|
||||
- ``sck``, ``mosi``, ``miso`` are pins (machine.Pin) objects to use for bus signals. For most
|
||||
hardware SPI blocks (as selected by ``id`` parameter to the constructore), pins are fixed
|
||||
and cannot be changed. In some cases, hardware blocks allow 2-3 alternative pin sets for
|
||||
a hardware SPI block. Arbitrary pin assignments are possible only for a bitbanging SPI driver
|
||||
(``id``=-1).
|
||||
(``id`` = -1).
|
||||
- ``pins`` - WiPy port doesn't ``sck``, ``mosi``, ``miso`` arguments, and instead allows to
|
||||
specify them as a tuple of ``pins`` paramter.
|
||||
|
||||
.. method:: SPI.deinit()
|
||||
|
||||
|
|
|
@ -5,11 +5,12 @@
|
|||
.. module:: network
|
||||
:synopsis: network configuration
|
||||
|
||||
This module provides network drivers and routing configuration. Network
|
||||
drivers for specific hardware are available within this module and are
|
||||
used to configure a hardware network interface. Configured interfaces
|
||||
are then available for use via the :mod:`socket` module. To use this module
|
||||
the network build of firmware must be installed.
|
||||
This module provides network drivers and routing configuration. To use this
|
||||
module, a MicroPython variant/build with network capabilities must be installed.
|
||||
Network drivers for specific hardware are available within this module and are
|
||||
used to configure hardware network interface(s). Network services provided
|
||||
by configured interfaces are then available for use via the :mod:`socket`
|
||||
module.
|
||||
|
||||
For example::
|
||||
|
||||
|
@ -79,7 +80,7 @@ For example::
|
|||
class CC3K
|
||||
==========
|
||||
|
||||
This class provides a driver for CC3000 wifi modules. Example usage::
|
||||
This class provides a driver for CC3000 WiFi modules. Example usage::
|
||||
|
||||
import network
|
||||
nic = network.CC3K(pyb.SPI(2), pyb.Pin.board.Y5, pyb.Pin.board.Y4, pyb.Pin.board.Y3)
|
||||
|
@ -128,16 +129,16 @@ For example::
|
|||
|
||||
.. method:: cc3k.connect(ssid, key=None, \*, security=WPA2, bssid=None)
|
||||
|
||||
Connect to a wifi access point using the given SSID, and other security
|
||||
Connect to a WiFi access point using the given SSID, and other security
|
||||
parameters.
|
||||
|
||||
.. method:: cc3k.disconnect()
|
||||
|
||||
Disconnect from the wifi access point.
|
||||
Disconnect from the WiFi access point.
|
||||
|
||||
.. method:: cc3k.isconnected()
|
||||
|
||||
Returns True if connected to a wifi access point and has a valid IP address,
|
||||
Returns True if connected to a WiFi access point and has a valid IP address,
|
||||
False otherwise.
|
||||
|
||||
.. method:: cc3k.ifconfig()
|
||||
|
@ -323,7 +324,7 @@ For example::
|
|||
|
||||
.. method:: wlan.isconnected()
|
||||
|
||||
In case of STA mode, returns ``True`` if connected to a wifi access
|
||||
In case of STA mode, returns ``True`` if connected to a WiFi access
|
||||
point and has a valid IP address. In AP mode returns ``True`` when a
|
||||
station is connected. Returns ``False`` otherwise.
|
||||
|
||||
|
@ -348,7 +349,7 @@ For example::
|
|||
|
||||
# Set WiFi access point name (formally known as ESSID) and WiFi channel
|
||||
ap.config(essid='My AP', channel=11)
|
||||
# Queey params one by one
|
||||
# Query params one by one
|
||||
print(ap.config('essid'))
|
||||
print(ap.config('channel'))
|
||||
|
||||
|
@ -433,7 +434,7 @@ For example::
|
|||
|
||||
.. method:: wlan.connect(ssid, \*, auth=None, bssid=None, timeout=None)
|
||||
|
||||
Connect to a wifi access point using the given SSID, and other security
|
||||
Connect to a WiFi access point using the given SSID, and other security
|
||||
parameters.
|
||||
|
||||
- ``auth`` is a tuple with (sec, key). Security can be ``None``, ``WLAN.WEP``,
|
||||
|
@ -451,16 +452,16 @@ For example::
|
|||
|
||||
.. method:: wlan.disconnect()
|
||||
|
||||
Disconnect from the wifi access point.
|
||||
Disconnect from the WiFi access point.
|
||||
|
||||
.. method:: wlan.isconnected()
|
||||
|
||||
In case of STA mode, returns ``True`` if connected to a wifi access point and has a valid IP address.
|
||||
In case of STA mode, returns ``True`` if connected to a WiFi access point and has a valid IP address.
|
||||
In AP mode returns ``True`` when a station is connected, ``False`` otherwise.
|
||||
|
||||
.. method:: wlan.ifconfig(if_id=0, config=['dhcp' or configtuple])
|
||||
|
||||
With no parameters given eturns a 4-tuple of ``(ip, subnet_mask, gateway, DNS_server)``.
|
||||
With no parameters given returns a 4-tuple of ``(ip, subnet_mask, gateway, DNS_server)``.
|
||||
|
||||
if ``'dhcp'`` is passed as a parameter then the DHCP client is enabled and the IP params
|
||||
are negotiated with the AP.
|
||||
|
@ -498,10 +499,10 @@ For example::
|
|||
Create a callback to be triggered when a WLAN event occurs during ``machine.SLEEP``
|
||||
mode. Events are triggered by socket activity or by WLAN connection/disconnection.
|
||||
|
||||
- ``handler`` is the function that gets called when the irq is triggered.
|
||||
- ``handler`` is the function that gets called when the IRQ is triggered.
|
||||
- ``wake`` must be ``machine.SLEEP``.
|
||||
|
||||
Returns an irq object.
|
||||
Returns an IRQ object.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
|
|
@ -82,37 +82,128 @@ Functions
|
|||
|
||||
.. function:: ticks_ms()
|
||||
|
||||
Returns an increasing millisecond counter with arbitrary reference point,
|
||||
that wraps after some (unspecified) value. The value should be treated as
|
||||
opaque, suitable for use only with ticks_diff().
|
||||
Returns an increasing millisecond counter with an arbitrary reference point,
|
||||
that wraps around after some value. This value is not explicitly exposed,
|
||||
but we will refer to it as `TICKS_MAX` to simplify discussion. Period of
|
||||
the values is `TICKS_PERIOD = TICKS_MAX + 1`. `TICKS_PERIOD` is guaranteed
|
||||
to be a power of two, but otherwise may differ from port to port. The same
|
||||
period value is used for all of ticks_ms(), ticks_us(), ticks_cpu() functions
|
||||
(for simplicity). Thus, these functions will return a value in range
|
||||
[0 .. `TICKS_MAX`], inclusive, total `TICKS_PERIOD` values. Note that only
|
||||
non-negative values are used. For the most part, you should treat values
|
||||
returned by these functions as opaque. The only operations available for them
|
||||
are ``ticks_diff()`` and ``ticks_add()`` functions described below.
|
||||
|
||||
Note: Performing standard mathematical operations (+, -) or relational
|
||||
operators (<, <=, >, >=) directly on these value will lead to invalid
|
||||
result. Performing mathematical operations and then passing their results
|
||||
as arguments to ``ticks_diff()`` or ``ticks_add()`` will also lead to
|
||||
invalid results from the latter functions.
|
||||
|
||||
.. function:: ticks_us()
|
||||
|
||||
Just like ``ticks_ms`` above, but in microseconds.
|
||||
|
||||
.. only:: port_wipy or port_pyboard
|
||||
.. function:: ticks_cpu()
|
||||
|
||||
.. function:: ticks_cpu()
|
||||
Similar to ``ticks_ms`` and ``ticks_us``, but with the highest possible resolution
|
||||
in the system. This is usually CPU clocks, and that's why the function is named that
|
||||
way. But it doesn't have to a CPU clock, some other timing source available in a
|
||||
system (e.g. high-resolution timer) can be used instead. The exact timing unit
|
||||
(resolution) of this function is not specified on ``utime`` module level, but
|
||||
documentation for a specific port may provide more specific information. This
|
||||
function is intended for very fine benchmarking or very tight real-time loops.
|
||||
Avoid using it in portable code.
|
||||
|
||||
Similar to ``ticks_ms`` and ``ticks_us``, but with higher resolution (usually CPU clocks).
|
||||
Availability: Not every port implements this function.
|
||||
|
||||
.. only:: port_unix or port_pyboard or port_wipy or port_esp8266
|
||||
|
||||
.. function:: ticks_diff(old, new)
|
||||
.. function:: ticks_add(ticks, delta)
|
||||
|
||||
Measure period between consecutive calls to ticks_ms(), ticks_us(), or ticks_cpu().
|
||||
The value returned by these functions may wrap around at any time, so directly
|
||||
subtracting them is not supported. ticks_diff() should be used instead. "old" value should
|
||||
actually precede "new" value in time, or result is undefined. This function should not be
|
||||
used to measure arbitrarily long periods of time (because ticks_*() functions wrap around
|
||||
and usually would have short period). The expected usage pattern is implementing event
|
||||
polling with timeout::
|
||||
Offset ticks value by a given number, which can be either positive or negative.
|
||||
Given a ``ticks`` value, this function allows to calculate ticks value ``delta``
|
||||
ticks before or after it, following modular-arithmetic definition of tick values
|
||||
(see ``ticks_ms()`` above). ``ticks`` parameter must be a direct result of call
|
||||
to ``tick_ms()``, ``ticks_us()``, ``ticks_cpu()`` functions (or from previous
|
||||
call to ``ticks_add()``). However, ``delta`` can be an arbitrary integer number
|
||||
or numeric expression. ``ticks_add()`` is useful for calculating deadlines for
|
||||
events/tasks. (Note: you must use ``ticks_diff()`` function to work with
|
||||
deadlines.)
|
||||
|
||||
Examples::
|
||||
|
||||
# Find out what ticks value there was 100ms ago
|
||||
print(tick_add(time.ticks_ms(), -100))
|
||||
|
||||
# Calculate deadline for operation and test for it
|
||||
deadline = tick_add(time.ticks_ms(), 200)
|
||||
while ticks_diff(deadline, time.ticks_ms()) > 0:
|
||||
do_a_little_of_something()
|
||||
|
||||
# Find out TICKS_MAX used by this port
|
||||
print(tick_add(0, -1))
|
||||
|
||||
|
||||
.. function:: ticks_diff(ticks1, ticks2)
|
||||
|
||||
Measure ticks difference between values returned from ticks_ms(), ticks_us(), or ticks_cpu()
|
||||
functions. The argument order is the same as for subtraction operator,
|
||||
``tick_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``. However, values returned by
|
||||
ticks_ms(), etc. functions may wrap around, so directly using subtraction on them will
|
||||
produce incorrect result. That is why ticks_diff() is needed, it implements modular
|
||||
(or more specifically, ring) arithmetics to produce correct result even for wrap-around
|
||||
values (as long as they not too distant inbetween, see below). The function returns
|
||||
**signed** value in the range [`-TICKS_PERIOD/2` .. `TICKS_PERIOD/2-1`] (that's a typical
|
||||
range definition for two's-complement signed binary integers). If the result is negative,
|
||||
it means that `ticks1` occured earlier in time than `ticks2`. Otherwise, it means that
|
||||
`ticks1` occured after `ticks2`. This holds `only` if `ticks1` and `ticks2` are apart from
|
||||
each other for no more than `TICKS_PERIOD/2-1` ticks. If that does not hold, incorrect
|
||||
result will be returned. Specifically, if 2 tick values are apart for `TICKS_PERIOD/2-1`
|
||||
ticks, that value will be returned by the function. However, if `TICKS_PERIOD/2` of
|
||||
real-time ticks has passed between them, the function will return `-TICKS_PERIOD/2`
|
||||
instead, i.e. result value will wrap around to the negative range of possible values.
|
||||
|
||||
Informal rationale of the constraints above: Suppose you are locked in a room with no
|
||||
means to monitor passing of time except a standard 12-notch clock. Then if you look at
|
||||
dial-plate now, and don't look again for another 13 hours (e.g., if you fall for a
|
||||
long sleep), then once you finally look again, it may seem to you that only 1 hour
|
||||
has passed. To avoid this mistake, just look at the clock regularly. Your application
|
||||
should do the same. "Too long sleep" metaphor also maps directly to application
|
||||
behavior: don't let your application run any single task for too long. Run tasks
|
||||
in steps, and do time-keeping inbetween.
|
||||
|
||||
``ticks_diff()`` is designed to accommodate various usage patterns, among them:
|
||||
|
||||
Polling with timeout. In this case, the order of events is known, and you will deal
|
||||
only with positive results of ``ticks_diff()``::
|
||||
|
||||
# Wait for GPIO pin to be asserted, but at most 500us
|
||||
start = time.ticks_us()
|
||||
while pin.value() == 0:
|
||||
if time.ticks_diff(time.ticks_us(), start) > 500:
|
||||
raise TimeoutError
|
||||
|
||||
Scheduling events. In this case, ``ticks_diff()`` result may be negative
|
||||
if an event is overdue::
|
||||
|
||||
# This code snippet is not optimized
|
||||
now = time.ticks_ms()
|
||||
scheduled_time = task.scheduled_time()
|
||||
if ticks_diff(now, scheduled_time) > 0:
|
||||
print("Too early, let's nap")
|
||||
sleep_ms(ticks_diff(now, scheduled_time))
|
||||
task.run()
|
||||
elif ticks_diff(now, scheduled_time) == 0:
|
||||
print("Right at time!")
|
||||
task.run()
|
||||
elif ticks_diff(now, scheduled_time) < 0:
|
||||
print("Oops, running late, tell task to run faster!")
|
||||
task.run(run_faster=true)
|
||||
|
||||
Note: Do not pass ``time()`` values to ``ticks_diff()``, and should use
|
||||
normal mathematical operations on them. But note that ``time()`` may (and will)
|
||||
also overflow. This is known as https://en.wikipedia.org/wiki/Year_2038_problem .
|
||||
|
||||
# Wait for GPIO pin to be asserted, but at most 500us
|
||||
start = time.ticks_us()
|
||||
while pin.value() == 0:
|
||||
if time.ticks_diff(start, time.ticks_us()) > 500:
|
||||
raise TimeoutError
|
||||
|
||||
.. function:: time()
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ Use the :mod:`time <utime>` module::
|
|||
time.sleep_ms(500) # sleep for 500 milliseconds
|
||||
time.sleep_us(10) # sleep for 10 microseconds
|
||||
start = time.ticks_ms() # get value of millisecond counter
|
||||
delta = time.ticks_diff(start, time.ticks_ms()) # compute time difference
|
||||
delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference
|
||||
|
||||
LEDs
|
||||
----
|
||||
|
|
|
@ -132,7 +132,7 @@ The following enables any function or method to be timed by adding an
|
|||
def new_func(*args, **kwargs):
|
||||
t = time.ticks_us()
|
||||
result = f(*args, **kwargs)
|
||||
delta = time.ticks_diff(t, time.ticks_us())
|
||||
delta = time.ticks_diff(time.ticks_us(), t)
|
||||
print('Function {} Time = {:6.3f}ms'.format(myname, delta/1000))
|
||||
return result
|
||||
return new_func
|
||||
|
|
|
@ -99,7 +99,7 @@ STATIC tSpiInformation sSpiInformation;
|
|||
STATIC char spi_buffer[CC3000_RX_BUFFER_SIZE];
|
||||
unsigned char wlan_tx_buffer[CC3000_TX_BUFFER_SIZE];
|
||||
|
||||
STATIC const mp_obj_fun_builtin_t irq_callback_obj;
|
||||
STATIC const mp_obj_fun_builtin_fixed_t irq_callback_obj;
|
||||
|
||||
// set the pins to use to communicate with the CC3000
|
||||
// the arguments must be of type pin_obj_t* and SPI_HandleTypeDef*
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#include "py/obj.h"
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(dht_readinto_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(dht_readinto_obj);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""NRF24L01 driver for Micro Python
|
||||
"""
|
||||
|
||||
from micropython import const
|
||||
import pyb
|
||||
|
||||
# nRF24L01+ registers
|
||||
|
|
|
@ -21,6 +21,7 @@ Example usage on ESP8266:
|
|||
|
||||
"""
|
||||
|
||||
from micropython import const
|
||||
import time
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ QSTR_DEFS = qstrdefsport.h #$(BUILD)/pins_qstr.h
|
|||
|
||||
MICROPY_PY_USSL = 1
|
||||
MICROPY_SSL_AXTLS = 1
|
||||
MICROPY_FATFS = 1
|
||||
MICROPY_PY_BTREE = 1
|
||||
|
||||
FROZEN_DIR = scripts
|
||||
|
@ -13,9 +14,6 @@ FROZEN_MPY_DIR = modules
|
|||
# include py core make definitions
|
||||
include ../py/py.mk
|
||||
|
||||
MPY_CROSS = ../mpy-cross/mpy-cross
|
||||
MPY_TOOL = ../tools/mpy-tool.py
|
||||
|
||||
PORT ?= /dev/ttyACM0
|
||||
BAUD ?= 115200
|
||||
FLASH_MODE ?= qio
|
||||
|
@ -45,7 +43,8 @@ CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \
|
|||
CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
|
||||
$(CFLAGS_XTENSA) $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
|
||||
|
||||
LDFLAGS = -nostdlib -T esp8266.ld -Map=$(@:.elf=.map) --cref
|
||||
LDSCRIPT = esp8266.ld
|
||||
LDFLAGS = -nostdlib -T $(LDSCRIPT) -Map=$(@:.elf=.map) --cref
|
||||
LIBS = -L$(ESP_SDK)/lib -lmain -ljson -llwip_open -lpp -lnet80211 -lwpa -lphy -lnet80211 $(LDFLAGS_MOD)
|
||||
|
||||
LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
|
||||
|
@ -76,19 +75,19 @@ SRC_C = \
|
|||
espapa102.c \
|
||||
intr.c \
|
||||
modpyb.c \
|
||||
modpybpin.c \
|
||||
modpybpwm.c \
|
||||
modpybrtc.c \
|
||||
modpybadc.c \
|
||||
modpybuart.c \
|
||||
modmachinewdt.c \
|
||||
modpybspi.c \
|
||||
modpybhspi.c \
|
||||
modmachine.c \
|
||||
machine_pin.c \
|
||||
machine_pwm.c \
|
||||
machine_rtc.c \
|
||||
machine_adc.c \
|
||||
machine_uart.c \
|
||||
machine_wdt.c \
|
||||
machine_spi.c \
|
||||
machine_hspi.c \
|
||||
modesp.c \
|
||||
modnetwork.c \
|
||||
modutime.c \
|
||||
moduos.c \
|
||||
modmachine.c \
|
||||
modonewire.c \
|
||||
ets_alt_task.c \
|
||||
fatfs_port.c \
|
||||
|
@ -131,10 +130,14 @@ LIB_SRC_C = $(addprefix lib/,\
|
|||
utils/pyexec.c \
|
||||
utils/pyhelp.c \
|
||||
utils/interrupt_char.c \
|
||||
fatfs/ff.c \
|
||||
fatfs/option/ccsbcs.c \
|
||||
)
|
||||
|
||||
ifeq ($(MICROPY_FATFS), 1)
|
||||
LIB_SRC_C += \
|
||||
lib/fatfs/ff.c \
|
||||
lib/fatfs/option/ccsbcs.c
|
||||
endif
|
||||
|
||||
DRIVERS_SRC_C = $(addprefix drivers/,\
|
||||
dht/dht.c \
|
||||
)
|
||||
|
@ -142,9 +145,6 @@ DRIVERS_SRC_C = $(addprefix drivers/,\
|
|||
SRC_S = \
|
||||
gchelper.s \
|
||||
|
||||
FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py')
|
||||
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
|
||||
|
||||
OBJ =
|
||||
OBJ += $(PY_O)
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
||||
|
@ -153,7 +153,6 @@ OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o))
|
|||
OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
|
||||
OBJ += $(BUILD)/$(BUILD)/frozen_mpy.o
|
||||
#OBJ += $(BUILD)/pins_$(BOARD).o
|
||||
|
||||
# List of sources for qstr extraction
|
||||
|
@ -176,23 +175,11 @@ $(BUILD)/uart.o: $(CONFVARS_FILE)
|
|||
|
||||
FROZEN_EXTRA_DEPS = $(CONFVARS_FILE)
|
||||
|
||||
# to build .mpy files from .py files
|
||||
$(BUILD)/$(FROZEN_MPY_DIR)/%.mpy: $(FROZEN_MPY_DIR)/%.py
|
||||
@$(ECHO) "MPY $<"
|
||||
$(Q)$(MKDIR) -p $(dir $@)
|
||||
$(Q)$(MPY_CROSS) -o $@ -s $(^:$(FROZEN_MPY_DIR)/%=%) $^
|
||||
|
||||
# to build frozen_mpy.c from all .mpy files
|
||||
$(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h
|
||||
@$(ECHO) "Creating $@"
|
||||
$(Q)$(PYTHON) $(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h $(FROZEN_MPY_MPY_FILES) > $@
|
||||
|
||||
.PHONY: deploy
|
||||
|
||||
deploy: $(BUILD)/firmware-combined.bin
|
||||
$(ECHO) "Writing $< to the board"
|
||||
$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --verify --flash_size=$(FLASH_SIZE) --flash_mode=$(FLASH_MODE) 0 $<
|
||||
#$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --flash_size=8m 0 $(BUILD)/firmware.elf-0x00000.bin 0x9000 $(BUILD)/firmware.elf-0x0[1-f]000.bin
|
||||
|
||||
reset:
|
||||
echo -e "\r\nimport machine; machine.reset()\r\n" >$(PORT)
|
||||
|
@ -207,6 +194,9 @@ $(BUILD)/firmware.elf: $(OBJ)
|
|||
$(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
$(Q)$(SIZE) $@
|
||||
|
||||
512k:
|
||||
$(MAKE) LDSCRIPT=esp8266_512k.ld CFLAGS_EXTRA='-DMP_CONFIGFILE="<mpconfigport_512k.h>"' MICROPY_FATFS=0 MICROPY_PY_BTREE=0
|
||||
|
||||
#MAKE_PINS = boards/make-pins.py
|
||||
#BOARD_PINS = boards/$(BOARD)/pins.csv
|
||||
#AF_FILE = boards/stm32f4xx_af.csv
|
||||
|
|
|
@ -70,13 +70,14 @@ $ make deploy
|
|||
```
|
||||
This will use the `esptool.py` script to download the images. You must have
|
||||
your ESP module in the bootloader mode, and connected to a serial port on your PC.
|
||||
The default serial port is `/dev/ttyACM0`, flash mode is `qio` and flash size is `8m`.
|
||||
To specify other values, use, eg:
|
||||
The default serial port is `/dev/ttyACM0`, flash mode is `qio` and flash size is
|
||||
`detect` (auto-detect based on Flash ID). To specify other values, use, eg (note
|
||||
that flash size is in megabits):
|
||||
```bash
|
||||
$ make PORT=/dev/ttyUSB0 FLASH_MODE=qio FLASH_SIZE=8m deploy
|
||||
$ make PORT=/dev/ttyUSB0 FLASH_MODE=qio FLASH_SIZE=32m deploy
|
||||
```
|
||||
|
||||
The image produced is `firmware-combined.bin`, to be flashed at 0x00000.
|
||||
The image produced is `build/firmware-combined.bin`, to be flashed at 0x00000.
|
||||
|
||||
First start
|
||||
-----------
|
||||
|
|
|
@ -137,16 +137,16 @@ SECTIONS
|
|||
*lexerstr32.o(.literal* .text*)
|
||||
*utils.o(.literal* .text*)
|
||||
*modpyb.o(.literal*, .text*)
|
||||
*modpybpin.o(.literal*, .text*)
|
||||
*modpybpwm.o(.literal*, .text*)
|
||||
*modpybrtc.o(.literal*, .text*)
|
||||
*modpybadc.o(.literal*, .text*)
|
||||
*modpybuart.o(.literal*, .text*)
|
||||
*machine_pin.o(.literal*, .text*)
|
||||
*machine_pwm.o(.literal*, .text*)
|
||||
*machine_rtc.o(.literal*, .text*)
|
||||
*machine_adc.o(.literal*, .text*)
|
||||
*machine_uart.o(.literal*, .text*)
|
||||
*modpybi2c.o(.literal*, .text*)
|
||||
*modmachine.o(.literal*, .text*)
|
||||
*modmachinewdt.o(.literal*, .text*)
|
||||
*modpybspi.o(.literal*, .text*)
|
||||
*modpybhspi.o(.literal*, .text*)
|
||||
*machine_wdt.o(.literal*, .text*)
|
||||
*machine_spi.o(.literal*, .text*)
|
||||
*machine_hspi.o(.literal*, .text*)
|
||||
*hspi.o(.literal*, .text*)
|
||||
*modesp.o(.literal* .text*)
|
||||
*modnetwork.o(.literal* .text*)
|
||||
|
|
|
@ -0,0 +1,303 @@
|
|||
/* GNU linker script for ESP8266 */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
dport0_0_seg : org = 0x3ff00000, len = 0x10
|
||||
dram0_0_seg : org = 0x3ffe8000, len = 0x14000
|
||||
iram1_0_seg : org = 0x40100000, len = 0x8000
|
||||
irom0_0_seg : org = 0x40209000, len = 0x72000
|
||||
}
|
||||
|
||||
/* define the top of RAM */
|
||||
_heap_end = ORIGIN(dram0_0_seg) + LENGTH(dram0_0_seg);
|
||||
|
||||
PHDRS
|
||||
{
|
||||
dport0_0_phdr PT_LOAD;
|
||||
dram0_0_phdr PT_LOAD;
|
||||
dram0_0_bss_phdr PT_LOAD;
|
||||
iram1_0_phdr PT_LOAD;
|
||||
irom0_0_phdr PT_LOAD;
|
||||
}
|
||||
|
||||
ENTRY(firmware_start)
|
||||
EXTERN(_DebugExceptionVector)
|
||||
EXTERN(_DoubleExceptionVector)
|
||||
EXTERN(_KernelExceptionVector)
|
||||
EXTERN(_NMIExceptionVector)
|
||||
EXTERN(_UserExceptionVector)
|
||||
|
||||
PROVIDE(_memmap_vecbase_reset = 0x40000000);
|
||||
|
||||
/* Various memory-map dependent cache attribute settings: */
|
||||
_memmap_cacheattr_wb_base = 0x00000110;
|
||||
_memmap_cacheattr_wt_base = 0x00000110;
|
||||
_memmap_cacheattr_bp_base = 0x00000220;
|
||||
_memmap_cacheattr_unused_mask = 0xFFFFF00F;
|
||||
_memmap_cacheattr_wb_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wba_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wbna_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wt_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_bp_trapnull = 0x2222222F;
|
||||
_memmap_cacheattr_wb_strict = 0xFFFFF11F;
|
||||
_memmap_cacheattr_wt_strict = 0xFFFFF11F;
|
||||
_memmap_cacheattr_bp_strict = 0xFFFFF22F;
|
||||
_memmap_cacheattr_wb_allvalid = 0x22222112;
|
||||
_memmap_cacheattr_wt_allvalid = 0x22222112;
|
||||
_memmap_cacheattr_bp_allvalid = 0x22222222;
|
||||
PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.dport0.rodata : ALIGN(4)
|
||||
{
|
||||
_dport0_rodata_start = ABSOLUTE(.);
|
||||
*(.dport0.rodata)
|
||||
*(.dport.rodata)
|
||||
_dport0_rodata_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.dport0.literal : ALIGN(4)
|
||||
{
|
||||
_dport0_literal_start = ABSOLUTE(.);
|
||||
*(.dport0.literal)
|
||||
*(.dport.literal)
|
||||
_dport0_literal_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.dport0.data : ALIGN(4)
|
||||
{
|
||||
_dport0_data_start = ABSOLUTE(.);
|
||||
*(.dport0.data)
|
||||
*(.dport.data)
|
||||
_dport0_data_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.irom0.text : ALIGN(4)
|
||||
{
|
||||
_irom0_text_start = ABSOLUTE(.);
|
||||
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
|
||||
|
||||
/* we put some specific text in this section */
|
||||
|
||||
*py/argcheck.o*(.literal* .text*)
|
||||
*py/asm*.o*(.literal* .text*)
|
||||
*py/bc.o*(.literal* .text*)
|
||||
*py/binary.o*(.literal* .text*)
|
||||
*py/builtin*.o*(.literal* .text*)
|
||||
*py/compile.o*(.literal* .text*)
|
||||
*py/emit*.o*(.literal* .text*)
|
||||
*py/formatfloat.o*(.literal* .text*)
|
||||
*py/frozenmod.o*(.literal* .text*)
|
||||
*py/gc.o*(.literal* .text*)
|
||||
*py/lexer*.o*(.literal* .text*)
|
||||
*py/malloc*.o*(.literal* .text*)
|
||||
*py/map*.o*(.literal* .text*)
|
||||
*py/mod*.o*(.literal* .text*)
|
||||
*py/mpprint.o*(.literal* .text*)
|
||||
*py/mpstate.o*(.literal* .text*)
|
||||
*py/mpz.o*(.literal* .text*)
|
||||
*py/native*.o*(.literal* .text*)
|
||||
*py/nlr*.o*(.literal* .text*)
|
||||
*py/obj*.o*(.literal* .text*)
|
||||
*py/opmethods.o*(.literal* .text*)
|
||||
*py/parse*.o*(.literal* .text*)
|
||||
*py/qstr.o*(.literal* .text*)
|
||||
*py/repl.o*(.literal* .text*)
|
||||
*py/runtime.o*(.literal* .text*)
|
||||
*py/scope.o*(.literal* .text*)
|
||||
*py/sequence.o*(.literal* .text*)
|
||||
*py/showbc.o*(.literal* .text*)
|
||||
*py/smallint.o*(.literal* .text*)
|
||||
*py/stackctrl.o*(.literal* .text*)
|
||||
*py/stream.o*(.literal* .text*)
|
||||
*py/unicode.o*(.literal* .text*)
|
||||
*py/vm.o*(.literal* .text*)
|
||||
*py/vstr.o*(.literal* .text*)
|
||||
*py/warning.o*(.literal* .text*)
|
||||
|
||||
*extmod/*.o*(.literal* .text*)
|
||||
|
||||
*lib/fatfs/*.o*(.literal*, .text*)
|
||||
*/libaxtls.a:(.literal*, .text*)
|
||||
*lib/berkeley-db-1.xx/*.o(.literal*, .text*)
|
||||
*lib/libm/*.o*(.literal*, .text*)
|
||||
*lib/mp-readline/*.o(.literal*, .text*)
|
||||
*lib/netutils/*.o*(.literal*, .text*)
|
||||
*lib/timeutils/*.o*(.literal*, .text*)
|
||||
*lib/utils/*.o*(.literal*, .text*)
|
||||
|
||||
*stmhal/pybstdio.o(.literal*, .text*)
|
||||
|
||||
build/main.o(.literal* .text*)
|
||||
*gccollect.o(.literal* .text*)
|
||||
*gchelper.o(.literal* .text*)
|
||||
*help.o(.literal* .text*)
|
||||
*lexerstr32.o(.literal* .text*)
|
||||
*utils.o(.literal* .text*)
|
||||
*modpyb.o(.literal*, .text*)
|
||||
*machine_pin.o(.literal*, .text*)
|
||||
*machine_pwm.o(.literal*, .text*)
|
||||
*machine_rtc.o(.literal*, .text*)
|
||||
*machine_adc.o(.literal*, .text*)
|
||||
*machine_uart.o(.literal*, .text*)
|
||||
*modpybi2c.o(.literal*, .text*)
|
||||
*modmachine.o(.literal*, .text*)
|
||||
*machine_wdt.o(.literal*, .text*)
|
||||
*machine_spi.o(.literal*, .text*)
|
||||
*machine_hspi.o(.literal*, .text*)
|
||||
*hspi.o(.literal*, .text*)
|
||||
*modesp.o(.literal* .text*)
|
||||
*modnetwork.o(.literal* .text*)
|
||||
*moduos.o(.literal* .text*)
|
||||
*modutime.o(.literal* .text*)
|
||||
*modlwip.o(.literal* .text*)
|
||||
*modsocket.o(.literal* .text*)
|
||||
*modonewire.o(.literal* .text*)
|
||||
|
||||
/* we put as much rodata as possible in this section */
|
||||
/* note that only rodata accessed as a machine word is allowed here */
|
||||
*py/qstr.o(.rodata.const_pool)
|
||||
*.o(.rodata.mp_type_*) /* catches type: mp_obj_type_t */
|
||||
*.o(.rodata.*_locals_dict*) /* catches types: mp_obj_dict_t, mp_map_elem_t */
|
||||
*.o(.rodata.mp_module_*) /* catches types: mp_obj_module_t, mp_obj_dict_t, mp_map_elem_t */
|
||||
*/frozen.o(.rodata.mp_frozen_sizes) /* frozen modules */
|
||||
*/frozen.o(.rodata.mp_frozen_content) /* frozen modules */
|
||||
|
||||
/* for -mforce-l32 */
|
||||
build/*.o(.rodata*)
|
||||
|
||||
_irom0_text_end = ABSOLUTE(.);
|
||||
} >irom0_0_seg :irom0_0_phdr
|
||||
|
||||
.text : ALIGN(4)
|
||||
{
|
||||
_stext = .;
|
||||
_text_start = ABSOLUTE(.);
|
||||
*(.UserEnter.text)
|
||||
. = ALIGN(16);
|
||||
*(.DebugExceptionVector.text)
|
||||
. = ALIGN(16);
|
||||
*(.NMIExceptionVector.text)
|
||||
. = ALIGN(16);
|
||||
*(.KernelExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN(16);
|
||||
*(.UserExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN(16);
|
||||
*(.DoubleExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN (16);
|
||||
*(.entry.text)
|
||||
*(.init.literal)
|
||||
*(.init)
|
||||
*(.literal .text .literal.* .text.* .iram0.literal .iram0.text .iram0.text.*.literal .iram0.text.*)
|
||||
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} >iram1_0_seg :iram1_0_phdr
|
||||
|
||||
.lit4 : ALIGN(4)
|
||||
{
|
||||
_lit4_start = ABSOLUTE(.);
|
||||
*(*.lit4)
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
} >iram1_0_seg :iram1_0_phdr
|
||||
|
||||
.data : ALIGN(4)
|
||||
{
|
||||
_data_start = ABSOLUTE(.);
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
*(.gnu.linkonce.s2.*)
|
||||
*(.jcr)
|
||||
_data_end = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_phdr
|
||||
|
||||
.rodata : ALIGN(4)
|
||||
{
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
*(.sdk.version)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
__XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
|
||||
*(.xt_except_table)
|
||||
*(.gcc_except_table)
|
||||
*(.gnu.linkonce.e.*)
|
||||
*(.gnu.version_r)
|
||||
*(.eh_frame)
|
||||
/* C++ constructor and destructor tables, properly ordered: */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
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)
|
||||
. = ALIGN(4); /* this table MUST be 4-byte aligned */
|
||||
_bss_table_start = ABSOLUTE(.);
|
||||
LONG(_bss_start)
|
||||
LONG(_bss_end)
|
||||
_bss_table_end = ABSOLUTE(.);
|
||||
_rodata_end = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_phdr
|
||||
|
||||
.bss ALIGN(8) (NOLOAD) : ALIGN(4)
|
||||
{
|
||||
. = ALIGN (8);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
_heap_start = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_bss_phdr
|
||||
}
|
||||
|
||||
/* get ROM code address */
|
||||
INCLUDE "eagle.rom.addr.v6.ld"
|
|
@ -31,9 +31,6 @@
|
|||
#include "user_interface.h"
|
||||
#include "extmod/misc.h"
|
||||
|
||||
uint32_t SPIRead(uint32_t offset, void *buf, uint32_t len);
|
||||
uint32_t SPIWrite(uint32_t offset, const void *buf, uint32_t len);
|
||||
uint32_t SPIEraseSector(int sector);
|
||||
NORETURN void call_user_start(void);
|
||||
void ets_printf(const char *fmt, ...);
|
||||
extern char flashchip;
|
||||
|
|
|
@ -75,7 +75,7 @@ void ets_event_poll(void);
|
|||
// C-level pin HAL
|
||||
#include "etshal.h"
|
||||
#include "gpio.h"
|
||||
#include "esp8266/modpyb.h"
|
||||
#include "esp8266/modmachine.h"
|
||||
#define mp_hal_pin_obj_t uint32_t
|
||||
#define mp_hal_get_pin_obj(o) mp_obj_get_pin(o)
|
||||
void mp_hal_pin_input(mp_hal_pin_obj_t pin);
|
||||
|
|
|
@ -33,7 +33,7 @@ void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32
|
|||
#ifdef NEO_KHZ400
|
||||
if(is800KHz) {
|
||||
#endif
|
||||
time0 = fcpu / 2500000; // 0.4us
|
||||
time0 = fcpu / 2857143; // 0.35us
|
||||
time1 = fcpu / 1250000; // 0.8us
|
||||
period = fcpu / 800000; // 1.25us per bit
|
||||
#ifdef NEO_KHZ400
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
#include "etshal.h"
|
||||
#include "user_interface.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
#include "esponewire.h"
|
||||
|
||||
#define TIMING_RESET1 (0)
|
||||
|
|
|
@ -24,7 +24,9 @@ extern void ets_wdt_disable(void);
|
|||
extern void wdt_feed(void);
|
||||
|
||||
// Opaque structure
|
||||
typedef char MD5_CTX[64];
|
||||
#ifndef MD5_CTX
|
||||
typedef char MD5_CTX[88];
|
||||
#endif
|
||||
|
||||
void MD5Init(MD5_CTX *context);
|
||||
void MD5Update(MD5_CTX *context, const void *data, unsigned int len);
|
||||
|
@ -32,6 +34,12 @@ void MD5Final(unsigned char digest[16], MD5_CTX *context);
|
|||
|
||||
// These prototypes are for recent SDKs with "malloc tracking"
|
||||
void *pvPortMalloc(unsigned sz, const char *fname, int line);
|
||||
void *pvPortZalloc(unsigned sz, const char *fname, int line);
|
||||
void *pvPortRealloc(void *p, unsigned sz, const char *fname, int line);
|
||||
void vPortFree(void *p, const char *fname, int line);
|
||||
|
||||
uint32_t SPIRead(uint32_t offset, void *buf, uint32_t len);
|
||||
uint32_t SPIWrite(uint32_t offset, const void *buf, uint32_t len);
|
||||
uint32_t SPIEraseSector(int sector);
|
||||
|
||||
#endif // _INCLUDED_ETSHAL_H_
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "py/obj.h"
|
||||
#include "lib/fatfs/ff.h"
|
||||
#include "timeutils.h"
|
||||
#include "modpybrtc.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
DWORD get_fattime(void) {
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "etshal.h"
|
||||
#include "ets_alt_task.h"
|
||||
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
// this is in a separate file so it can go in iRAM
|
||||
void pin_intr_handler_iram(void *arg) {
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/mphal.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
#define GET_TRIGGER(phys_port) \
|
||||
GPIO_PIN_INT_TYPE_GET(GPIO_REG_READ(GPIO_PIN_ADDR(phys_port)))
|
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
typedef struct _pyb_pwm_obj_t {
|
||||
mp_obj_base_t base;
|
|
@ -32,7 +32,7 @@
|
|||
#include "py/runtime.h"
|
||||
#include "timeutils.h"
|
||||
#include "user_interface.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
typedef struct _pyb_rtc_obj_t {
|
||||
mp_obj_base_t base;
|
|
@ -34,7 +34,7 @@
|
|||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
// UartDev is defined and initialized in rom code.
|
||||
extern UartDevice UartDev;
|
|
@ -39,7 +39,7 @@
|
|||
#include "gccollect.h"
|
||||
#include "user_interface.h"
|
||||
|
||||
STATIC char heap[28 * 1024];
|
||||
STATIC char heap[36 * 1024];
|
||||
|
||||
STATIC void mp_reset(void) {
|
||||
mp_stack_set_top((void*)0x40000000);
|
||||
|
|
|
@ -45,8 +45,7 @@
|
|||
#include "mem.h"
|
||||
#include "espneopixel.h"
|
||||
#include "espapa102.h"
|
||||
#include "modpyb.h"
|
||||
#include "modpybrtc.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
#define MODESP_ESPCONN (0)
|
||||
|
||||
|
@ -629,6 +628,11 @@ STATIC mp_obj_t esp_flash_size(void) {
|
|||
}
|
||||
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(0x90000);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_user_start_obj, esp_flash_user_start);
|
||||
|
||||
STATIC mp_obj_t esp_check_fw(void) {
|
||||
MD5_CTX ctx;
|
||||
uint32_t *sz_p = (uint32_t*)0x40208ffc;
|
||||
|
@ -706,6 +710,7 @@ STATIC const mp_map_elem_t esp_module_globals_table[] = {
|
|||
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_write), (mp_obj_t)&esp_flash_write_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_erase), (mp_obj_t)&esp_flash_erase_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_size), (mp_obj_t)&esp_flash_size_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_user_start), (mp_obj_t)&esp_flash_user_start_obj },
|
||||
#if MODESP_ESPCONN
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&esp_socket_type },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_getaddrinfo_obj },
|
||||
|
|
|
@ -33,8 +33,7 @@
|
|||
#include "extmod/machine_mem.h"
|
||||
#include "extmod/machine_pulse.h"
|
||||
#include "extmod/machine_i2c.h"
|
||||
#include "modpyb.h"
|
||||
#include "modpybrtc.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
#include "xtirq.h"
|
||||
#include "os_type.h"
|
||||
|
|
|
@ -13,7 +13,7 @@ extern const mp_obj_type_t pyb_spi_type;
|
|||
extern const mp_obj_type_t pyb_hspi_type;
|
||||
extern const mp_obj_type_t machine_spi_type;
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(pyb_info_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj);
|
||||
|
||||
typedef struct _pyb_pin_obj_t {
|
||||
mp_obj_base_t base;
|
||||
|
@ -33,4 +33,11 @@ pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in);
|
|||
int pin_get(uint pin);
|
||||
void pin_set(uint pin, int value);
|
||||
|
||||
extern uint32_t pyb_rtc_alarm0_wake;
|
||||
extern uint64_t pyb_rtc_alarm0_expiry;
|
||||
|
||||
void pyb_rtc_set_us_since_2000(uint64_t nowus);
|
||||
uint64_t pyb_rtc_get_us_since_2000();
|
||||
void rtc_prepare_deepsleep(uint64_t sleep_us);
|
||||
|
||||
#endif // __MICROPY_INCLUDED_ESP8266_MODPYB_H__
|
|
@ -100,17 +100,23 @@ STATIC mp_obj_t esp_connect(mp_uint_t n_args, const mp_obj_t *args) {
|
|||
mp_uint_t len;
|
||||
const char *p;
|
||||
|
||||
p = mp_obj_str_get_data(args[1], &len);
|
||||
memcpy(config.ssid, p, len);
|
||||
p = mp_obj_str_get_data(args[2], &len);
|
||||
memcpy(config.password, p, len);
|
||||
if (n_args > 1) {
|
||||
p = mp_obj_str_get_data(args[1], &len);
|
||||
memcpy(config.ssid, p, len);
|
||||
if (n_args > 2) {
|
||||
p = mp_obj_str_get_data(args[2], &len);
|
||||
} else {
|
||||
p = "";
|
||||
}
|
||||
memcpy(config.password, p, len);
|
||||
|
||||
error_check(wifi_station_set_config(&config), "Cannot set STA config");
|
||||
error_check(wifi_station_set_config(&config), "Cannot set STA config");
|
||||
}
|
||||
error_check(wifi_station_connect(), "Cannot connect to AP");
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_connect_obj, 3, 7, esp_connect);
|
||||
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) {
|
||||
require_if(self_in, STATION_IF);
|
||||
|
@ -295,7 +301,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
|
|||
switch ((uintptr_t)kwargs->table[i].key) {
|
||||
case QS(MP_QSTR_mac): {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
|
||||
mp_get_buffer_raise(kwargs->table[i].value, &bufinfo, MP_BUFFER_READ);
|
||||
if (bufinfo.len != 6) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"invalid buffer length"));
|
||||
|
@ -336,6 +342,14 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
|
|||
cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value);
|
||||
break;
|
||||
}
|
||||
case QS(MP_QSTR_dhcp_hostname): {
|
||||
req_if = STATION_IF;
|
||||
if (self->if_id == STATION_IF) {
|
||||
const char *s = mp_obj_str_get_str(kwargs->table[i].value);
|
||||
wifi_station_set_hostname((char*)s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto unknown;
|
||||
}
|
||||
|
@ -389,6 +403,12 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
|
|||
req_if = SOFTAP_IF;
|
||||
val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel);
|
||||
break;
|
||||
case QS(MP_QSTR_dhcp_hostname): {
|
||||
req_if = STATION_IF;
|
||||
char* s = wifi_station_get_hostname();
|
||||
val = mp_obj_new_str(s, strlen(s), false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto unknown;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#include "py/obj.h"
|
||||
#include "py/mphal.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
#include "esponewire.h"
|
||||
|
||||
STATIC mp_obj_t onewire_timings(mp_obj_t timings_in) {
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
|
||||
#include "py/gc.h"
|
||||
#include "gccollect.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
// The pyb module no longer exists since all functionality now appears
|
||||
// elsewhere, in more standard places (eg time, machine modules). The
|
||||
// only remaining function is pyb.info() which has been moved to the
|
||||
// esp module, pending deletion/renaming/moving elsewher.
|
||||
// esp module, pending deletion/renaming/moving elsewhere.
|
||||
|
||||
STATIC mp_obj_t pyb_info(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
// print info about memory
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 Josef Gajdusek
|
||||
*
|
||||
* 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 pyb_rtc_alarm0_wake;
|
||||
extern uint64_t pyb_rtc_alarm0_expiry;
|
||||
|
||||
void pyb_rtc_set_us_since_2000(uint64_t nowus);
|
||||
|
||||
uint64_t pyb_rtc_get_us_since_2000();
|
||||
|
||||
void rtc_prepare_deepsleep(uint64_t sleep_us);
|
|
@ -1,6 +1,8 @@
|
|||
# DS18x20 temperature sensor driver for MicroPython.
|
||||
# MIT license; Copyright (c) 2016 Damien P. George
|
||||
|
||||
from micropython import const
|
||||
|
||||
_CONVERT = const(0x44)
|
||||
_RD_SCRATCH = const(0xbe)
|
||||
_WR_SCRATCH = const(0x4e)
|
||||
|
@ -43,4 +45,7 @@ class DS18X20:
|
|||
t = buf[0] >> 1
|
||||
return t - 0.25 + (buf[7] - buf[6]) / buf[7]
|
||||
else:
|
||||
return (buf[1] << 8 | buf[0]) / 16
|
||||
t = buf[1] << 8 | buf[0]
|
||||
if t & 0x8000: # sign bit set
|
||||
t = -((t ^ 0xffff) + 1)
|
||||
return t / 16
|
||||
|
|
|
@ -3,7 +3,7 @@ import esp
|
|||
class FlashBdev:
|
||||
|
||||
SEC_SIZE = 4096
|
||||
START_SEC = 0x90000 // SEC_SIZE
|
||||
START_SEC = esp.flash_user_start() // SEC_SIZE
|
||||
NUM_BLK = 0x6b
|
||||
|
||||
def __init__(self, blocks=NUM_BLK):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# 1-Wire driver for MicroPython on ESP8266
|
||||
# MIT license; Copyright (c) 2016 Damien P. George
|
||||
|
||||
from micropython import const
|
||||
import _onewire as _ow
|
||||
|
||||
class OneWireError(Exception):
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
../../tools/upip.py
|
|
@ -0,0 +1 @@
|
|||
../../tools/upip_utarfile.py
|
|
@ -59,18 +59,16 @@ def start(port=8266, password=None):
|
|||
stop()
|
||||
if password is None:
|
||||
try:
|
||||
import port_config
|
||||
_webrepl.password(port_config.WEBREPL_PASS)
|
||||
import webrepl_cfg
|
||||
_webrepl.password(webrepl_cfg.PASS)
|
||||
setup_conn(port, accept_conn)
|
||||
print("Started webrepl in normal mode")
|
||||
except:
|
||||
import webrepl_setup
|
||||
setup_conn(port, webrepl_setup.handle_conn)
|
||||
print("Started webrepl in setup mode")
|
||||
print("WebREPL is not configured, run 'import webrepl_setup'")
|
||||
else:
|
||||
_webrepl.password(password)
|
||||
setup_conn(port, accept_conn)
|
||||
print("Started webrepl in normal mode")
|
||||
print("Started webrepl in manual override mode")
|
||||
|
||||
|
||||
def start_foreground(port=8266):
|
||||
|
|
|
@ -1,83 +1,111 @@
|
|||
import sys
|
||||
import socket
|
||||
import time
|
||||
#import uos as os
|
||||
import os
|
||||
import machine
|
||||
|
||||
from websocket import *
|
||||
import websocket_helper
|
||||
RC = "./boot.py"
|
||||
CONFIG = "./webrepl_cfg.py"
|
||||
|
||||
|
||||
def setup_server():
|
||||
s = socket.socket()
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
ai = socket.getaddrinfo("0.0.0.0", 8266)
|
||||
addr = ai[0][4]
|
||||
|
||||
s.bind(addr)
|
||||
s.listen(1)
|
||||
return s
|
||||
|
||||
def getpass(stream, prompt):
|
||||
stream.write(prompt)
|
||||
passwd = b""
|
||||
def input_choice(prompt, choices):
|
||||
while 1:
|
||||
c = stream.read(1)
|
||||
if c in (b"\r", b"\n"):
|
||||
stream.write("\r\n")
|
||||
return passwd
|
||||
passwd += c
|
||||
stream.write("*")
|
||||
resp = input(prompt)
|
||||
if resp in choices:
|
||||
return resp
|
||||
|
||||
def handle_conn(listen_sock):
|
||||
cl, remote_addr = listen_sock.accept()
|
||||
|
||||
print("""
|
||||
|
||||
First-time WebREPL connection has been received. WebREPL initial setup
|
||||
will now start over this connection. During setup, UART REPL will be
|
||||
non-responsive. After setup finishes, the board will be rebooted. In
|
||||
case of error during setup, current session will continue.
|
||||
|
||||
If you receive this message unexpectedly, it may mean that your WebREPL
|
||||
connection is being hacked (power off board if unsure).
|
||||
""")
|
||||
|
||||
websocket_helper.server_handshake(cl)
|
||||
ws = websocket(cl)
|
||||
|
||||
ws.write("""\
|
||||
Welcome to MicroPython WebREPL!\r
|
||||
\r
|
||||
This is the first time you connect to WebREPL, so please set a password\r
|
||||
to use for the following WebREPL sessions. Once you enter the password\r
|
||||
twice, your board will reboot with WebREPL running in active mode. On\r
|
||||
some boards, you may need to press reset button or reconnect power.\r
|
||||
\r
|
||||
""")
|
||||
def getpass(prompt):
|
||||
return input(prompt)
|
||||
|
||||
def input_pass():
|
||||
while 1:
|
||||
passwd1 = getpass(ws, "New password: ")
|
||||
passwd1 = getpass("New password: ")
|
||||
if len(passwd1) < 4:
|
||||
ws.write("Password too short\r\n")
|
||||
print("Password too short")
|
||||
continue
|
||||
elif len(passwd1) > 9:
|
||||
ws.write("Password too long\r\n")
|
||||
print("Password too long")
|
||||
continue
|
||||
passwd2 = getpass(ws, "Confirm password: ")
|
||||
passwd2 = getpass("Confirm password: ")
|
||||
if passwd1 == passwd2:
|
||||
break
|
||||
ws.write("Passwords do not match\r\n")
|
||||
|
||||
with open("port_config.py", "w") as f:
|
||||
f.write("WEBREPL_PASS = %r\n" % passwd1.decode("ascii"))
|
||||
|
||||
ws.write("Password successfully set, restarting...\r\n")
|
||||
cl.close()
|
||||
time.sleep(2)
|
||||
import machine
|
||||
machine.reset()
|
||||
return passwd1
|
||||
print("Passwords do not match")
|
||||
|
||||
|
||||
def test():
|
||||
s = setup_server()
|
||||
handle_conn(s)
|
||||
def exists(fname):
|
||||
try:
|
||||
with open(fname):
|
||||
pass
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
def copy_stream(s_in, s_out):
|
||||
buf = bytearray(64)
|
||||
while 1:
|
||||
sz = s_in.readinto(buf)
|
||||
s_out.write(buf, sz)
|
||||
|
||||
|
||||
def get_daemon_status():
|
||||
with open(RC) as f:
|
||||
for l in f:
|
||||
if "webrepl" in l:
|
||||
if l.startswith("#"):
|
||||
return False
|
||||
return True
|
||||
return None
|
||||
|
||||
def add_daemon():
|
||||
with open(RC) as old_f, open(RC + ".tmp", "w") as new_f:
|
||||
new_f.write("import webrepl\nwebrepl.start()\n")
|
||||
copy_stream(old_f, new_f)
|
||||
|
||||
def change_daemon(action):
|
||||
LINES = ("import webrepl", "webrepl.start()")
|
||||
with open(RC) as old_f, open(RC + ".tmp", "w") as new_f:
|
||||
for l in old_f:
|
||||
for patt in LINES:
|
||||
if patt in l:
|
||||
if action and l.startswith("#"):
|
||||
l = l[1:]
|
||||
elif not action and not l.startswith("#"):
|
||||
l = "#" + l
|
||||
new_f.write(l)
|
||||
# FatFs rename() is not POSIX compliant, will raise OSError if
|
||||
# dest file exists.
|
||||
os.remove(RC)
|
||||
os.rename(RC + ".tmp", RC)
|
||||
|
||||
|
||||
def main():
|
||||
status = get_daemon_status()
|
||||
|
||||
print("WebREPL daemon auto-start status:", "enabled" if status else "disabled")
|
||||
print("\nWould you like to (E)nable or (D)isable it running on boot?")
|
||||
print("(Empty line to quit)")
|
||||
resp = input("> ").upper()
|
||||
|
||||
if resp == "E":
|
||||
if exists(CONFIG):
|
||||
resp2 = input_choice("Would you like to change WebREPL password? (y/n) ", ("y", "n", ""))
|
||||
else:
|
||||
print("To enable WebREPL, you must set password for it")
|
||||
resp2 = "y"
|
||||
|
||||
if resp2 == "y":
|
||||
passwd = input_pass()
|
||||
with open(CONFIG, "w") as f:
|
||||
f.write("PASS = %r\n" % passwd)
|
||||
|
||||
|
||||
if resp not in ("D", "E") or (resp == "D" and not status) or (resp == "E" and status):
|
||||
print("No further action required")
|
||||
sys.exit()
|
||||
|
||||
change_daemon(resp == "E")
|
||||
|
||||
print("Changes will be activated after reboot")
|
||||
resp = input_choice("Would you like to reboot now? (y/n) ", ("y", "n", ""))
|
||||
if resp == "y":
|
||||
machine.reset()
|
||||
|
||||
main()
|
||||
|
|
|
@ -34,8 +34,7 @@
|
|||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/smallint.h"
|
||||
#include "modpyb.h"
|
||||
#include "modpybrtc.h"
|
||||
#include "modmachine.h"
|
||||
#include "timeutils.h"
|
||||
#include "user_interface.h"
|
||||
#include "extmod/utime_mphal.h"
|
||||
|
@ -108,19 +107,20 @@ STATIC mp_obj_t time_time(void) {
|
|||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
|
||||
|
||||
STATIC const mp_map_elem_t time_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_utime) },
|
||||
STATIC const mp_rom_map_elem_t time_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) },
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_localtime), (mp_obj_t)&time_localtime_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mktime), (mp_obj_t)&time_mktime_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&mp_utime_sleep_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_ms), (mp_obj_t)&mp_utime_sleep_ms_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_us), (mp_obj_t)&mp_utime_sleep_us_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_ms), (mp_obj_t)&mp_utime_ticks_ms_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_us), (mp_obj_t)&mp_utime_ticks_us_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_cpu), (mp_obj_t)&mp_utime_ticks_cpu_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_diff), (mp_obj_t)&mp_utime_ticks_diff_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_time_obj },
|
||||
{ MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&time_localtime_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&time_mktime_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_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) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#include <mpconfigport.h>
|
||||
|
||||
#undef MICROPY_FSUSERMOUNT
|
||||
#define MICROPY_FSUSERMOUNT (0)
|
||||
#undef MICROPY_VFS_FAT
|
||||
#define MICROPY_VFS_FAT (0)
|
||||
|
||||
#undef MICROPY_PERSISTENT_CODE_LOAD
|
||||
#define MICROPY_PERSISTENT_CODE_LOAD (0)
|
||||
|
||||
#undef MICROPY_PY_IO_FILEIO
|
||||
#define MICROPY_PY_IO_FILEIO (0)
|
||||
|
||||
#undef MICROPY_PY_SYS_STDIO_BUFFER
|
||||
#define MICROPY_PY_SYS_STDIO_BUFFER (0)
|
||||
#undef MICROPY_PY_BUILTINS_SLICE_ATTRS
|
||||
#define MICROPY_PY_BUILTINS_SLICE_ATTRS (0)
|
||||
#undef MICROPY_PY_ALL_SPECIAL_METHODS
|
||||
#define MICROPY_PY_ALL_SPECIAL_METHODS (0)
|
|
@ -2,27 +2,16 @@
|
|||
# MIT license; Copyright (c) 2016 Robert Foss, Daniel Busch
|
||||
|
||||
from esp import apa102_write
|
||||
from neopixel import NeoPixel
|
||||
|
||||
class APA102:
|
||||
def __init__(self, clock_pin, data_pin, n):
|
||||
|
||||
class APA102(NeoPixel):
|
||||
ORDER = (0, 1, 2, 3)
|
||||
|
||||
def __init__(self, clock_pin, data_pin, n, bpp=4):
|
||||
super().__init__(data_pin, n, bpp)
|
||||
self.clock_pin = clock_pin
|
||||
self.data_pin = data_pin
|
||||
self.n = n
|
||||
self.buf = bytearray(n * 4)
|
||||
|
||||
self.clock_pin.init(clock_pin.OUT)
|
||||
self.data_pin.init(data_pin.OUT)
|
||||
|
||||
def __setitem__(self, index, val):
|
||||
r, g, b, brightness = val
|
||||
self.buf[index * 4] = r
|
||||
self.buf[index * 4 + 1] = g
|
||||
self.buf[index * 4 + 2] = b
|
||||
self.buf[index * 4 + 3] = brightness
|
||||
|
||||
def __getitem__(self, index):
|
||||
i = index * 4
|
||||
return self.buf[i], self.buf[i + 1], self.buf[i + 2], self.buf[i + 3]
|
||||
|
||||
def write(self):
|
||||
apa102_write(self.clock_pin, self.data_pin, self.buf)
|
||||
apa102_write(self.clock_pin, self.pin, self.buf)
|
||||
|
|
|
@ -3,29 +3,30 @@
|
|||
|
||||
from esp import neopixel_write
|
||||
|
||||
|
||||
class NeoPixel:
|
||||
def __init__(self, pin, n):
|
||||
ORDER = (1, 0, 2, 3)
|
||||
|
||||
def __init__(self, pin, n, bpp=3):
|
||||
self.pin = pin
|
||||
self.n = n
|
||||
self.buf = bytearray(n * 3)
|
||||
self.bpp = bpp
|
||||
self.buf = bytearray(n * bpp)
|
||||
self.pin.init(pin.OUT)
|
||||
|
||||
def __setitem__(self, index, val):
|
||||
r, g, b = val
|
||||
self.buf[index * 3] = g
|
||||
self.buf[index * 3 + 1] = r
|
||||
self.buf[index * 3 + 2] = b
|
||||
offset = index * self.bpp
|
||||
for i in range(self.bpp):
|
||||
self.buf[offset + self.ORDER[i]] = val[i]
|
||||
|
||||
def __getitem__(self, index):
|
||||
i = index * 3
|
||||
return self.buf[i + 1], self.buf[i], self.buf[i + 2]
|
||||
offset = index * self.bpp
|
||||
return tuple(self.buf[offset + self.ORDER[i]]
|
||||
for i in range(self.bpp))
|
||||
|
||||
def fill(self, color):
|
||||
r, g, b = color
|
||||
for i in range(len(self.buf) / 3):
|
||||
self.buf[i * 3] = g
|
||||
self.buf[i * 3 + 1] = r
|
||||
self.buf[i * 3 + 2] = b
|
||||
for i in range(self.n):
|
||||
self[i] = color
|
||||
|
||||
def write(self):
|
||||
neopixel_write(self.pin, self.buf, True)
|
||||
|
|
|
@ -24,8 +24,8 @@ def main():
|
|||
print("STA ifconfig:", network.WLAN(network.STA_IF).ifconfig())
|
||||
print("AP ifconfig:", network.WLAN(network.AP_IF).ifconfig())
|
||||
print("Free WiFi driver buffers of type:")
|
||||
for i in range(5):
|
||||
print("%d: %d" % (i, esp.esf_free_bufs(i)))
|
||||
for i, comm in enumerate(("1,2 TX", "4 Mngmt TX(len: 0x41-0x100)", "5 Mngmt TX (len: 0-0x40)", "7", "8 RX")):
|
||||
print("%d: %d (%s)" % (i, esp.esf_free_bufs(i), comm))
|
||||
print("lwIP PCBs:")
|
||||
lwip.print_pcbs()
|
||||
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
This directory shows the best practices for using MicroPython hardware API
|
||||
(`machine` module). `machine` module strives to provide consistent API
|
||||
across various boards, with the aim to enable writing portable applications,
|
||||
which would work from a board to board, from a system to another systems.
|
||||
This is inherently a hard problem, because hardware is different from one
|
||||
board type to another, and even from examplar of board to another. For
|
||||
example, if your app requires an external LED, one user may connect it
|
||||
to one GPIO pin, while another user may find it much more convinient to
|
||||
use another pin. This of course applies to relays, buzzers, sensors, etc.
|
||||
|
||||
With complications above in mind, it's still possible to write portable
|
||||
applications by using "low[est] denominator" subset of hardware API and
|
||||
following simple rules outlined below. The applications won't be able
|
||||
to rely on advanced hardware capabilities of a particular board and
|
||||
will be limited to generic capabilities, but it's still possible to
|
||||
write many useful applications in such a way, with the obvious benefit of
|
||||
"write once - run everywhere" approach (only configuration for a particular
|
||||
board is required).
|
||||
|
||||
The key to this approach is splitting your application into (at least)
|
||||
2 parts:
|
||||
|
||||
* main application logic
|
||||
* hardware configuration
|
||||
|
||||
The key point is that hardware configuration should be a separate file
|
||||
(module in Python terms). A good name would be `hwconfig.py`, and that's
|
||||
how we'll call it from now on. Another key point is that main application
|
||||
should never instantiate (construct) hardware objects directly. Instead,
|
||||
they should be defined in `hwconfig.py`, and main application should
|
||||
import and reference hardware objects via this module. The simplest
|
||||
application of this idea would look like:
|
||||
|
||||
`hwconfig.py`:
|
||||
|
||||
from machine import Pin
|
||||
|
||||
LED = Pin("A3", Pin.OUT)
|
||||
|
||||
`app.py`:
|
||||
|
||||
from hwconfig import *
|
||||
import utime
|
||||
|
||||
while True:
|
||||
LED.value(1)
|
||||
utime.sleep_ms(500)
|
||||
LED.value(0)
|
||||
utime.sleep_ms(500)
|
||||
|
||||
|
||||
To deploy this application to a particular board, a user will need:
|
||||
|
||||
1. Edit `hwconfig.py` to adjust Pin and other hardware peripheral
|
||||
parameters and locations.
|
||||
2. Actually deploy `hwconfig.py` and `app.py` to a board (e.g. copy to
|
||||
board's filesystem, or build new firmware with these modules frozen
|
||||
into it).
|
||||
|
||||
Note that there's no need to edit the main application code! (Which may
|
||||
be complex, while `hwconfig.py` should usually remain short enough, and
|
||||
focused solely on hardware configuration).
|
||||
|
||||
An obvious improvement to this approach is the following. There're few
|
||||
well-known boards which run MicroPython, and most of them include an
|
||||
onboard LED. So, to help users of these boards to do configuration
|
||||
quickly (that's especially important for novice users, for who may
|
||||
be stumped by the need to reach out to a board reference to find LED
|
||||
pin assignments), `hwconfig.py` your application ships may include
|
||||
commented out sections with working configurations for different
|
||||
boards. The step 1 above then will be:
|
||||
|
||||
1. Look thru `hwconfig.py` to find a section which either exactly
|
||||
matches your board, or the closest to it. Uncomment, and if any
|
||||
adjustments required, apply them.
|
||||
|
||||
It's important to keep in mind that adjustments may be always required,
|
||||
and that there may be users whose configuration doesn't match any of
|
||||
the available. So, always include a section or instructions for them.
|
||||
Consider for example that even on a supported board, user may want to
|
||||
blink not an on-board LED, but the one they connected externally.
|
||||
MicroPython's Hardware API offers portability not just among "supported"
|
||||
boards, but to any board at all, so make sure users can enjoy it.
|
||||
|
||||
There's next step of improvement to make. While having one `hwconfig.py`
|
||||
with many sections would work for smaller projects with few hardware
|
||||
objects, it may become more cumbersome to maintain both on programmer's
|
||||
and user's sides for larger projects. Then instead of single
|
||||
`hwconfig.py` file, you can provide few "template" ones for well-known
|
||||
boards:
|
||||
|
||||
* `hwconfig_pyboard.py`
|
||||
* `hwconfig_wipy.py`
|
||||
* `hwconfig_esp8266.py`
|
||||
* etc.
|
||||
|
||||
Then step 1 above will be:
|
||||
|
||||
1. Look thru available `hwconfig_*.py` files and find one which matches
|
||||
your board the best, then rename to `hwconfig.py` and make adjustments,
|
||||
if any.
|
||||
|
||||
Again, please keep in mind that there may be users whose hardware will be
|
||||
completely unlike you heard of. Give them some helpful hints too, perhaps
|
||||
provide `hwconfig_custom.py` with some instructions.
|
||||
|
||||
That's where we stop with improvements to the "separate file for hardware
|
||||
configuration" idea, as it is already pretty flexible and viable. An
|
||||
application in this directory shows it in practice, using slightly less
|
||||
trivial example than just a blinking LED: `soft_pwm.py` implements a
|
||||
software PWM (pulse width modulation) to produce an LED fade-in/fade-out
|
||||
effect - without any dependence on hardware PWM availability.
|
||||
|
||||
Note that improvements to board configuration handling may continue further.
|
||||
For example, one may invent a "configuration manager" helper module which will
|
||||
try to detect current board (among well-known ones), and load appropriate
|
||||
`hwconfig_*.py` - this assumes that a user would lazily deploy them all
|
||||
(or that application will be automatically installed, e.g. using MicroPython's
|
||||
`upip` package manager). The key point in this case remains the same as
|
||||
elaborated above - always assume there can, and will be a custom configuration,
|
||||
and it should be well supported. So, any automatic detection should be
|
||||
overridable by a user, and instructions how to do so are among the most
|
||||
important you may provide for your application.
|
||||
|
||||
By following these best practices, you will use MicroPython at its full
|
||||
potential, and let users enjoy it too. Good luck!
|
|
@ -0,0 +1,12 @@
|
|||
from machine import Pin
|
||||
|
||||
# 96Boards/Qualcomm DragonBoard 410c
|
||||
# By default, on-board LEDs are controlled by kernel LED driver.
|
||||
# To make corresponding pins be available as normal GPIO,
|
||||
# corresponding driver needs to be unbound first (as root):
|
||||
# echo -n "soc:leds" >/sys/class/leds/apq8016-sbc:green:user1/device/driver/unbind
|
||||
# Note that application also either should be run as root, or
|
||||
# /sys/class/gpio ownership needs to be changed.
|
||||
|
||||
# User LED 1 on gpio21
|
||||
LED = Pin(21, Pin.OUT)
|
|
@ -0,0 +1,5 @@
|
|||
from machine import Pin
|
||||
|
||||
# ESP12 module as used by many boards
|
||||
# Blue LED on pin 2
|
||||
LED = Pin(2, Pin.OUT)
|
|
@ -0,0 +1,5 @@
|
|||
from machine import Pin
|
||||
|
||||
# Freescale/NXP FRDM-K64F board
|
||||
# Blue LED on port B, pin 21
|
||||
LED = Pin(("GPIO_1", 21), Pin.OUT)
|
|
@ -0,0 +1,38 @@
|
|||
import utime
|
||||
from hwconfig import LED
|
||||
|
||||
|
||||
# Using sleep_ms() gives pretty poor PWM resolution and
|
||||
# brightness control, but we use it in the attempt to
|
||||
# make this demo portable to even more boards (e.g. to
|
||||
# those which don't provide sleep_us(), or provide, but
|
||||
# it's not precise, like would be on non realtime OSes).
|
||||
# We otherwise use 20ms period, to make frequency not less
|
||||
# than 50Hz to avoid visible flickering (you may still see
|
||||
# if you're unlucky).
|
||||
def pwm_cycle(led, duty, cycles):
|
||||
duty_off = 20 - duty
|
||||
for i in range(cycles):
|
||||
if duty:
|
||||
led.value(1)
|
||||
utime.sleep_ms(duty)
|
||||
if duty_off:
|
||||
led.value(0)
|
||||
utime.sleep_ms(duty_off)
|
||||
|
||||
|
||||
# At the duty setting of 1, an LED is still pretty bright, then
|
||||
# at duty 0, it's off. This makes rather unsmooth transition, and
|
||||
# breaks fade effect. So, we avoid value of 0 and oscillate between
|
||||
# 1 and 20. Actually, highest values like 19 and 20 are also
|
||||
# barely distinguishible (like, both of them too bright and burn
|
||||
# your eye). So, improvement to the visible effect would be to use
|
||||
# more steps (at least 10x), and then higher frequency, and use
|
||||
# range which includes 1 but excludes values at the top.
|
||||
while True:
|
||||
# Fade in
|
||||
for i in range(1, 21):
|
||||
pwm_cycle(LED, i, 2)
|
||||
# Fade out
|
||||
for i in range(20, 0, -1):
|
||||
pwm_cycle(LED, i, 2)
|
|
@ -1,3 +1,5 @@
|
|||
# Do not use this code in real projects! Read
|
||||
# http_server_simplistic_commented.py for details.
|
||||
try:
|
||||
import usocket as socket
|
||||
except:
|
||||
|
|
|
@ -62,6 +62,6 @@ typedef struct _fs_user_mount_t {
|
|||
fs_user_mount_t *fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, bool mkfs);
|
||||
mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(fsuser_mount_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(fsuser_umount_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(fsuser_mkfs_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(fsuser_mount_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(fsuser_umount_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(fsuser_mkfs_obj);
|
||||
|
|
|
@ -32,6 +32,6 @@
|
|||
|
||||
mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(machine_time_pulse_us_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj);
|
||||
|
||||
#endif // __MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H__
|
||||
|
|
|
@ -47,9 +47,9 @@ typedef struct _mp_machine_soft_spi_obj_t {
|
|||
|
||||
void mp_machine_soft_spi_transfer(mp_obj_base_t *self, size_t len, const uint8_t *src, uint8_t *dest);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_read_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_readinto_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_write_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_write_readinto_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj);
|
||||
|
||||
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <stddef.h>
|
||||
#include "py/runtime.h"
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_uos_dupterm_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj);
|
||||
|
||||
#if MICROPY_PY_OS_DUPTERM
|
||||
void mp_uos_dupterm_tx_strn(const char *str, size_t len);
|
||||
|
|
|
@ -33,10 +33,10 @@ extern mp_obj_t mod_binascii_a2b_base64(mp_obj_t data);
|
|||
extern mp_obj_t mod_binascii_b2a_base64(mp_obj_t data);
|
||||
extern mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_hexlify_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_unhexlify_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_a2b_base64_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_b2a_base64_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_crc32_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_hexlify_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mod_binascii_unhexlify_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj);
|
||||
|
||||
#endif /* MICROPY_EXTMOD_MODUBINASCII */
|
||||
|
|
|
@ -33,14 +33,17 @@
|
|||
#include "py/obj.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/smallint.h"
|
||||
#include "py/runtime.h"
|
||||
#include "extmod/utime_mphal.h"
|
||||
|
||||
STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_hal_delay_ms(1000 * mp_obj_get_float(seconds_o));
|
||||
#else
|
||||
mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o));
|
||||
#endif
|
||||
MP_THREAD_GIL_ENTER();
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_obj, time_sleep);
|
||||
|
@ -48,7 +51,9 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_obj, time_sleep);
|
|||
STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) {
|
||||
mp_int_t ms = mp_obj_get_int(arg);
|
||||
if (ms > 0) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
mp_hal_delay_ms(ms);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
@ -57,33 +62,47 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_ms_obj, time_sleep_ms);
|
|||
STATIC mp_obj_t time_sleep_us(mp_obj_t arg) {
|
||||
mp_int_t us = mp_obj_get_int(arg);
|
||||
if (us > 0) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
mp_hal_delay_us(us);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_us_obj, time_sleep_us);
|
||||
|
||||
STATIC mp_obj_t time_ticks_ms(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & MP_SMALL_INT_POSITIVE_MASK);
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_ms_obj, time_ticks_ms);
|
||||
|
||||
STATIC mp_obj_t time_ticks_us(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_us() & MP_SMALL_INT_POSITIVE_MASK);
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_us() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_us_obj, time_ticks_us);
|
||||
|
||||
STATIC mp_obj_t time_ticks_cpu(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_cpu() & MP_SMALL_INT_POSITIVE_MASK);
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_cpu() & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_cpu_obj, time_ticks_cpu);
|
||||
|
||||
STATIC mp_obj_t time_ticks_diff(mp_obj_t start_in, mp_obj_t end_in) {
|
||||
STATIC mp_obj_t time_ticks_diff(mp_obj_t end_in, mp_obj_t start_in) {
|
||||
// we assume that the arguments come from ticks_xx so are small ints
|
||||
uint32_t start = MP_OBJ_SMALL_INT_VALUE(start_in);
|
||||
uint32_t end = MP_OBJ_SMALL_INT_VALUE(end_in);
|
||||
return MP_OBJ_NEW_SMALL_INT((end - start) & MP_SMALL_INT_POSITIVE_MASK);
|
||||
mp_uint_t start = MP_OBJ_SMALL_INT_VALUE(start_in);
|
||||
mp_uint_t end = MP_OBJ_SMALL_INT_VALUE(end_in);
|
||||
// Optimized formula avoiding if conditions. We adjust difference "forward",
|
||||
// wrap it around and adjust back.
|
||||
mp_int_t diff = ((end - start + MICROPY_PY_UTIME_TICKS_PERIOD / 2) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1))
|
||||
- MICROPY_PY_UTIME_TICKS_PERIOD / 2;
|
||||
return MP_OBJ_NEW_SMALL_INT(diff);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj, time_ticks_diff);
|
||||
|
||||
STATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) {
|
||||
// we assume that first argument come from ticks_xx so is small int
|
||||
mp_uint_t ticks = MP_OBJ_SMALL_INT_VALUE(ticks_in);
|
||||
mp_uint_t delta = mp_obj_get_int(delta_in);
|
||||
return MP_OBJ_NEW_SMALL_INT((ticks + delta) & (MICROPY_PY_UTIME_TICKS_PERIOD - 1));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj, time_ticks_add);
|
||||
|
||||
#endif // MICROPY_PY_UTIME_MP_HAL
|
||||
|
|
|
@ -27,10 +27,11 @@
|
|||
|
||||
#include "py/obj.h"
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_utime_sleep_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_utime_sleep_ms_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_utime_sleep_us_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_utime_ticks_ms_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_utime_ticks_us_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_utime_ticks_cpu_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_utime_ticks_diff_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_ms_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_utime_sleep_us_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_ms_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_us_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_cpu_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj);
|
||||
|
|
|
@ -120,9 +120,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(file_obj_flush_obj, file_obj_flush);
|
|||
|
||||
STATIC mp_obj_t file_obj_close(mp_obj_t self_in) {
|
||||
pyb_file_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
FRESULT res = f_close(&self->fp);
|
||||
if (res != FR_OK) {
|
||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
||||
// if fs==NULL then the file is closed and in that case this method is a no-op
|
||||
if (self->fp.fs != NULL) {
|
||||
FRESULT res = f_close(&self->fp);
|
||||
if (res != FR_OK) {
|
||||
mp_raise_OSError(fresult_to_errno_table[res]);
|
||||
}
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,6 @@
|
|||
extern const byte fresult_to_errno_table[20];
|
||||
|
||||
mp_obj_t fatfs_builtin_open(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_open_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_open_obj);
|
||||
|
||||
mp_obj_t fat_vfs_listdir(const char *path, bool is_str_type);
|
||||
|
|
|
@ -86,19 +86,6 @@ double __aeabi_dmul(double x , double y) {
|
|||
|
||||
#endif // defined(__thumb__)
|
||||
|
||||
// TODO this needs a better way of testing for Thumb2 FP hardware
|
||||
#if defined(__thumb2__)
|
||||
|
||||
float sqrtf(float x) {
|
||||
asm volatile (
|
||||
"vsqrt.f32 %[r], %[x]\n"
|
||||
: [r] "=t" (x)
|
||||
: [x] "t" (x));
|
||||
return x;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
float copysignf(float x, float y) {
|
||||
float_s_t fx={.f = x};
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// an implementation of sqrtf for Thumb using hardware VFP instructions
|
||||
|
||||
#include <math.h>
|
||||
|
||||
float sqrtf(float x) {
|
||||
asm volatile (
|
||||
"vsqrt.f32 %[r], %[x]\n"
|
||||
: [r] "=t" (x)
|
||||
: [x] "t" (x));
|
||||
return x;
|
||||
}
|
|
@ -120,7 +120,9 @@ STATIC int parse_compile_execute(void *source, mp_parse_input_kind_t input_kind,
|
|||
{
|
||||
size_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes;
|
||||
qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes);
|
||||
printf("qstr:\n n_pool=" UINT_FMT "\n n_qstr=" UINT_FMT "\n n_str_data_bytes=" UINT_FMT "\n n_total_bytes=" UINT_FMT "\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes);
|
||||
printf("qstr:\n n_pool=" UINT_FMT "\n n_qstr=" UINT_FMT "\n "
|
||||
"n_str_data_bytes=" UINT_FMT "\n n_total_bytes=" UINT_FMT "\n",
|
||||
(unsigned)n_pool, (unsigned)n_qstr, (unsigned)n_str_data_bytes, (unsigned)n_total_bytes);
|
||||
}
|
||||
|
||||
#if MICROPY_ENABLE_GC
|
||||
|
|
|
@ -49,6 +49,6 @@ void pyexec_event_repl_init(void);
|
|||
int pyexec_event_repl_process_char(int c);
|
||||
extern uint8_t pyexec_repl_active;
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(pyb_set_repl_info_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(pyb_set_repl_info_obj);
|
||||
|
||||
#endif // __MICROPY_INCLUDED_LIB_UTILS_PYEXEC_H__
|
||||
|
|
|
@ -29,11 +29,11 @@
|
|||
#include "lib/utils/pyhelp.h"
|
||||
|
||||
STATIC void pyhelp_print_info_about_object(mp_obj_t name_o, mp_obj_t value) {
|
||||
printf(" ");
|
||||
mp_printf(MP_PYTHON_PRINTER, " ");
|
||||
mp_obj_print(name_o, PRINT_STR);
|
||||
printf(" -- ");
|
||||
mp_printf(MP_PYTHON_PRINTER, " -- ");
|
||||
mp_obj_print(value, PRINT_STR);
|
||||
printf("\n");
|
||||
mp_printf(MP_PYTHON_PRINTER, "\n");
|
||||
}
|
||||
|
||||
// Helper for 1-argument form of builtin help
|
||||
|
@ -57,9 +57,9 @@ STATIC void pyhelp_print_info_about_object(mp_obj_t name_o, mp_obj_t value) {
|
|||
//
|
||||
void pyhelp_print_obj(const mp_obj_t obj) {
|
||||
// try to print something sensible about the given object
|
||||
printf("object ");
|
||||
mp_printf(MP_PYTHON_PRINTER, "object ");
|
||||
mp_obj_print(obj, PRINT_STR);
|
||||
printf(" is of type %s\n", mp_obj_get_type_str(obj));
|
||||
mp_printf(MP_PYTHON_PRINTER, " is of type %s\n", mp_obj_get_type_str(obj));
|
||||
|
||||
mp_map_t *map = NULL;
|
||||
if (MP_OBJ_IS_TYPE(obj, &mp_type_module)) {
|
||||
|
|
|
@ -68,9 +68,11 @@ $(BUILD)/firmware.elf: $(OBJ)
|
|||
$(Q)$(LD) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
$(Q)$(SIZE) $@
|
||||
|
||||
$(BUILD)/firmware.dfu: $(BUILD)/firmware.elf
|
||||
$(ECHO) "Create $@"
|
||||
$(BUILD)/firmware.bin: $(BUILD)/firmware.elf
|
||||
$(Q)$(OBJCOPY) -O binary -j .isr_vector -j .text -j .data $^ $(BUILD)/firmware.bin
|
||||
|
||||
$(BUILD)/firmware.dfu: $(BUILD)/firmware.bin
|
||||
$(ECHO) "Create $@"
|
||||
$(Q)$(PYTHON) $(DFU) -b 0x08000000:$(BUILD)/firmware.bin $@
|
||||
|
||||
deploy: $(BUILD)/firmware.dfu
|
||||
|
|
|
@ -70,7 +70,6 @@ typedef long mp_off_t;
|
|||
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
|
||||
|
||||
// extra built in names to add to the global namespace
|
||||
extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
|
||||
#define MICROPY_PORT_BUILTINS \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
|
||||
|
||||
|
|
|
@ -88,7 +88,6 @@ typedef int mp_off_t;
|
|||
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
|
||||
|
||||
// extra builtin names to add to the global namespace
|
||||
extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
|
||||
#define MICROPY_PORT_BUILTINS \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
|
||||
|
||||
|
|
97
py/builtin.h
97
py/builtin.h
|
@ -32,56 +32,56 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args);
|
|||
mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
|
||||
mp_obj_t mp_micropython_mem_info(size_t n_args, const mp_obj_t *args);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin___build_class___obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin___import___obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin___repl_print___obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_abs_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_all_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_any_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_bin_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_callable_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_compile_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_chr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_dir_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_divmod_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_eval_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_exec_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_execfile_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_getattr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_setattr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_globals_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hasattr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hash_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_hex_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_id_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_isinstance_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_issubclass_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_iter_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_len_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_list_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_locals_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_max_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_min_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_next_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_oct_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_ord_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_pow_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_print_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_repr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_round_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sorted_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sum_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR(mp_builtin___build_class___obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin___import___obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin___repl_print___obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_abs_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_all_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_any_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_bin_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_callable_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_compile_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_chr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_delattr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_dir_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_divmod_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_eval_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_exec_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_execfile_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_getattr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_3(mp_builtin_setattr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(mp_builtin_globals_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_hasattr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_hash_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_hex_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_id_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_iter_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_len_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_0(mp_builtin_locals_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_max_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_min_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_next_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_oct_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_ord_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_pow_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_print_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_builtin_repr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj);
|
||||
// Defined by a port, but declared here for simplicity
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_help_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_input_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_open_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_input_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_open_obj);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_namedtuple_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_namedtuple_obj);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_op_contains_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_op_getitem_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_op_setitem_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_op_delitem_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_op_contains_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_op_getitem_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_3(mp_op_setitem_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_2(mp_op_delitem_obj);
|
||||
|
||||
extern const mp_obj_module_t mp_module___main__;
|
||||
extern const mp_obj_module_t mp_module_builtins;
|
||||
|
@ -116,7 +116,4 @@ extern const mp_obj_module_t mp_module_webrepl;
|
|||
extern const mp_obj_module_t mp_module_framebuf;
|
||||
extern const mp_obj_module_t mp_module_btree;
|
||||
|
||||
// extmod functions
|
||||
MP_DECLARE_CONST_FUN_OBJ(pyb_mount_obj);
|
||||
|
||||
#endif // __MICROPY_INCLUDED_PY_BUILTIN_H__
|
||||
|
|
|
@ -183,7 +183,6 @@ STATIC void emit_write_bytecode_byte(emit_t *emit, byte b1) {
|
|||
}
|
||||
|
||||
STATIC void emit_write_bytecode_byte_byte(emit_t* emit, byte b1, byte b2) {
|
||||
assert((b2 & (~0xff)) == 0);
|
||||
byte *c = emit_get_cur_to_write_bytecode(emit, 2);
|
||||
c[0] = b1;
|
||||
c[1] = b2;
|
||||
|
@ -550,7 +549,6 @@ void mp_emit_bc_load_null(emit_t *emit) {
|
|||
|
||||
void mp_emit_bc_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
|
||||
(void)qst;
|
||||
assert(local_num >= 0);
|
||||
emit_bc_pre(emit, 1);
|
||||
if (local_num <= 15) {
|
||||
emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_MULTI + local_num);
|
||||
|
@ -608,7 +606,6 @@ void mp_emit_bc_load_subscr(emit_t *emit) {
|
|||
|
||||
void mp_emit_bc_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
|
||||
(void)qst;
|
||||
assert(local_num >= 0);
|
||||
emit_bc_pre(emit, -1);
|
||||
if (local_num <= 15) {
|
||||
emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_MULTI + local_num);
|
||||
|
@ -927,7 +924,7 @@ void mp_emit_bc_return_value(emit_t *emit) {
|
|||
}
|
||||
|
||||
void mp_emit_bc_raise_varargs(emit_t *emit, mp_uint_t n_args) {
|
||||
assert(0 <= n_args && n_args <= 2);
|
||||
assert(n_args <= 2);
|
||||
emit_bc_pre(emit, -n_args);
|
||||
emit_write_bytecode_byte_byte(emit, MP_BC_RAISE_VARARGS, n_args);
|
||||
}
|
||||
|
|
|
@ -59,6 +59,8 @@ LD += -m32
|
|||
endif
|
||||
|
||||
MAKE_FROZEN = ../tools/make-frozen.py
|
||||
MPY_CROSS = ../mpy-cross/mpy-cross
|
||||
MPY_TOOL = ../tools/mpy-tool.py
|
||||
|
||||
all:
|
||||
.PHONY: all
|
||||
|
|
|
@ -106,6 +106,23 @@ $(BUILD)/frozen.c: $(wildcard $(FROZEN_DIR)/*) $(HEADER_BUILD) $(FROZEN_EXTRA_DE
|
|||
$(Q)$(MAKE_FROZEN) $(FROZEN_DIR) > $@
|
||||
endif
|
||||
|
||||
ifneq ($(FROZEN_MPY_DIR),)
|
||||
# make a list of all the .py files that need compiling and freezing
|
||||
FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py' -printf '%P\n')
|
||||
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/frozen_mpy/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
|
||||
|
||||
# to build .mpy files from .py files
|
||||
$(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/%.py
|
||||
@$(ECHO) "MPY $<"
|
||||
$(Q)$(MKDIR) -p $(dir $@)
|
||||
$(Q)$(MPY_CROSS) -o $@ -s $(^:$(FROZEN_MPY_DIR)/%=%) $^
|
||||
|
||||
# to build frozen_mpy.c from all .mpy files
|
||||
$(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h
|
||||
@$(ECHO) "Creating $@"
|
||||
$(Q)$(PYTHON) $(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h $(FROZEN_MPY_MPY_FILES) > $@
|
||||
endif
|
||||
|
||||
ifneq ($(PROG),)
|
||||
# Build a standalone executable (unix does this)
|
||||
|
||||
|
|
|
@ -430,13 +430,8 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_print_obj, 0, mp_builtin_print);
|
|||
|
||||
STATIC mp_obj_t mp_builtin___repl_print__(mp_obj_t o) {
|
||||
if (o != mp_const_none) {
|
||||
#if MICROPY_PY_IO
|
||||
mp_obj_print_helper(&mp_sys_stdout_print, o, PRINT_REPR);
|
||||
mp_print_str(&mp_sys_stdout_print, "\n");
|
||||
#else
|
||||
mp_obj_print_helper(&mp_plat_print, o, PRINT_REPR);
|
||||
mp_print_str(&mp_plat_print, "\n");
|
||||
#endif
|
||||
mp_obj_print_helper(MP_PYTHON_PRINTER, o, PRINT_REPR);
|
||||
mp_print_str(MP_PYTHON_PRINTER, "\n");
|
||||
#if MICROPY_CAN_OVERRIDE_BUILTINS
|
||||
// Set "_" special variable
|
||||
mp_obj_t dest[2] = {MP_OBJ_SENTINEL, o};
|
||||
|
@ -547,6 +542,13 @@ STATIC mp_obj_t mp_builtin_setattr(mp_obj_t base, mp_obj_t attr, mp_obj_t value)
|
|||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(mp_builtin_setattr_obj, mp_builtin_setattr);
|
||||
|
||||
#if MICROPY_CPYTHON_COMPAT
|
||||
STATIC mp_obj_t mp_builtin_delattr(mp_obj_t base, mp_obj_t attr) {
|
||||
return mp_builtin_setattr(base, attr, MP_OBJ_NULL);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_delattr_obj, mp_builtin_delattr);
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t mp_builtin_hasattr(mp_obj_t object_in, mp_obj_t attr_in) {
|
||||
qstr attr = mp_obj_str_get_qstr(attr_in);
|
||||
|
||||
|
@ -622,6 +624,9 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = {
|
|||
#if MICROPY_PY_BUILTINS_SET
|
||||
{ MP_ROM_QSTR(MP_QSTR_set), MP_ROM_PTR(&mp_type_set) },
|
||||
#endif
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
{ MP_ROM_QSTR(MP_QSTR_slice), MP_ROM_PTR(&mp_type_slice) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_str), MP_ROM_PTR(&mp_type_str) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_super), MP_ROM_PTR(&mp_type_super) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_tuple), MP_ROM_PTR(&mp_type_tuple) },
|
||||
|
@ -647,6 +652,9 @@ STATIC const mp_rom_map_elem_t mp_module_builtins_globals_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_compile), MP_ROM_PTR(&mp_builtin_compile_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_chr), MP_ROM_PTR(&mp_builtin_chr_obj) },
|
||||
#if MICROPY_CPYTHON_COMPAT
|
||||
{ MP_ROM_QSTR(MP_QSTR_delattr), MP_ROM_PTR(&mp_builtin_delattr_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_dir), MP_ROM_PTR(&mp_builtin_dir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_divmod), MP_ROM_PTR(&mp_builtin_divmod_obj) },
|
||||
#if MICROPY_PY_BUILTINS_EVAL_EXEC
|
||||
|
|
|
@ -32,9 +32,8 @@
|
|||
#include <math.h>
|
||||
|
||||
// M_PI is not part of the math.h standard and may not be defined
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265358979323846)
|
||||
#endif
|
||||
// And by defining our own we can ensure it uses the correct const format.
|
||||
#define MP_PI MICROPY_FLOAT_CONST(3.14159265358979323846)
|
||||
|
||||
/// \module math - mathematical functions
|
||||
///
|
||||
|
@ -204,13 +203,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_modf_obj, mp_math_modf);
|
|||
|
||||
/// \function radians(x)
|
||||
STATIC mp_obj_t mp_math_radians(mp_obj_t x_obj) {
|
||||
return mp_obj_new_float(mp_obj_get_float(x_obj) * M_PI / 180.0);
|
||||
return mp_obj_new_float(mp_obj_get_float(x_obj) * (MP_PI / MICROPY_FLOAT_CONST(180.0)));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_radians_obj, mp_math_radians);
|
||||
|
||||
/// \function degrees(x)
|
||||
STATIC mp_obj_t mp_math_degrees(mp_obj_t x_obj) {
|
||||
return mp_obj_new_float(mp_obj_get_float(x_obj) * 180.0 / M_PI);
|
||||
return mp_obj_new_float(mp_obj_get_float(x_obj) * (MICROPY_FLOAT_CONST(180.0) / MP_PI));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_degrees_obj, mp_math_degrees);
|
||||
|
||||
|
|
|
@ -110,10 +110,11 @@
|
|||
// Be conservative and always clear to zero newly (re)allocated memory in the GC.
|
||||
// This helps eliminate stray pointers that hold on to memory that's no longer
|
||||
// used. It decreases performance due to unnecessary memory clearing.
|
||||
// A memory manager which always clears memory can set this to 0.
|
||||
// TODO Do analysis to understand why some memory is not properly cleared and
|
||||
// find a more efficient way to clear it.
|
||||
#ifndef MICROPY_GC_CONSERVATIVE_CLEAR
|
||||
#define MICROPY_GC_CONSERVATIVE_CLEAR (1)
|
||||
#define MICROPY_GC_CONSERVATIVE_CLEAR (MICROPY_ENABLE_GC)
|
||||
#endif
|
||||
|
||||
// Support automatic GC when reaching allocation threshold,
|
||||
|
@ -504,10 +505,12 @@ typedef long long mp_longint_impl_t;
|
|||
|
||||
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
|
||||
#define MICROPY_PY_BUILTINS_FLOAT (1)
|
||||
#define MICROPY_FLOAT_CONST(x) x##F
|
||||
#define MICROPY_FLOAT_C_FUN(fun) fun##f
|
||||
typedef float mp_float_t;
|
||||
#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
|
||||
#define MICROPY_PY_BUILTINS_FLOAT (1)
|
||||
#define MICROPY_FLOAT_CONST(x) x
|
||||
#define MICROPY_FLOAT_C_FUN(fun) fun
|
||||
typedef double mp_float_t;
|
||||
#else
|
||||
|
@ -866,6 +869,16 @@ typedef double mp_float_t;
|
|||
#define MICROPY_PY_UTIME_MP_HAL (0)
|
||||
#endif
|
||||
|
||||
// Period of values returned by utime.ticks_ms(), ticks_us(), ticks_cpu()
|
||||
// functions. Should be power of two. All functions above use the same
|
||||
// period, so if underlying hardware/API has different periods, the
|
||||
// minimum of them should be used. The value below is the maximum value
|
||||
// this parameter can take (corresponding to 30 bit tick values on 32-bit
|
||||
// system).
|
||||
#ifndef MICROPY_PY_UTIME_TICKS_PERIOD
|
||||
#define MICROPY_PY_UTIME_TICKS_PERIOD (MP_SMALL_INT_POSITIVE_MASK + 1)
|
||||
#endif
|
||||
|
||||
// Whether to provide "_thread" module
|
||||
#ifndef MICROPY_PY_THREAD
|
||||
#define MICROPY_PY_THREAD (0)
|
||||
|
|
|
@ -39,6 +39,12 @@
|
|||
#define PF_FLAG_ADD_PERCENT (0x100)
|
||||
#define PF_FLAG_SHOW_OCTAL_LETTER (0x200)
|
||||
|
||||
#if MICROPY_PY_IO
|
||||
# define MP_PYTHON_PRINTER &mp_sys_stdout_print
|
||||
#else
|
||||
# define MP_PYTHON_PRINTER &mp_plat_print
|
||||
#endif
|
||||
|
||||
typedef void (*mp_print_strn_t)(void *data, const char *str, size_t len);
|
||||
|
||||
typedef struct _mp_print_t {
|
||||
|
|
5
py/mpz.c
5
py/mpz.c
|
@ -1652,7 +1652,10 @@ char *mpz_as_str(const mpz_t *i, mp_uint_t base) {
|
|||
// assumes enough space as calculated by mp_int_format_size
|
||||
// returns length of string, not including null byte
|
||||
mp_uint_t mpz_as_str_inpl(const mpz_t *i, mp_uint_t base, const char *prefix, char base_char, char comma, char *str) {
|
||||
if (str == NULL || base < 2 || base > 32) {
|
||||
if (str == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if (base < 2 || base > 32) {
|
||||
str[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
34
py/nlrx86.S
34
py/nlrx86.S
|
@ -37,9 +37,18 @@
|
|||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define NLR_OS_WINDOWS
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#define NLR_OS_MAC
|
||||
#endif
|
||||
|
||||
#if defined(NLR_OS_WINDOWS) || defined(NLR_OS_MAC)
|
||||
#define NLR_TOP (_mp_state_ctx + NLR_TOP_OFFSET)
|
||||
#define MP_THREAD_GET_STATE _mp_thread_get_state
|
||||
#else
|
||||
#define NLR_TOP (mp_state_ctx + NLR_TOP_OFFSET)
|
||||
#define MP_THREAD_GET_STATE mp_thread_get_state
|
||||
#endif
|
||||
|
||||
// offset of nlr_top within mp_state_thread_t structure
|
||||
|
@ -55,6 +64,9 @@
|
|||
.globl _nlr_push
|
||||
.def _nlr_push; .scl 2; .type 32; .endef
|
||||
_nlr_push:
|
||||
#elif defined(NLR_OS_MAC)
|
||||
.globl _nlr_push
|
||||
_nlr_push:
|
||||
#else
|
||||
.globl nlr_push
|
||||
.type nlr_push, @function
|
||||
|
@ -75,7 +87,7 @@ nlr_push:
|
|||
mov %edx, NLR_TOP # stor new nlr_buf (to make linked list)
|
||||
#else
|
||||
// to check: stack is aligned to 16-byte boundary before this call
|
||||
call mp_thread_get_state # get mp_state_thread ptr into eax
|
||||
call MP_THREAD_GET_STATE # get mp_state_thread ptr into eax
|
||||
mov 4(%esp), %edx # load nlr_buf argument into edx (edx clobbered by call)
|
||||
mov NLR_TOP_TH_OFF(%eax), %ecx # get thread.nlr_top (last nlr_buf)
|
||||
mov %ecx, (%edx) # store it
|
||||
|
@ -84,7 +96,7 @@ nlr_push:
|
|||
|
||||
xor %eax, %eax # return 0, normal return
|
||||
ret # return
|
||||
#if !defined(NLR_OS_WINDOWS)
|
||||
#if !defined(NLR_OS_WINDOWS) && !defined(NLR_OS_MAC)
|
||||
.size nlr_push, .-nlr_push
|
||||
#endif
|
||||
|
||||
|
@ -95,6 +107,9 @@ nlr_push:
|
|||
.globl _nlr_pop
|
||||
.def _nlr_pop; .scl 2; .type 32; .endef
|
||||
_nlr_pop:
|
||||
#elif defined(NLR_OS_MAC)
|
||||
.globl _nlr_pop
|
||||
_nlr_pop:
|
||||
#else
|
||||
.globl nlr_pop
|
||||
.type nlr_pop, @function
|
||||
|
@ -106,14 +121,14 @@ nlr_pop:
|
|||
mov (%eax), %eax # load prev nlr_buf
|
||||
mov %eax, NLR_TOP # store nlr_top (to unlink list)
|
||||
#else
|
||||
call mp_thread_get_state # get mp_state_thread ptr into eax
|
||||
call MP_THREAD_GET_STATE # get mp_state_thread ptr into eax
|
||||
mov NLR_TOP_TH_OFF(%eax), %ecx # get thread.nlr_top (last nlr_buf)
|
||||
mov (%ecx), %ecx # load prev nlr_buf
|
||||
mov %ecx, NLR_TOP_TH_OFF(%eax) # store prev nlr_buf (to unlink list)
|
||||
#endif
|
||||
|
||||
ret # return
|
||||
#if !defined(NLR_OS_WINDOWS)
|
||||
#if !defined(NLR_OS_WINDOWS) && !defined(NLR_OS_MAC)
|
||||
.size nlr_pop, .-nlr_pop
|
||||
#endif
|
||||
|
||||
|
@ -124,6 +139,9 @@ nlr_pop:
|
|||
.globl _nlr_jump
|
||||
.def _nlr_jump; .scl 2; .type 32; .endef
|
||||
_nlr_jump:
|
||||
#elif defined(NLR_OS_MAC)
|
||||
.globl _nlr_jump
|
||||
_nlr_jump:
|
||||
#else
|
||||
.globl nlr_jump
|
||||
.type nlr_jump, @function
|
||||
|
@ -133,7 +151,7 @@ nlr_jump:
|
|||
#if !MICROPY_PY_THREAD
|
||||
mov NLR_TOP, %edx # load nlr_top
|
||||
test %edx, %edx # check for nlr_top being NULL
|
||||
#if defined(NLR_OS_WINDOWS)
|
||||
#if defined(NLR_OS_WINDOWS) || defined(NLR_OS_MAC)
|
||||
je _nlr_jump_fail # fail if nlr_top is NULL
|
||||
#else
|
||||
je nlr_jump_fail # fail if nlr_top is NULL
|
||||
|
@ -143,10 +161,10 @@ nlr_jump:
|
|||
mov (%edx), %eax # load prev nlr_top
|
||||
mov %eax, NLR_TOP # store nlr_top (to unlink list)
|
||||
#else
|
||||
call mp_thread_get_state # get mp_state_thread ptr into eax
|
||||
call MP_THREAD_GET_STATE # get mp_state_thread ptr into eax
|
||||
mov NLR_TOP_TH_OFF(%eax), %edx # get thread.nlr_top (last nlr_buf)
|
||||
test %edx, %edx # check for nlr_top being NULL
|
||||
#if defined(NLR_OS_WINDOWS)
|
||||
#if defined(NLR_OS_WINDOWS) || defined(NLR_OS_MAC)
|
||||
je _nlr_jump_fail # fail if nlr_top is NULL
|
||||
#else
|
||||
je nlr_jump_fail # fail if nlr_top is NULL
|
||||
|
@ -167,7 +185,7 @@ nlr_jump:
|
|||
xor %eax, %eax # clear return register
|
||||
inc %al # increase to make 1, non-local return
|
||||
ret # return
|
||||
#if !defined(NLR_OS_WINDOWS)
|
||||
#if !defined(NLR_OS_WINDOWS) && !defined(NLR_OS_MAC)
|
||||
.size nlr_jump, .-nlr_jump
|
||||
#endif
|
||||
|
||||
|
|
6
py/obj.c
6
py/obj.c
|
@ -76,11 +76,7 @@ void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t
|
|||
}
|
||||
|
||||
void mp_obj_print(mp_obj_t o_in, mp_print_kind_t kind) {
|
||||
#if MICROPY_PY_IO
|
||||
mp_obj_print_helper(&mp_sys_stdout_print, o_in, kind);
|
||||
#else
|
||||
mp_obj_print_helper(&mp_plat_print, o_in, kind);
|
||||
#endif
|
||||
mp_obj_print_helper(MP_PYTHON_PRINTER, o_in, kind);
|
||||
}
|
||||
|
||||
// helper function to print an exception with traceback
|
||||
|
|
63
py/obj.h
63
py/obj.h
|
@ -270,29 +270,35 @@ static inline bool mp_obj_is_integer(mp_const_obj_t o) { return MP_OBJ_IS_INT(o)
|
|||
// These macros are used to declare and define constant function objects
|
||||
// You can put "static" in front of the definitions to make them local
|
||||
|
||||
#define MP_DECLARE_CONST_FUN_OBJ(obj_name) extern const mp_obj_fun_builtin_t obj_name
|
||||
#define MP_DECLARE_CONST_FUN_OBJ_0(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name
|
||||
#define MP_DECLARE_CONST_FUN_OBJ_1(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name
|
||||
#define MP_DECLARE_CONST_FUN_OBJ_2(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name
|
||||
#define MP_DECLARE_CONST_FUN_OBJ_3(obj_name) extern const mp_obj_fun_builtin_fixed_t obj_name
|
||||
#define MP_DECLARE_CONST_FUN_OBJ_VAR(obj_name) extern const mp_obj_fun_builtin_var_t obj_name
|
||||
#define MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name) extern const mp_obj_fun_builtin_var_t obj_name
|
||||
#define MP_DECLARE_CONST_FUN_OBJ_KW(obj_name) extern const mp_obj_fun_builtin_var_t obj_name
|
||||
|
||||
#define MP_DEFINE_CONST_FUN_OBJ_0(obj_name, fun_name) \
|
||||
const mp_obj_fun_builtin_t obj_name = \
|
||||
{{&mp_type_fun_builtin}, false, 0, 0, .fun._0 = fun_name}
|
||||
const mp_obj_fun_builtin_fixed_t obj_name = \
|
||||
{{&mp_type_fun_builtin_0}, .fun._0 = fun_name}
|
||||
#define MP_DEFINE_CONST_FUN_OBJ_1(obj_name, fun_name) \
|
||||
const mp_obj_fun_builtin_t obj_name = \
|
||||
{{&mp_type_fun_builtin}, false, 1, 1, .fun._1 = fun_name}
|
||||
const mp_obj_fun_builtin_fixed_t obj_name = \
|
||||
{{&mp_type_fun_builtin_1}, .fun._1 = fun_name}
|
||||
#define MP_DEFINE_CONST_FUN_OBJ_2(obj_name, fun_name) \
|
||||
const mp_obj_fun_builtin_t obj_name = \
|
||||
{{&mp_type_fun_builtin}, false, 2, 2, .fun._2 = fun_name}
|
||||
const mp_obj_fun_builtin_fixed_t obj_name = \
|
||||
{{&mp_type_fun_builtin_2}, .fun._2 = fun_name}
|
||||
#define MP_DEFINE_CONST_FUN_OBJ_3(obj_name, fun_name) \
|
||||
const mp_obj_fun_builtin_t obj_name = \
|
||||
{{&mp_type_fun_builtin}, false, 3, 3, .fun._3 = fun_name}
|
||||
const mp_obj_fun_builtin_fixed_t obj_name = \
|
||||
{{&mp_type_fun_builtin_3}, .fun._3 = fun_name}
|
||||
#define MP_DEFINE_CONST_FUN_OBJ_VAR(obj_name, n_args_min, fun_name) \
|
||||
const mp_obj_fun_builtin_t obj_name = \
|
||||
{{&mp_type_fun_builtin}, false, n_args_min, MP_OBJ_FUN_ARGS_MAX, .fun.var = fun_name}
|
||||
const mp_obj_fun_builtin_var_t obj_name = \
|
||||
{{&mp_type_fun_builtin_var}, false, n_args_min, MP_OBJ_FUN_ARGS_MAX, .fun.var = fun_name}
|
||||
#define MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(obj_name, n_args_min, n_args_max, fun_name) \
|
||||
const mp_obj_fun_builtin_t obj_name = \
|
||||
{{&mp_type_fun_builtin}, false, n_args_min, n_args_max, .fun.var = fun_name}
|
||||
const mp_obj_fun_builtin_var_t obj_name = \
|
||||
{{&mp_type_fun_builtin_var}, false, n_args_min, n_args_max, .fun.var = fun_name}
|
||||
#define MP_DEFINE_CONST_FUN_OBJ_KW(obj_name, n_args_min, fun_name) \
|
||||
const mp_obj_fun_builtin_t obj_name = \
|
||||
{{&mp_type_fun_builtin}, true, n_args_min, MP_OBJ_FUN_ARGS_MAX, .fun.kw = fun_name}
|
||||
const mp_obj_fun_builtin_var_t obj_name = \
|
||||
{{&mp_type_fun_builtin_var}, true, n_args_min, MP_OBJ_FUN_ARGS_MAX, .fun.kw = fun_name}
|
||||
|
||||
// These macros are used to define constant map/dict objects
|
||||
// You can put "static" in front of the definition to make it local
|
||||
|
@ -530,7 +536,11 @@ extern const mp_obj_type_t mp_type_zip;
|
|||
extern const mp_obj_type_t mp_type_array;
|
||||
extern const mp_obj_type_t mp_type_super;
|
||||
extern const mp_obj_type_t mp_type_gen_instance;
|
||||
extern const mp_obj_type_t mp_type_fun_builtin;
|
||||
extern const mp_obj_type_t mp_type_fun_builtin_0;
|
||||
extern const mp_obj_type_t mp_type_fun_builtin_1;
|
||||
extern const mp_obj_type_t mp_type_fun_builtin_2;
|
||||
extern const mp_obj_type_t mp_type_fun_builtin_3;
|
||||
extern const mp_obj_type_t mp_type_fun_builtin_var;
|
||||
extern const mp_obj_type_t mp_type_fun_bc;
|
||||
extern const mp_obj_type_t mp_type_module;
|
||||
extern const mp_obj_type_t mp_type_staticmethod;
|
||||
|
@ -740,27 +750,34 @@ void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item);
|
|||
void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step);
|
||||
|
||||
// functions
|
||||
#define MP_OBJ_FUN_ARGS_MAX (0xffff) // to set maximum value in n_args_max below
|
||||
typedef struct _mp_obj_fun_builtin_t { // use this to make const objects that go in ROM
|
||||
|
||||
typedef struct _mp_obj_fun_builtin_fixed_t {
|
||||
mp_obj_base_t base;
|
||||
bool is_kw : 1;
|
||||
mp_uint_t n_args_min : 15; // inclusive
|
||||
mp_uint_t n_args_max : 16; // inclusive
|
||||
union {
|
||||
mp_fun_0_t _0;
|
||||
mp_fun_1_t _1;
|
||||
mp_fun_2_t _2;
|
||||
mp_fun_3_t _3;
|
||||
} fun;
|
||||
} mp_obj_fun_builtin_fixed_t;
|
||||
|
||||
#define MP_OBJ_FUN_ARGS_MAX (0xffff) // to set maximum value in n_args_max below
|
||||
typedef struct _mp_obj_fun_builtin_var_t {
|
||||
mp_obj_base_t base;
|
||||
bool is_kw : 1;
|
||||
mp_uint_t n_args_min : 15; // inclusive
|
||||
mp_uint_t n_args_max : 16; // inclusive
|
||||
union {
|
||||
mp_fun_var_t var;
|
||||
mp_fun_kw_t kw;
|
||||
} fun;
|
||||
} mp_obj_fun_builtin_t;
|
||||
} mp_obj_fun_builtin_var_t;
|
||||
|
||||
qstr mp_obj_fun_get_name(mp_const_obj_t fun);
|
||||
qstr mp_obj_code_get_name(const byte *code_info);
|
||||
|
||||
mp_obj_t mp_identity(mp_obj_t self);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_identity_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ_1(mp_identity_obj);
|
||||
|
||||
// module
|
||||
typedef struct _mp_obj_module_t {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue