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:
Scott Shawcroft 2016-11-14 10:20:16 -08:00
commit bd36873362
177 changed files with 3234 additions and 1071 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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 },

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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
--------------

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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
---------

View File

@ -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()

View File

@ -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
----

View File

@ -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

View File

@ -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*

View File

@ -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);

View File

@ -1,6 +1,7 @@
"""NRF24L01 driver for Micro Python
"""
from micropython import const
import pyb
# nRF24L01+ registers

View File

@ -21,6 +21,7 @@ Example usage on ESP8266:
"""
from micropython import const
import time

View File

@ -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

View File

@ -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
-----------

View File

@ -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*)

303
esp8266/esp8266_512k.ld Normal file
View File

@ -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"

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -28,7 +28,7 @@
#include "etshal.h"
#include "user_interface.h"
#include "modpyb.h"
#include "modmachine.h"
#include "esponewire.h"
#define TIMING_RESET1 (0)

View File

@ -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_

View File

@ -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) {

View File

@ -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) {

View File

@ -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)))

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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 },

View File

@ -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"

View File

@ -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__

View File

@ -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;
}

View File

@ -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) {

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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):

View File

@ -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):

1
esp8266/modules/upip.py Symbolic link
View File

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

View File

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

View File

@ -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):

View File

@ -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()

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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()

126
examples/hwapi/README.md Normal file
View File

@ -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!

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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:

View File

@ -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);

View File

@ -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__

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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};

View File

@ -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;
}

View File

@ -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

View File

@ -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__

View File

@ -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)) {

View File

@ -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

View File

@ -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 },

View File

@ -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 },

View File

@ -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__

View File

@ -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);
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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 {

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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