Compare commits

..

189 Commits
v1.8 ... v1.8.1

Author SHA1 Message Date
Damien George
9b39263b11 docs: Bump version to 1.8.1. 2016-06-03 15:45:43 +01:00
Damien George
97ce5d1d77 tests/pyb/rtc: Make RTC test on pyboard more reliable by calling init(). 2016-06-03 15:13:39 +01:00
Damien George
7d60a97914 tests/misc/recursive_iternext: Provide more fine-grained selection of N.
To work on a variety of ports the selection of N is very specific.
2016-06-03 15:09:45 +01:00
puuu
3f6ca4b22c docs/esp8266/general: Add note about RTC overflow. 2016-06-03 14:37:49 +01:00
puuu
cafdfb7af3 esp8266/modpybrtc: Handle RTC overflow.
ESP-SDK system_get_rtc_time() returns uint32 and therefore overflow
about every 7:45h.  Let's write the last state of system_get_rtc_time()
in RTC mem and use it to check for overflow. This commit require running
pyb_rtc_get_us_since_2000() at least once within 7 hours to avoid
overflow.
2016-06-03 14:37:49 +01:00
Tobias Badertscher
1191ec6a14 stmhal/uart.c: Fix wrong baudrate calculation for stm32l4 series. 2016-06-03 14:24:59 +01:00
Radomir Dopieralski
43c8f545d2 drivers/display/ssd1306: update SSD1306_SPI to work with new API
Makes it work on the ESP8266.
2016-06-03 11:13:17 +01:00
Damien George
ddadbaed06 tests/misc/recursive_iternext.py: Increase depth N from 1000 to 2000.
This makes the test reliably overflow the recursion limit (which is the
correct behaviour) on Mac OS X.
2016-06-03 09:33:57 +01:00
Paul Sokolovsky
1bc8aa85a4 lib/timeutils/timeutils: Fix pedantic warning in coverage build. 2016-06-03 10:46:15 +03:00
Paul Sokolovsky
993cc3611a lib/timeutils/timeutils: timeutils_mktime may accept negative time values.
And will normalize them.
2016-06-02 22:52:42 +03:00
Paul Sokolovsky
d8cc51ea2b docs/esp8266/quickref: Update WebREPL section for 1.8.1 release.
WebREPL is much more stable now.
2016-06-02 20:11:40 +03:00
Damien George
ed4e5d2583 docs/library/index: Fix grammar and spelling in intro paragraph. 2016-06-02 11:05:13 +01:00
Marcel Stör
0b9725812e docs/wipy/tutorial: Add note about screen key bindings on OS X. 2016-06-02 00:13:21 +03:00
Paul Sokolovsky
e456b2cc94 docs/README: Add some hints for PDF docs generation. 2016-06-02 00:08:47 +03:00
Paul Sokolovsky
09f764dc04 docs/library/index: Add intro paragraph regarding availability of modules.
This introductions makes explicit the fact that whenever possible,
the documentation describes full MicroPython functionality, and arbitrary
functions/classes/modules may be missing in a paricular port or build.
2016-06-02 00:08:07 +03:00
Paul Sokolovsky
9a1a49ceec esp8266/general: Typo/grammar fixes. 2016-06-01 23:16:17 +03:00
Paul Sokolovsky
fdf45a718b esp8266/quickref: Use local image of Adafruit Huzzah board.
Using remote image causes problems with tools (partly because the image
is semi-firewalled and can't be accessed by arbitrary tools).
2016-06-01 23:11:49 +03:00
Paul Sokolovsky
c4ab8895e8 docs: math, cmath: Add port availability information. 2016-06-01 22:12:39 +03:00
Paul Sokolovsky
1a05a59116 docs/math: Typo fix. 2016-06-01 22:09:51 +03:00
Damien George
927388e80e esp8266: Provide a dedicated variable to disable ets_loop_iter.
So ets_loop_iter is now only disabled when using machine.disable_irq.
2016-06-01 17:26:49 +01:00
Damien George
752e952096 esp8266/rtc: Set RTC user memory length to 0 on first boot.
So that RTC.memory() returns b'' on power up if it was never set.

Fixes issue #2138.
2016-06-01 11:33:04 +01:00
Robert HH
4f3fbf09cc esp8266/moduos.c: Add stat() to the module uos of esp8266.
This implementation makes use of vfs.stat() and therefore has the same
properties. Known issues for all ports: uos.stat(".") on the top level
returns the error code 22, EINVAL. The same happens with
uos.stat("dirname/") where dirname IS the name of a directory.
2016-05-31 23:00:38 +03:00
Paul Sokolovsky
15eb1ce52d esp8266: Enable MICROPY_PY_IO_FILEIO to get compliant text/binary streams. 2016-05-31 21:46:02 +03:00
Damien George
33168081f4 extmod/machine: Add MICROPY_PY_MACHINE_PULSE config for time_pulse_us.
Since not all ports that enable the machine module have the pin HAL
functions.
2016-05-31 14:25:19 +01:00
Damien George
cff2b7a6e3 esp8266/modmachine: Add machine.time_pulse_us function. 2016-05-31 14:06:50 +01:00
Damien George
93a9c2e840 docs/library/machine: Add documentation for machine.time_pulse_us. 2016-05-31 14:06:33 +01:00
Damien George
4940bee62a extmod: Add machine time_pulse_us function (at C and Python level).
The C implementation is taken from the DHT driver.
2016-05-31 13:58:48 +01:00
Paul Sokolovsky
298c2ae2c7 extmod/vfs_fat: Mark anused "self" arg for fat_vfs_stat(). 2016-05-31 15:42:08 +03:00
Peter Hinch
641300dccb stmhal/dac: DAC deinit() method added. 2016-05-31 13:10:35 +03:00
Robert HH
ee009d713a extmod/vfs_fat.c: Add vfs.stat().
The call to stat() returns a 10 element tuple consistent to the os.stat()
call. At the moment, the only relevant information returned are file
type and file size.
2016-05-31 13:03:12 +03:00
Tomas R
7d4fd8b6db docs/esp8266/general: Remove duplicate phrase. 2016-05-30 19:20:11 +03:00
Paul Sokolovsky
225562d915 esp8266/scripts/ntptime: Allow to override NTP server.
This is not part of public API, variable name may change, or it can be
replaced with a function.
2016-05-30 19:16:05 +03:00
Paul Sokolovsky
480159ca8b extmod/vfs_fat: getcwd(): Use mp_obj_new_exception_arg1().
Copy-paste issue, with the original mistake in stmhal.
2016-05-29 20:04:53 +03:00
Paul Sokolovsky
2503b59592 stmhal/moduos: getcwd(): Use mp_obj_new_exception_arg1().
Argument types were converted, but old function call of
mp_obj_new_exception_msg_varg() remained.
2016-05-29 20:04:32 +03:00
Paul Sokolovsky
12401f337e esp8266/moduos: Add chdir() and getcwd() functions. 2016-05-29 19:44:24 +03:00
Paul Sokolovsky
f0eea1fdf9 tests/extmod/vfs_fat_ramdisk: Add testcases for chdir(), getcwd(). 2016-05-29 18:54:14 +03:00
Paul Sokolovsky
ee5e3f6527 extmod/vfs_fat: chdir(), getcwd() methods should accept VFS object (self). 2016-05-29 18:52:41 +03:00
Paul Sokolovsky
cac6c9704e extmod/vfs_fat: Add getcwd() method.
Ported from stmhal.
2016-05-29 18:23:59 +03:00
Paul Sokolovsky
f12146cbf6 extmod/vfs_fat: Add chdir() method.
Ported from stmhal.
2016-05-29 18:17:00 +03:00
Damien George
602305b211 esp8266/uart: Properly initialise UART0 RXD pin in uart_config.
Tested and seems to work.  See #1995.
2016-05-29 10:30:27 +01:00
Damien George
6707fc94ae esp8266/modnetwork: Allow to press ctrl-C while scan() is running.
Ctrl-C will raise a KeyboardInterrupt and stop the scan (although it will
continue to run in the background, it won't report anything).  If
interrupted, and another scan() is started before the old one completes
in the background, then the second scan will fail with an OSError.
2016-05-29 09:53:04 +01:00
Damien George
84381fa0fc esp8266/modnetwork: Protect scan() callback against memory errors.
scan() allocates memory so may cause an exception to be raised.
2016-05-29 09:52:07 +01:00
Damien George
55df14f1a4 esp8266/modnetwork: scan() is only supported by STA when it's enabled. 2016-05-29 00:35:24 +01:00
Damien George
715ee9d925 py/modstruct: Allow to have "0s" in struct format. 2016-05-28 23:27:38 +01:00
Paul Sokolovsky
282d81a40e README: "quick build": Use "make axtls" after all.
"make deplibs" also builds libffi, and that requires GNU autotools. As
we use host libffi by default, skip requiring users to build it for now.
2016-05-28 21:08:09 +03:00
Paul Sokolovsky
4889b6ff9b unix/Makefile: "make axtls": Automatically fetch submodules if missing.
Try to emulate "you can build without reading instructions" behavior as far
as possible.
2016-05-28 21:03:48 +03:00
Paul Sokolovsky
e66b3042d6 README: Add "make deplibs" to quick build section. 2016-05-28 20:41:39 +03:00
Paul Sokolovsky
6055d411a9 unix/mpconfigport.mk: Document MICROPY_STANDALONE make-level option.
Avoid using system libraries, use copies bundled with MicroPython as
submodules (currently affects only libffi, other dependencies either
already used as bundled-only (axtls), or can't be bundled (so far),
like libjni).
2016-05-28 20:38:14 +03:00
Paul Sokolovsky
cbe544a76d tools: Upgrade upip to 0.7.
SSL certificate warning, switch to uerrno, and better usage message.
2016-05-28 02:57:53 +03:00
Paul Sokolovsky
2ec0ee082a py/moduerrno: Add ECONNREFUSED, one of frequent networking errors. 2016-05-28 00:17:19 +03:00
Robert HH
7c004e794c extmod/vfs_fat*: Replace text error messages by POSIX error numbers.
These changes are in line with similar changes in other modules, and
with standard Python interface.
2016-05-27 23:57:01 +03:00
Paul Sokolovsky
751e3b7a82 extmod/virtpin: Initial implementation of open-ended C-level Pin interface.
Using usual method of virtual method tables. Single virtual method,
ioctl, is defined currently for all operations. This universal and
extensible vtable-based method is also defined as a default MPHAL
GPIO implementation, but a specific port may override it with its
own implementation (e.g. close-ended, but very efficient, e.g. avoiding
virtual method dispatch).
2016-05-27 01:08:43 +03:00
Paul Sokolovsky
74e6c0337d esp8266/Makefile: Document "disable" value for UART_OS. 2016-05-27 00:44:05 +03:00
Damien George
7ebfe09fbd esp8266: Add dht.py script for high-level control of DHT11/DHT22 sensor.
TODO: should go in a more port-neutral place, like drivers/dht, but at the
moment in relies on specific esp module.
2016-05-26 17:13:03 +01:00
Damien George
45f3416816 esp8266: Enable DHT C-level driver.
Exposed as esp.dht_readinto.  Probably should go somewhere less
port-specific.
2016-05-26 17:11:43 +01:00
Damien George
48a7ef0576 drivers: Add C-level function to read DHT11 and DHT22 devices.
Uses mp_hal_pin API.
2016-05-26 17:10:06 +01:00
Damien George
4b37e775ea extmod/machine_i2c: Redo mp_hal_pin macros to use open_drain and od_low.
mp_hal_pin_config_od is renamed mp_hal_pin_open_drain, and mp_hal_pin_low
is mp_hal_pin_od_low.
2016-05-26 17:06:40 +01:00
Damien George
a3dc2c6031 docs/machine: Make disable_irq and enable_irq docs available for all. 2016-05-26 15:47:47 +01:00
Damien George
9a368ae831 esp8266/modmachine: Add disable_irq and enable_irq functions. 2016-05-26 15:47:47 +01:00
Damien George
849eb835f0 esp8266/ets_alt_task: Don't run ets_loop_iter if irqs are disabled.
ets_loop_iter processes pending tasks, and tasks are considered lower
priority than interrupts, so tasks shouldn't be processed if interrupts
are disabled.
2016-05-26 15:47:47 +01:00
Damien George
99b14593a6 esp8266/xtirq: Add xtirq.h for controlling xtensa irqs. 2016-05-26 15:47:47 +01:00
Damien George
7e809b4baf esp8266/modpybspi: Configure pins when initialising an SPI object. 2016-05-26 15:42:44 +01:00
Damien George
68e222afdc esp8266: Add mp_hal_pin_input() and mp_hal_pin_output() functions. 2016-05-26 15:42:27 +01:00
Paul Sokolovsky
20aa9c8511 .travis.yml: Install gcc-arm-none-eabi with --force-yes for now.
There appears to be issue signature problem with the PPA package we use,
so workaround it this way for now. Warning: with broken signature, there's
always a possibility that PPA was hacked and ships trojaned binaries.
2016-05-26 13:06:22 +03:00
Paul Sokolovsky
f5d63bcd23 unix: Enable "ussl" module.
ussl was in testing mode for 8 months, and now enabled in other ports
(e.g. esp8266), so time for unix port to catch up.
2016-05-26 02:12:11 +03:00
Paul Sokolovsky
2ea019f3d3 extmod/modussl: Coverage build fixes. 2016-05-26 02:11:24 +03:00
Paul Sokolovsky
37f9761801 unix/Makefile: nanbox build is not compatible with modussl, disable. 2016-05-26 02:11:17 +03:00
Paul Sokolovsky
9d04fec5d9 extmod/modussl: Make more compatible with non-default obj representations.
Still not compatible with nanboxing.
2016-05-26 02:10:35 +03:00
Paul Sokolovsky
c76acd8c23 py/moduerrno: Add EEXIST, EISDIR.
Useful to check file/dir operations result, in particular used by upip.
2016-05-25 01:23:57 +03:00
Paul Sokolovsky
2b05b60bbc esp8266/esp_mphal: mp_uos_dupterm_deactivate() may raise exception.
So, keep call to it protected via NLR still.
2016-05-24 15:04:59 +03:00
Paul Sokolovsky
4681b86850 esp8266/esp_mphal: Handle Ctrl+C from dupterm (e.g. WebREPL). 2016-05-24 01:37:56 +03:00
Paul Sokolovsky
116eeee6db esp8266/esp_mphal: Fix NLR buffer leak in call_dupterm_read(). 2016-05-24 01:30:28 +03:00
Paul Sokolovsky
bc2ba6b2e3 esp8266/scripts/port_diag: Dump network interface IP settings. 2016-05-24 01:27:16 +03:00
mad474
eaecc4c02e docs/esp8266/general: Grammar fixes. 2016-05-23 23:33:23 +03:00
Antonin ENFRUN
ca41dc2750 py/objnamedtuple: Allow passing field names as a tuple.
So the documentation's example works.  Besides, a tuple can be more
memory efficient.
2016-05-23 21:08:07 +01:00
Damien George
2133924e46 unix: Support frozen packages.
To use, put your directory structure with .py files in frozen/ and then:

    make FROZEN_MPY_DIR=frozen
2016-05-23 15:19:53 +01:00
Damien George
202d5acd06 py/makeqstrdata.py: Allow to have double-quote characters in qstrs.
When rendering the qstr for a C header file, the double-quate character
must be escaped.
2016-05-23 15:18:55 +01:00
Damien George
3e03d1b87e stmhal: Support frozen packages using .mpy files.
See issue #1814.
2016-05-23 13:29:56 +01:00
Damien George
25a42fb6ef tools/mpy-tool.py: Don't strip directories from the frozen source name.
Directories are now supported by the frozen import system (to implement
frozen packages) so we should keep them.
2016-05-23 13:29:03 +01:00
Damien George
74fb4e795b mpy-cross: Add -s option to specify the embedded source filename.
.mpy files contain the name of the source file that they were compiled
from.  This patch adds a way to change this name to an arbitrary string,
specified on the command line with the -s option.  The default is to use
the full name of the input filename.

This new -s option is useful to strip off a leading directory name so
that mpy-tool.py can freeze packages.
2016-05-23 13:25:54 +01:00
Damien George
9b4c013823 tools/mpy-tool.py: Include .py extension in frozen filename.
So that it can be correctly stat'd when looking for frozen files.
2016-05-23 12:46:02 +01:00
Damien George
274952a117 py: Allow to stat and import frozen mpy files using new frozen "VFS".
Freezing mpy files using mpy-tool.py now works again.
2016-05-23 12:42:23 +01:00
Paul Sokolovsky
3e33aeb0db docs: esp8266: Include ussl module in the docs. 2016-05-22 23:57:26 +03:00
Paul Sokolovsky
bca4c9e465 docs/ussl: Add basic description of axTLS-based modussl.
In particular, disclose the fact that server certificates are not
validated.
2016-05-22 23:56:22 +03:00
Paul Sokolovsky
cb7693bab4 esp8266/main: Update _boot module loading for recent frozen modules refactors. 2016-05-22 04:09:15 +03:00
Paul Sokolovsky
9c2217a165 esp8266: Enable collections.OrderedDict. 2016-05-22 02:57:33 +03:00
Paul Sokolovsky
9dde6062cc py/objstr: Fix mix-signed comparison in str.center(). 2016-05-22 02:22:14 +03:00
Dave Hylands
6a60fb3cf4 py/objstr*: Properly ifdef str.center(). 2016-05-22 01:54:41 +03:00
Paul Sokolovsky
53bac8e869 tests: Add testcase for str.center(). 2016-05-22 00:18:53 +03:00
Paul Sokolovsky
1b5abfcaae py/objstr: Implement str.center().
Disabled by default, enabled in unix port. Need for this method easily
pops up when working with text UI/reporting, and coding workalike
manually again and again counter-productive.
2016-05-22 00:13:44 +03:00
Paul Sokolovsky
2c573f00b8 py/builtinimport: Unbreak bare-arm build. 2016-05-21 22:37:58 +03:00
Paul Sokolovsky
8a2970e136 py/builtinimport: Unbreak minimal build.
These are workarounds required until frozen .mpy loading following standard
frozen modules code path.
2016-05-21 22:23:08 +03:00
Paul Sokolovsky
daa4793578 tools/make-frozen: Update for latest changes in frozen modules support.
Frozen modules are now stored with extensions and with '/' as path
separator. In other words, frozen modules paths stored as they are
in normal filesystem.
2016-05-21 21:39:27 +03:00
Paul Sokolovsky
fb742cdc12 py/{builtinimport,frozenmod}: Rework frozen modules support to support packages.
Now frozen modules is treated just as a kind of VFS, and all operations
performed on it correspond to operations on normal filesystem. This allows
to support packages properly, and potentially also data files.

This change also have changes to rework frozen bytecode modules support to
use the same framework, but it's not finished (and actually may not work,
as older adhox handling of any type of frozen modules is removed).
2016-05-21 21:38:50 +03:00
Paul Sokolovsky
b580958216 unix/unix_mphal: Implement mp_hal_ticks_us().
Similar to existing mp_hal_ticks_ms().
2016-05-21 02:16:35 +03:00
Paul Sokolovsky
5a2a4e9452 py/mphal.h: Provide default prototypes for mp_hal_delay_us/mp_hal_ticks_us.
Similar to existing mp_hal_delay_ms/mp_hal_ticks_ms.
2016-05-21 02:13:50 +03:00
Paul Sokolovsky
0ab372585f extmod/moduos_dupterm: Dumpterm subsystem is responsible for closing stream.
Make dupterm subsystem close a term stream object when EOF or error occurs.
There's no other party than dupterm itself in a better position to do this,
and this is required to properly reclaim stream resources, especially if
multiple dupterm sessions may be established (e.g. as networking
connections).
2016-05-20 22:20:37 +03:00
Paul Sokolovsky
3a29db8e58 extmod/modwebrepl: Add close() method. 2016-05-20 21:32:41 +03:00
Paul Sokolovsky
ccf4e5ab7b extmod/modwebsocket: Add close() method. 2016-05-20 21:18:49 +03:00
Paul Sokolovsky
497660fcda py/stream: Add mp_stream_close() helper function. 2016-05-20 21:18:49 +03:00
Damien George
f9dc644017 extmod: When including extmod headers, prefix path with extmod/. 2016-05-20 12:46:20 +01:00
Damien George
3ff16ff52e py: Declare constant data as properly constant.
Otherwise some compilers (eg without optimisation) will put this read-only
data in RAM instead of ROM.
2016-05-20 12:46:20 +01:00
misterdanb
a0a08b4be1 esp8266: Add APA102 serial individually controllable LEDs support.
APA102 is a new "smart LED", similar to WS2812 aka "Neopixel".
2016-05-19 22:29:11 +03:00
Torwag
6fa60153ea esp8266/README: Add a very first start section.
Adding a very first start section to get people going after flashing.
I tried to condense it to  a minimum to avoid as much as possible
redundancy and bloating.
2016-05-19 21:10:35 +03:00
Paul Sokolovsky
7f7c84b10a py/stream: Support both "exact size" and "one underlying call" operations.
Both read and write operations support variants where either a) a single
call is made to the undelying stream implementation and returned buffer
length may be less than requested, or b) calls are repeated until requested
amount of data is collected, shorter amount is returned only in case of
EOF or error.

These operations are available from the level of C support functions to be
used by other C modules to implementations of Python methods to be used in
user-facing objects.

The rationale of these changes is to allow to write concise and robust
code to work with *blocking* streams of types prone to short reads, like
serial interfaces and sockets. Particular object types may select "exact"
vs "once" types of methods depending on their needs. E.g., for sockets,
revc() and send() methods continue to be "once", while read() and write()
thus converted to "exactly" versions.

These changes don't affect non-blocking handling, e.g. trying "exact"
method on the non-blocking socket will return as much data as available
without blocking. No data available is continued to be signaled as None
return value to read() and write().

From the point of view of CPython compatibility, this model is a cross
between its io.RawIOBase and io.BufferedIOBase abstract classes. For
blocking streams, it works as io.BufferedIOBase model (guaranteeing
lack of short reads/writes), while for non-blocking - as io.RawIOBase,
returning None in case of lack of data (instead of raising expensive
exception, as required by io.BufferedIOBase). Such a cross-behavior
should be optimal for MicroPython needs.
2016-05-18 02:41:45 +03:00
Paul Sokolovsky
92a342a011 unix/mpconfigport_coverage.h: Add dedicated config file for coverage build.
This allows to enable the options which aren't enabled in the normal unix
config (as unix port is no longer an enable-all port).
2016-05-18 00:58:32 +03:00
Paul Sokolovsky
418faae8f7 esp8266/scripts/webrepl_setup: Add max password length check.
modwebrepl truncates password to 9 chars, and that led people to confusion.
2016-05-17 02:21:45 +03:00
Damien George
1e024de7be unix: Add ability to include frozen bytecode in the build.
To use frozen bytecode make a subdirectory under the unix/ directory
(eg frozen/), put .py files there, then run:

    make FROZEN_MPY_DIR=frozen

Be sure to build from scratch.  The .py files will then be available for
importing.
2016-05-16 23:17:11 +01:00
Damien George
99b4719357 tools/mpy-tool.py: Add checks for critical configuration vars.
When an mpy file is frozen it must know the values of certain
configuration variables.  This patch provides an explicit check in the
generated C file that the configuration variables are what they are
supposed to be.
2016-05-16 23:13:30 +01:00
Paul Sokolovsky
21ec1fd850 esp8266/scripts/webrepl_setup: Show password placeholder char.
That was the intent for the initial user setup, but didn't work before
due to lwIP issues. Enable now that they're fixed.
2016-05-17 00:01:41 +03:00
Paul Sokolovsky
7327d5f6f7 esp8266/scripts/port_diag: Add network diagnostic output. 2016-05-16 23:52:58 +03:00
Robert HH
a676a41cb7 esp8266/moduos.c: Addition of the rename method to module uos.
That one was missing in the module, even if it was available in the
vfs object. The change consist of adding the name and preparing the
call to the underlying vfs module, similar to what was already
implemented e.g. for remove.

Rename is useful by itself, or for instance for a safe file replace,
consisting of the sequence:

    write to a temp file
    delete the original file
    rename the temp file to the original file's name
2016-05-16 13:19:13 +02:00
Paul Sokolovsky
afce978aca extmod/modlwip: Rework how Python accept callback is called.
Calling it from lwIP accept callback will lead incorrect functioning
and/or packet leaks if Python callback has any networking calls, due
to lwIP non-reentrancy. So, instead schedule "poll" callback to do
that, which will be called by lwIP when it does not perform networking
activities. "Poll" callback is called infrequently though (docs say
every 0.5s by default), so for better performance, lwIP needs to be
patched to call poll callback soon after accept callback, but when
current packet is already processed.
2016-05-15 22:42:12 +03:00
Paul Sokolovsky
ca63c77073 docs/ustruct: Describe supported type codes. 2016-05-14 20:48:43 +03:00
Paul Sokolovsky
7b1bf0c308 tools/make-frozen.py: Quick fix to support package-modules.
It allows to "import foo.bar", but not "from foo import bar".
2016-05-14 16:30:02 +03:00
Paul Sokolovsky
719f8c044a tests/struct1: Add testcase for an unknown type char. 2016-05-14 15:54:09 +03:00
Paul Sokolovsky
e53fb1bf03 py/modstruct: Raise ValueError on unsupported format char. 2016-05-14 15:47:08 +03:00
Paul Sokolovsky
2ae6697300 py/objstringio: Add TODO comment about avoiding copying on .getvalue(). 2016-05-14 14:46:13 +03:00
Paul Sokolovsky
772c73fa16 README: Add explicit note that subdirs contain more READMEs. 2016-05-14 06:33:47 +03:00
Radomir Dopieralski
ccb00b7724 docs/esp8266/quickstart: remove i2c examples with stop=False
Since the ``stop`` parameter has been dropped.
2016-05-14 00:02:02 +02:00
Damien George
87981fc517 stmhal/sdcard: Allow to do unaligned read-from/write-to SD card.
For example, the following code now works with a file on the SD card:

    f = open('test', 'rb') # test must be 1024 bytes or more in size
    f.seek(511)
    f.read(513)

Also works for writing.

Fixes issue #1863.
2016-05-13 14:45:40 +01:00
Damien George
5985e41afc tools/make-frozen.py: Properly escape hex chars when making C strings. 2016-05-13 13:12:01 +01:00
Damien George
1e2f829293 tests/basics/string_splitlines: Reinstate feature test for splitlines. 2016-05-13 13:11:22 +01:00
Damien George
cc80c4dd59 py/objstr: Make dedicated splitlines function, supporting diff newlines.
It now supports \n, \r and \r\n as newline separators.

Adds 56 bytes to stmhal and 80 bytes to unix x86-64.

Fixes issue #1689.
2016-05-13 12:21:32 +01:00
Damien George
1e388079f9 stmhal/i2c: Expose I2CHandle3 for use by custom C code.
If custom C code uses the I2C busses then it needs access to these
structures for i2c_init().
2016-05-13 11:23:32 +01:00
Damien George
1dc2862a83 stmhal/led: Allow LEDs to be in PWM mode with TIM1 and channels 1-4.
This allows PYBv3 to use PWM for LED(1) and LED(2).
2016-05-13 11:01:21 +01:00
Paul Sokolovsky
68a7a92cec py/gc: gc_dump_alloc_table(): Dump heap offset instead of actual address.
Address printed was truncated anyway and in general confusing to outsider.
A line which dumps it is still left in the source, commented, for peculiar
cases when it may be needed (e.g. when running under debugger).
2016-05-13 00:16:38 +03:00
Paul Sokolovsky
9a8751b006 gc: gc_dump_alloc_table(): Use '=' char for tail blocks.
'=' is pretty natural character for tail, and gives less dense picture
where it's easier to see what object types are actually there.
2016-05-13 00:16:38 +03:00
Paul Sokolovsky
10503f3534 py/moduerrno: Add EACCES, pretty common error on Unix. 2016-05-13 00:15:38 +03:00
Damien George
9a92499641 py/objexcept: Don't convert errno to str in constructor, do it in print.
OSError's are now printed like:

    OSError: [Errno 1] EPERM

but only if the string corresponding to the errno is found.
2016-05-12 14:27:52 +01:00
Paul Sokolovsky
a314b842bb py/emitglue: Fix build on AArch64 (ARMv8, etc.) related to loading .mpy files.
Actual loading of .mpy files isn't tested.
2016-05-12 16:00:57 +03:00
Colin Hogben
a896951a9a py/objfloat, py/modmath: Ensure M_PI and M_E defined.
In some compliation enviroments (e.g. mbed online compiler) with
strict standards compliance, <math.h> does not define constants such
as M_PI.  Provide fallback definitions of M_E and M_PI where needed.
2016-05-12 13:28:45 +01:00
Damien George
d45e5f8c35 py: Add mp_errno_to_str() and use it to provide nicer OSError msgs.
If an OSError is raised with an integer argument, and that integer
corresponds to an errno, then the string for the errno is used as the
argument to the exception, instead of the integer.  Only works if
the uerrno module is enabled.
2016-05-12 13:20:40 +01:00
Damien George
47bf6ba61a py/moduerrno: Add more constants to the errno module. 2016-05-12 13:18:48 +01:00
Damien George
0d6d315ba6 esp8266: Change to use internal errno's. 2016-05-12 12:49:36 +01:00
Damien George
0055457b5f extmod/modlwip: Convert errno's to use MP_Exxx symbols. 2016-05-12 12:49:14 +01:00
Damien George
c9a7430dbe py/mperrno: Add some more MP_Exxx constants, related to networking. 2016-05-12 12:48:47 +01:00
Paul Sokolovsky
bc04dc277e py/gc: Make (byte)array type dumping conditional on these types being enabled. 2016-05-11 19:21:53 +03:00
Paul Sokolovsky
3d7f3f00e0 py/gc: gc_dump_alloc_table(): Show byte/str and (byte)array objects.
These are typical consumers of large chunks of memory, so it's useful to
see at least their number (how much memory isn't clearly shown, as the data
for these objects is allocated elsewhere).
2016-05-11 19:00:15 +03:00
Damien George
80a8d473f6 py/repl: Fix handling of backslash in quotes when checking continuation. 2016-05-11 16:05:22 +01:00
Damien George
9b4502b7e8 docs/esp8266/tutorial: Fix typo in do_connect() network example.
Fixes issue #2065.
2016-05-11 13:40:28 +01:00
Damien George
ce2d34d74f drivers/cc3000: Rename timeval to cc3000_timeval, to avoid clash.
The timeval struct can be defined by system C headers.
2016-05-10 23:46:00 +01:00
Damien George
79a38a7a43 stmhal: For network drivers, convert to use MP_Exxx errno symbols. 2016-05-10 23:45:33 +01:00
Damien George
83a9a723b9 py/mperrno: Add EAFNOSUPPORT definition. 2016-05-10 23:44:59 +01:00
Damien George
7e1f580910 esp8266: Enable uerrno module, weak linked also as errno. 2016-05-10 23:30:39 +01:00
Damien George
4f2ba9fbdc esp8266: Convert to use new MP_Exxx errno symbols.
These symbols are still defined in terms of the system Exxx symbols, and
can be switched to internal numeric definitions at a later stage.

Note that extmod/modlwip still uses many system Exxx symbols.
2016-05-10 23:30:39 +01:00
Damien George
5ab98d5c41 stmhal: Convert to use internal errno symbols; enable uerrno module. 2016-05-10 23:30:39 +01:00
Damien George
088127d91c unix: Enable uerrno module. 2016-05-10 23:30:39 +01:00
Damien George
e36ff98c80 py/parse: Add uerrno to list of modules to look for constants in. 2016-05-10 23:30:39 +01:00
Damien George
596a3feb8f py: Add uerrno module, with errno constants and dict. 2016-05-10 23:30:39 +01:00
Damien George
3f56fd64b8 py: Add mperrno.h file with uPy defined errno constants. 2016-05-10 23:30:39 +01:00
Paul Sokolovsky
d60cb8e180 esp8266/help: Add "sta_if.active(True)" command.
As reported on the forum by Roberthh.
2016-05-10 23:21:32 +03:00
Paul Sokolovsky
f16bec6bc9 esp8266/mpconfigport: Reduce various parser-related allocation params.
This gives noticeable result for parsing simple input (modelled on 32-bit
unix port):

Before:
>>> micropython.mem_total()
3360
>>> micropython.mem_total()
4472

After:
>>> micropython.mem_total()
3072
>>> micropython.mem_total()
4052

However, effect on parsing large input is much less conclusive, e.g.:

Before:
>>> micropython.mem_total()
3376
>>> import pystone_lowmem
>>> micropython.mem_total()
33006

delta=29630

After:
>>> micropython.mem_total()
3091
>>> import pystone_lowmem
>>> micropython.mem_total()
32509

delta=29418
2016-05-10 15:38:31 +03:00
Tobias Badertscher
b924f649cd stmhal: Fix clock configuration for STM32L476-discovery; also add I2C2. 2016-05-10 09:20:30 +01:00
Radomir Dopieralski
e89413e9b0 docs/esp8266/quickref: New way to get MAC address 2016-05-10 00:31:57 +02:00
Paul Sokolovsky
6f34e138f1 py/vstr: Change allocation policy, +16 to requested size, instead of *2.
Effect measured on esp8266 port:

Before:
>>> pystone_lowmem.main(10000)
Pystone(1.2) time for 10000 passes = 44214 ms
This machine benchmarks at 226 pystones/second
>>> pystone_lowmem.main(10000)
Pystone(1.2) time for 10000 passes = 44246 ms
This machine benchmarks at 226 pystones/second

After:
>>> pystone_lowmem.main(10000)
Pystone(1.2) time for 10000 passes = 44343ms
This machine benchmarks at 225 pystones/second
>>> pystone_lowmem.main(10000)
Pystone(1.2) time for 10000 passes = 44376ms
This machine benchmarks at 225 pystones/second
2016-05-10 00:56:51 +03:00
Paul Sokolovsky
40f0096ee7 Revert "py/objstr: .format(): Avoid call to vstr_null_terminated_str()."
This reverts commit 6de8dbb488. The change
was incorrect (correct change would require comparing with end pointer in
each if statement in the block).
2016-05-09 23:42:42 +03:00
Paul Sokolovsky
a1f2245a81 py/vstr: vstr_null_terminated_str(): Extend string by at most one byte.
vstr_null_terminated_str is almost certainly a vstr finalization operation,
so it should add the requested NUL byte, and not try to pre-allocate more.
The previous implementation could actually allocate double of the buffer
size.
2016-05-09 22:39:57 +03:00
Paul Sokolovsky
6de8dbb488 py/objstr: .format(): Avoid call to vstr_null_terminated_str().
By comparing with string end pointer instead of checking for NUL byte.
Should alleviate reallocations and fragmentation a tiny bit.
2016-05-09 21:55:09 +03:00
Damien George
460b086333 py/mpz: Fix mpn_div so that it doesn't modify memory of denominator.
Previous to this patch bignum division and modulo would temporarily
modify the RHS argument to the operation (eg x/y would modify y), but on
return the RHS would be restored to its original value.  This is not
allowed because arguments to binary operations are const, and in
particular might live in ROM.  The modification was to normalise the arg
(and then unnormalise before returning), and this patch makes it so the
normalisation is done on the fly and the arg is now accessed as read-only.

This change doesn't increase the order complexity of the operation, and
actually reduces code size.
2016-05-09 17:21:42 +01:00
Paul Sokolovsky
de5e0ed2e0 esp8266/main: Bump heap size to 28K.
This is kind of compensation for 4K FatFs buffer size which is eaten away
from it on FS mount. This should still leave enough of networking ("OS")
heap.
2016-05-09 19:02:40 +03:00
Damien George
65402ab1ec py/mpz: Do Python style division/modulo within bignum divmod routine.
This patch consolidates the Python logic for division/modulo to one place
within the bignum code.
2016-05-08 22:21:21 +01:00
Damien George
dc3faea040 py/mpz: Fix bug with overflowing C-shift in division routine.
When DIG_SIZE=32, a uint32_t is used to store limbs, and no normalisation
is needed because the MSB is already set, then there will be left and
right shifts (in C) by 32 of a 32-bit variable, leading to undefined
behaviour.  This patch fixes this bug.
2016-05-08 21:38:43 +01:00
Paul Sokolovsky
d59c2e5e45 py/repl: If there're no better alternatives, try to complete "import".
Also do that only for the first word in a line. The idea is that when you
start up interpreter, high chance that you want to do an import. With this
patch, this can be achieved with "i<tab>".
2016-05-08 20:40:47 +03:00
Paul Sokolovsky
13a1acc7e2 esp8266/scripts/webrepl: Add start_foreground() method.
Starts WebREPL server in foreground and waits for (single) connection.
2016-05-08 20:01:15 +03:00
Henrik Sölver
c4587e2426 stmhal/can: Allow to get existing CAN obj if constructed without args.
Initialisation of CAN objects should now behave as other peripheral
objects.

Fixes issue #2001.
2016-05-08 12:47:33 +01:00
stijn
87106d025b windows: Enable multi-processor compilation for msvc
This will launch about as many compiler instances as there are logical
processors on a machine, and as such significantly speeds up compilation.
2016-05-08 12:07:57 +02:00
Paulus Schoutsen
c156e89379 Fix ESP8266 Network tutorial
The socket should either connect to `addr` or `addr_info[0][-1]`. Not to `addr[0][-1]`.
2016-05-07 23:24:24 -07:00
Damien George
9e47c145c7 tests: Disable memoryview tests that overflow int conversion.
They fail on builds with 32-bit word size.
2016-05-07 22:36:49 +01:00
Damien George
470c429ee1 py/runtime: Properly handle passing user mappings to ** keyword args. 2016-05-07 22:02:46 +01:00
Damien George
12dd8df375 py/objstr: Binary type of str/bytes for buffer protocol is 'B'.
The type is an unsigned 8-bit value, since bytes objects are exactly
that.  And it's also sensible for unicode strings to return unsigned
values when accessed in a byte-wise manner (CPython does not allow this).
2016-05-07 21:18:17 +01:00
Noah Rosamilia
2724bd4a94 esp8266/scripts/webrepl: Add optional password argument to webrepl.start()
This commit fixes issue #2045
2016-05-07 22:45:08 +03:00
Paul Sokolovsky
cea1c621e0 CODECONVENTIONS.md: Describe git commit messages conventions. 2016-05-07 22:32:13 +03:00
Pavol Rusnak
bc7ca7ca01 unix/mphalport: Add mp_hal_delay_us() for consistency with other ports. 2016-05-07 21:18:44 +03:00
Mike Causer
13d06a83e1 esp8266/scripts/: Add fill() to NeoPixel 2016-05-07 21:15:33 +03:00
Radomir Dopieralski
0c86a9471a docs/machine.UART: Filter out unimplemented UART methods from esp8266 docs. 2016-05-07 20:20:04 +03:00
Paul Sokolovsky
8db61e5b5a esp8266/scripts/inisetup: Don't start WebREPL on boot in master branch.
It interferes with running testsuite. master branch should be optimized for
development, so any features which interfere with that, would need to be
disabled by default.
2016-05-07 20:04:45 +03:00
Paul Sokolovsky
5ec11f565b tests/run-tests: Factor out list supported external boards.
To get consistent error messages, etc.
2016-05-07 18:45:16 +03:00
Damien George
88153dc56a stmhal/sdcard: Fix initialisation of DMA TX so that writes work.
Addresses issue #2034.
2016-05-06 10:53:25 +01:00
Dave Hylands
cbbeb786d7 stmhal/dma: Fix builds for boards with an F4 or F7 but no DAC. 2016-05-06 09:57:33 +01:00
Paul Sokolovsky
df2b1a4758 esp8266/scripts/: Remove use of pin.PULL_NONE.
This constant is no longer part of hardware API (replaced with just None),
and is a default, so not needed in calls.
2016-05-05 23:47:37 +03:00
Damien George
08d3d5d9ab stmhal: For LIMIFROG board, add early-init function to get to DFU mode. 2016-05-05 17:00:30 +01:00
Tobias Badertscher
770f169e63 stmhal: Add board files for LIMIFROG board. 2016-05-05 17:00:16 +01:00
Damien George
05d1664981 stmhal/dma: Make DAC DMA descriptors conditional on having a DAC. 2016-05-05 15:34:01 +01:00
Tobias Badertscher
0f846e563c stmhal: L4: Add support for machine.sleep on STM32L4 MCUs.
Also raise an exception for machine.freq and machine.deepsleep on this
MCU, since they are not yet implemented.
2016-05-05 15:28:55 +01:00
Tobias Badertscher
7441ba7749 stmhal: L4: Make CCM/DTCM RAM start-up conditional on MCU type. 2016-05-05 15:19:33 +01:00
Tobias Badertscher
adaaf439b0 stmhal: L4: Adapt startup code, clock configuration and interrupts. 2016-05-05 15:14:42 +01:00
Tobias Badertscher
e64032d6fd stmhal: L4: Adapt DMA to be able to support STM32L4 MCU series.
The main thing is to change the DMA code in a way that the structure
DMA_Stream_TypeDef (which is similar to DMA_Channel_TypeDef on stm32l4)
is no longer used outside of dma.c, as this structure only exists for the
F4 series.  Therefore I introduced a new structure (dma_descr_t) which
handles all DMA specific stuff for configuration.  Further the periphery
(spi, i2c, sdcard, dac) does not need to know the internals of the dma.
2016-05-05 14:51:20 +01:00
Damien George
eb54e4d065 py/obj: Add warning note about get_array return value and GC blocks. 2016-05-04 10:19:08 +01:00
177 changed files with 4342 additions and 938 deletions

View File

@@ -12,7 +12,8 @@ before_script:
- sudo add-apt-repository -y ppa:terry.guo/gcc-arm-embedded
- sudo dpkg --add-architecture i386
- sudo apt-get update -qq || true
- sudo apt-get install -y python3 gcc-multilib gcc-arm-none-eabi pkg-config libffi-dev libffi-dev:i386 qemu-system mingw32
- sudo apt-get install -y python3 gcc-multilib pkg-config libffi-dev libffi-dev:i386 qemu-system mingw32
- sudo apt-get install -y --force-yes gcc-arm-none-eabi
# For teensy build
- sudo apt-get install realpath
# For coverage testing

View File

@@ -1,3 +1,31 @@
Git commit conventions
======================
Each commit message should start with a directory or full file path
prefix, so it was clear which part of codebase a commit affects. If
a change affects one file, it's better to use path to a file. If it
affects few files in a subdirectory, using subdirectory as a prefix
is ok. For longish paths, it's acceptable to drop intermediate
components, which still should provide good context of a change.
It's also ok to drop file extensions.
Besides prefix, first line of a commit message should describe a
change clearly and to the point, and be a grammatical sentence with
final full stop. First line should fit within 78 characters. Examples
of good first line of commit messages:
py/objstr: Add splitlines() method.
py: Rename FOO to BAR.
docs/machine: Fix typo in reset() description.
ports: Switch to use lib/foo instead of duplicated code.
After the first line, add an empty line and in following lines describe
a change in a detail, if needed. Any change beyond 5 lines would likely
require such detailed description.
To get good practical examples of good commits and their messages, browse
thry the `git log` of the project.
Python code conventions
=======================

View File

@@ -54,6 +54,8 @@ Additional components:
- tools/ -- various tools, including the pyboard.py module.
- examples/ -- a few example Python scripts.
The subdirectories above may include READMEs with additional info.
"make" is used to build the components, or "gmake" on BSD-based systems.
You will also need bash and Python (at least 2.7 or 3.3).
@@ -69,6 +71,7 @@ Alternatively, fallback implementation based on setjmp/longjmp can be used.
To build (see section below for required dependencies):
$ cd unix
$ make axtls
$ make
Then to give it a try:

View File

@@ -26,3 +26,15 @@ In `micropython/docs`, build the docs:
Where `<port_name>` can be `unix`, `pyboard`, `wipy` or `esp8266`.
You'll find the index page at `micropython/docs/build/<port_name>/html/index.html`.
PDF manual generation
---------------------
This can be achieved with:
make MICROPY_PORT=<port_name> latexpdf
but require rather complete install of LaTeX with various extensions. On
Debiab/Ubuntu, try (500MB+ download):
apt-get install texlive-latex-recommended texlive-latex-extra

View File

@@ -93,7 +93,7 @@ copyright = '2014-2016, Damien P. George and contributors'
# The short X.Y version.
version = '1.8'
# The full version, including alpha/beta/rc tags.
release = '1.8'
release = '1.8.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View File

@@ -6,8 +6,8 @@ ESP8266 is a popular WiFi-enabled System-on-Chip (SoC) by Espressif Systems.
Multitude of boards
-------------------
There are multitude of modules and boards from different sources which carry
ESP8266 chip. MicroPython tries to provide a generic port which would run on
There are a multitude of modules and boards from different sources which carry
the ESP8266 chip. MicroPython tries to provide a generic port which would run on
as many boards/modules as possible, but there may be limitations. Adafruit
Feather HUZZAH board is taken as a reference board for the port (for example,
testing is performed on it). If you have another board, please make sure you
@@ -18,13 +18,13 @@ To make a generic ESP8266 port and support as many boards as possible,
following design and implementation decision were made:
* GPIO pin numbering is based on ESP8266 chip numbering, not some "logical"
numbering of a particular board. Please have manual/pin diagram of your board
handy to find correspondce between your board pins and actual ESP8266 pins.
numbering of a particular board. Please have the manual/pin diagram of your board
at hand to find correspondence between your board pins and actual ESP8266 pins.
We also encourage users of various boards to share this mapping via MicroPython
forum, with the idea to collect community-maintained reference materials
eventually.
* All pins which make sense to support, are supported by MicroPython
(for example, we don't expose pins which are used to connect SPI flash
(for example, pins which are used to connect SPI flash
are not exposed, as they're unlikely useful for anything else, and
operating on them will lead to board lock-up). However, any particular
board may expose only subset of pins. Consult your board reference manual.
@@ -37,10 +37,10 @@ Technical specifications and SoC datasheets
The datasheets and other reference material for ESP8266 chip are available
from the vendor site: http://bbs.espressif.com/viewtopic.php?f=67&t=225 .
The are primary reference for the chip technical specifications, capabilities,
They are the primary reference for the chip technical specifications, capabilities,
operating modes, internal functioning, etc.
For your convinience, some of technical specifications are provided below:
For your convenience, some of technical specifications are provided below:
* Architecture: Xtensa lx106
* CPU frequency: 80MHz overclockable to 160MHz
@@ -64,18 +64,18 @@ Boot process
On boot, MicroPython EPS8266 port executes ``_boot.py`` script from internal
frozen modules. It mounts filesystem in FlashROM, or if it's not available,
performs first-time setup of the module and creates the filesystem. This
part of boot process is considered fixed, and not available for customization
part of the boot process is considered fixed, and not available for customization
for end users (even if you build from source, please refrain from changes to
it; customization of early boot process is available only to advanced users
and developers, who can diagnose themselves any issues arising from
modifying the standard process).
Once filesystem is mounted, ``boot.py`` is executed from it. The standard
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
defaults starts up a WebREPL daemon to handle incoming connections. This
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
module start-up). But keep in mind that incorrect modifications to boot.py
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.
@@ -89,5 +89,14 @@ the following in ``main.py``::
import my_app
my_app.main()
This will allow to keep structure of your application clear, as well as
This will allow to keep the structure of your application clear, as well as
allow to install multiple applications on a board, and switch among them.
Real-time clock
---------------
Due to limitations of the ESP8266 chip the internal real-time clock (RTC)
will overflow every 7:45h. If a long-term working RTC time is required then
``time()`` or ``localtime()`` must be called at least once within 7 hours.
MicroPython will then handle the overflow.

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View File

@@ -3,7 +3,7 @@
Quick reference for the ESP8266
===============================
.. image:: https://learn.adafruit.com/system/assets/assets/000/028/689/medium640/adafruit_products_pinoutstop.jpg
.. image:: img/adafruit_products_pinoutstop.jpg
:alt: Adafruit Feather HUZZAH board
:width: 640px
@@ -43,7 +43,7 @@ The ``network`` module::
wlan.scan() # scan for access points
wlan.isconnected() # check if the station is connected to an AP
wlan.connect('essid', 'password') # connect to an AP
wlan.mac() # get the interface's MAC adddress
wlan.config('mac') # get the interface's MAC adddress
wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses
ap = network.WLAN(network.AP_IF) # create access-point interface
@@ -199,9 +199,6 @@ The I2C driver is implemented in software and works on all pins::
buf = bytearray(10) # create a buffer with 10 bytes
i2c.writeto(0x3a, buf) # write the given buffer to the slave
i2c.readfrom(0x3a, 4, stop=False) # don't send a stop bit after reading
i2c.writeto(0x3a, buf, stop=False) # don't send a stop bit after writing
Deep-sleep mode
---------------
@@ -274,31 +271,55 @@ For low-level driving of a NeoPixel::
import esp
esp.neopixel_write(pin, grb_buf, is800khz)
APA102 driver
-------------
Use the ``apa102`` module::
from machine import Pin
from apa102 import APA102
clock = Pin(14, Pin.OUT) # set GPIO14 to output to drive the clock
data = Pin(13, Pin.OUT) # set GPIO13 to output to drive the data
apa = APA102(clock, data, 8) # create APA102 driver on the clock and the data pin for 8 pixels
apa[0] = (255, 255, 255, 31) # set the first pixel to white with a maximum brightness of 31
apa.write() # write data to all pixels
r, g, b, brightness = apa[0] # get first pixel colour
For low-level driving of an APA102::
import esp
esp.apa102_write(clock_pin, data_pin, rgbi_buf)
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 , and start daemon using::
from https://github.com/micropython/webrepl (hosted version available
at http://micropython.org/webrepl), and start the daemon on a device
using::
import webrepl
webrepl.start()
(Release version will have it started on boot by default.)
(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
routers is set up and works correctly, you may also use it while connecting
to your normal Internet access point (use ESP8266 AP connection method if
face any issues).
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. There's also provision to transfer (both upload and download)
files over WebREPL connection, but it has unstable status (be ready to
reboot a module in case of issues). It still may be a practical way to
issues.
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 forum for other community-supported
alternatives to transfer files to ESP8266.
from the repository above. See the MicroPython forum for other
community-supported alternatives to transfer files to ESP8266.

View File

@@ -62,7 +62,7 @@ connect to your WiFi network::
print('connecting to network...')
sta_if.active(True)
sta_if.connect('<essid>', '<password>')
while not network.isconnected():
while not sta_if.isconnected():
pass
print('network config:', sta_if.ifconfig())

View File

@@ -36,7 +36,7 @@ information they hold.
Using the IP address we can make a socket and connect to the server::
>>> s = socket.socket()
>>> s.connect(addr[0][-1])
>>> s.connect(addr)
Now that we are connected we can download and display the data::

View File

@@ -4,9 +4,12 @@
.. module:: cmath
:synopsis: mathematical functions for complex numbers
The ``cmath`` module provides some basic mathematical funtions for
The ``cmath`` module provides some basic mathematical functions for
working with complex numbers.
Availability: not available on WiPy and ESP8266. Floating point support
required for this module.
Functions
---------

View File

@@ -1,9 +1,33 @@
MicroPython libraries
=====================
The following standard Python libraries are built in to MicroPython.
This chapter describes modules (function and class libraries) which are built
into MicroPython. There are a few categories of modules:
For additional libraries, please download them from the `micropython-lib repository
* Modules which implement a subset of standard Python functionality and are not
intended to be extended by the user.
* Modules which implement a subset of Python functionality, with a provision
for extension by the user (via Python code).
* Modules which implement MicroPython extensions to the Python standard libraries.
* Modules specific to a particular port and thus not portable.
Note about the availability of modules and their contents: This documentation
in general aspires to describe all modules and functions/classes which are
implemented in MicroPython. However, MicroPython is highly configurable, and
each port to a particular board/embedded system makes available only a subset
of MicroPython libraries. For officially supported ports, there is an effort
to either filter out non-applicable items, or mark individual descriptions
with "Availability:" clauses describing which ports provide a given feature.
With that in mind, please still be warned that some functions/classes
in a module (or even the entire module) described in this documentation may be
unavailable in a particular build of MicroPython on a particular board. The
best place to find general information of the availability/non-availability
of a particular feature is the "General Information" section which contains
information pertaining to a specific port.
Beyond the built-in libraries described in this documentation, many more
modules from the Python standard library, as well as further MicroPython
extensions to it, can be found in the `micropython-lib repository
<https://github.com/micropython/micropython-lib>`_.
Python standard libraries and micro-libraries
@@ -101,6 +125,7 @@ library.
uos.rst
ure.rst
usocket.rst
ussl.rst
ustruct.rst
utime.rst
uzlib.rst

View File

@@ -86,13 +86,15 @@ Methods
When no pins are given, then the default set of TX and RX pins is taken, and hardware
flow control will be disabled. If pins=None, no pin assignment will be made.
.. method:: uart.deinit()
.. only:: not port_esp8266
Turn off the UART bus.
.. method:: uart.deinit()
.. method:: uart.any()
Turn off the UART bus.
Return the number of characters available for reading.
.. method:: uart.any()
Return the number of characters available for reading.
.. method:: uart.read([nbytes])
@@ -127,11 +129,13 @@ Methods
Return value: number of bytes written or ``None`` on timeout.
.. method:: uart.sendbreak()
.. only:: not port_esp8266
Send a break condition on the bus. This drives the bus low for a duration
of 13 bits.
Return value: ``None``.
.. method:: uart.sendbreak()
Send a break condition on the bus. This drives the bus low for a duration
of 13 bits.
Return value: ``None``.
.. only:: port_wipy
@@ -158,14 +162,16 @@ Methods
Returns an irq object.
Constants
---------
.. only:: not port_esp8266
.. data:: UART.EVEN
.. data:: UART.ODD
Constants
---------
parity types (anlong with ``None``)
.. data:: UART.EVEN
.. data:: UART.ODD
.. data:: UART.RX_ANY
parity types (anlong with ``None``)
IRQ trigger sources
.. data:: UART.RX_ANY
IRQ trigger sources

View File

@@ -18,25 +18,23 @@ Reset related functions
Get the reset cause. See :ref:`constants <machine_constants>` for the possible return values.
.. only:: port_wipy
Interrupt related functions
---------------------------
Interrupt related functions
---------------------------
.. function:: disable_irq()
.. function:: disable_irq()
Disable interrupt requests.
Returns the previous IRQ state: ``False``/``True`` for disabled/enabled IRQs
respectively. This return value can be passed to enable_irq to restore
the IRQ to its original state.
Disable interrupt requests.
Returns the previous IRQ state: ``False``/``True`` for disabled/enabled IRQs
respectively. This return value can be passed to enable_irq to restore
the IRQ to its original state.
.. function:: enable_irq(state=True)
.. function:: enable_irq(state=True)
Enable interrupt requests.
If ``state`` is ``True`` (the default value) then IRQs are enabled.
If ``state`` is ``False`` then IRQs are disabled. The most common use of
this function is to pass it the value returned by ``disable_irq`` to
exit a critical section.
Enable interrupt requests.
If ``state`` is ``True`` (the default value) then IRQs are enabled.
If ``state`` is ``False`` then IRQs are disabled. The most common use of
this function is to pass it the value returned by ``disable_irq`` to
exit a critical section.
Power related functions
-----------------------
@@ -103,6 +101,19 @@ Miscellaneous functions
varies by hardware (so use substring of a full value if you expect a short
ID). In some MicroPython ports, ID corresponds to the network MAC address.
.. function:: time_pulse_us(pin, pulse_level, timeout_us=1000000)
Time a pulse on the given `pin`, and return the duration of the pulse in
microseconds. The `pulse_level` argument should be 0 to time a low pulse
or 1 to time a high pulse.
The function first waits while the pin input is different to the `pulse_level`
parameter, then times the duration that the pin is equal to `pulse_level`.
If the pin is already equal to `pulse_level` then timing starts straight away.
The function will raise an OSError with ETIMEDOUT if either of the waits is
longer than the given timeout value (which is in microseconds).
.. _machine_constants:
Constants

View File

@@ -4,11 +4,14 @@
.. module:: math
:synopsis: mathematical functions
The ``math`` module provides some basic mathematical funtions for
The ``math`` module provides some basic mathematical functions for
working with floating-point numbers.
*Note:* On the pyboard, floating-point numbers have 32-bit precision.
Availability: not available on WiPy. Floating point support required
for this module.
Functions
---------

View File

@@ -66,6 +66,10 @@ Methods
Reinitialise the DAC. ``bits`` can be 8 or 12.
.. method:: dac.deinit()
De-initialise the DAC making its pin available for other uses.
.. method:: dac.noise(freq)
Generate a pseudo-random noise signal. A new random sample is written

View File

@@ -8,56 +8,79 @@ This module provides access to Transport Layer Security (often known as
“Secure Sockets Layer”) encryption and peer authentication facilities for
network sockets, both client-side and server-side.
Functions
---------
.. only:: not port_wipy
.. function:: ssl.wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ca_certs=None)
Functions
---------
Takes an instance sock of socket.socket, and returns an instance of ssl.SSLSocket, a subtype of
``socket.socket``, which wraps the underlying socket in an SSL context. sock must be a ``SOCK_STREAM``
socket and protocol number ``socket.IPPROTO_SEC``; other socket types are unsupported. Example::
.. function:: ssl.wrap_socket(sock, server_side=False)
import socket
import ssl
s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
ss = ssl.wrap_socket(s)
ss.connect(socket.getaddrinfo('www.google.com', 443)[0][-1])
Takes a stream `sock` (usually usocket.socket instance of ``SOCK_STREAM`` type),
and returns an instance of ssl.SSLSocket, which wraps the underlying stream in
an SSL context. Returned object has the usual stream interface methods like
`read()`, `write()`, etc. In MicroPython, the returned object does not expose
socket interface and methods like `recv()`, `send()`. In particular, a
server-side SSL socket should be created from a normal socket returned from
`accept()` on a non-SSL listening server socket.
Certificates must be used in order to validate the other side of the connection, and also to
authenticate ourselves with the other end. Such certificates must be stored as files using the
FTP server, and they must be placed in specific paths with specific names.
.. warning::
- The certificate to validate the other side goes in: **'/flash/cert/ca.pem'**
- The certificate to authenticate ourselves goes in: **'/flash/cert/cert.pem'**
- The key for our own certificate goes in: **'/flash/cert/private.key'**
Currently, this function does NOT validate server certificates, which makes
an SSL connection established prone to man-in-the-middle attacks.
.. note::
When these files are stored, they are placed inside the internal **hidden** file system
(just like firmware updates), and therefore they are never visible.
.. only:: port_wipy
For instance to connect to the Blynk servers using certificates, take the file ``ca.pem`` located
in the `blynk examples folder <https://github.com/wipy/wipy/tree/master/examples/blynk>`_
and put it in '/flash/cert/'. Then do::
Functions
---------
import socket
import ssl
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
ss = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs='/flash/cert/ca.pem')
ss.connect(socket.getaddrinfo('cloud.blynk.cc', 8441)[0][-1])
.. function:: ssl.wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ca_certs=None)
SSL sockets inherit all methods and from the standard sockets, see the :mod:`usocket` module.
Takes an instance sock of socket.socket, and returns an instance of ssl.SSLSocket, a subtype of
``socket.socket``, which wraps the underlying socket in an SSL context. sock must be a ``SOCK_STREAM``
socket and protocol number ``socket.IPPROTO_SEC``; other socket types are unsupported. Example::
Exceptions
----------
import socket
import ssl
s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
ss = ssl.wrap_socket(s)
ss.connect(socket.getaddrinfo('www.google.com', 443)[0][-1])
.. data:: ssl.SSLError
Certificates must be used in order to validate the other side of the connection, and also to
authenticate ourselves with the other end. Such certificates must be stored as files using the
FTP server, and they must be placed in specific paths with specific names.
Constants
---------
- The certificate to validate the other side goes in: **'/flash/cert/ca.pem'**
- The certificate to authenticate ourselves goes in: **'/flash/cert/cert.pem'**
- The key for our own certificate goes in: **'/flash/cert/private.key'**
.. data:: ssl.CERT_NONE
.. data:: ssl.CERT_OPTIONAL
.. data:: ssl.CERT_REQUIRED
.. note::
supported values in ``cert_reqs``
When these files are stored, they are placed inside the internal **hidden** file system
(just like firmware updates), and therefore they are never visible.
For instance to connect to the Blynk servers using certificates, take the file ``ca.pem`` located
in the `blynk examples folder <https://github.com/wipy/wipy/tree/master/examples/blynk>`_
and put it in '/flash/cert/'. Then do::
import socket
import ssl
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
ss = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs='/flash/cert/ca.pem')
ss.connect(socket.getaddrinfo('cloud.blynk.cc', 8441)[0][-1])
SSL sockets inherit all methods and from the standard sockets, see the :mod:`usocket` module.
Exceptions
----------
.. data:: ssl.SSLError
Constants
---------
.. data:: ssl.CERT_NONE
.. data:: ssl.CERT_OPTIONAL
.. data:: ssl.CERT_REQUIRED
supported values in ``cert_reqs``

View File

@@ -7,6 +7,12 @@
See `Python struct <https://docs.python.org/3/library/struct.html>`_ for more
information.
Supported size/byte order prefixes: ``@``, ``<``, ``>``, ``!``.
Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``,
``L``, ``q``, ``Q``, ``s``, ``P``, ``f``, ``d`` (the latter 2 depending
on the floating-point support).
Functions
---------

View File

@@ -52,7 +52,12 @@ or::
$ screen /dev/tty.usbmodem* 115200
When you are finished and want to exit screen, type CTRL-A CTRL-\\.
When you are finished and want to exit ``screen``, type CTRL-A CTRL-\\. If your keyboard does not have a \\-key (i.e. you need an obscure combination for \\ like ALT-SHIFT-7) you can remap the ``quit`` command:
- create ``~/.screenrc``
- add ``bind q quit``
This will allow you to quit ``screen`` by hitting CTRL-A Q.
Linux
-----

View File

@@ -169,9 +169,9 @@ typedef INT32 time_t;
typedef UINT32 clock_t;
typedef INT32 suseconds_t;
typedef struct timeval timeval;
typedef struct cc3000_timeval cc3000_timeval;
struct timeval
struct cc3000_timeval
{
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */

View File

@@ -416,7 +416,7 @@ extern INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrle
//
//*****************************************************************************
extern INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds,
fd_set *exceptsds, struct timeval *timeout);
fd_set *exceptsds, struct cc3000_timeval *timeout);
//*****************************************************************************
//

View File

@@ -587,7 +587,7 @@ INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrlen)
//*****************************************************************************
INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds,
struct timeval *timeout)
struct cc3000_timeval *timeout)
{
UINT8 *ptr, *args;
tBsdSelectRecvParams tParams;

89
drivers/dht/dht.c Normal file
View File

@@ -0,0 +1,89 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "extmod/machine_pulse.h"
#include "drivers/dht/dht.h"
STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) {
mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in);
mp_hal_pin_open_drain(pin);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
if (bufinfo.len < 5) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "buffer too small"));
}
// issue start command
mp_hal_pin_od_high(pin);
mp_hal_delay_ms(250);
mp_hal_pin_od_low(pin);
mp_hal_delay_ms(18);
mp_uint_t irq_state = mp_hal_quiet_timing_enter();
// release the line so the device can respond
mp_hal_pin_od_high(pin);
mp_hal_delay_us_fast(10);
// wait for device to respond
mp_uint_t ticks = mp_hal_ticks_us();
while (mp_hal_pin_read(pin) != 0) {
if ((mp_uint_t)(mp_hal_ticks_us() - ticks) > 100) {
goto timeout;
}
}
// time pulse, should be 80us
ticks = machine_time_pulse_us(pin, 1, 150);
if (ticks == (mp_uint_t)-1) {
goto timeout;
}
// time 40 pulses for data (either 26us or 70us)
uint8_t *buf = bufinfo.buf;
for (int i = 0; i < 40; ++i) {
ticks = machine_time_pulse_us(pin, 1, 100);
if (ticks == (mp_uint_t)-1) {
goto timeout;
}
buf[i / 8] = (buf[i / 8] << 1) | (ticks > 48);
}
mp_hal_quiet_timing_exit(irq_state);
return mp_const_none;
timeout:
mp_hal_quiet_timing_exit(irq_state);
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ETIMEDOUT)));
}
MP_DEFINE_CONST_FUN_OBJ_2(dht_readinto_obj, dht_readinto);

3
drivers/dht/dht.h Normal file
View File

@@ -0,0 +1,3 @@
#include "py/obj.h"
MP_DECLARE_CONST_FUN_OBJ(dht_readinto_obj);

View File

@@ -3,6 +3,7 @@
import time
import framebuf
# register definitions
SET_CONTRAST = const(0x81)
SET_ENTIRE_ON = const(0xa4)
@@ -22,6 +23,7 @@ SET_PRECHARGE = const(0xd9)
SET_VCOM_DESEL = const(0xdb)
SET_CHARGE_PUMP = const(0x8d)
class SSD1306:
def __init__(self, height, external_vcc):
self.width = 128
@@ -91,6 +93,7 @@ class SSD1306:
def text(self, string, x, y, col=1):
self.framebuf.text(string, x, y, col)
class SSD1306_I2C(SSD1306):
def __init__(self, height, i2c, addr=0x3c, external_vcc=False):
self.i2c = i2c
@@ -114,27 +117,34 @@ class SSD1306_I2C(SSD1306):
def poweron(self):
pass
# TODO convert this class to use the new hardware API
class SSD1306_SPI(SSD1306):
def __init__(self, height, spi, dc, res, cs=None, external_vcc=False):
rate = 10 * 1024 * 1024
spi.init(spi.MASTER, baudrate=rate, polarity=0, phase=0)
dc.init(dc.OUT, dc.PULL_NONE, value=0)
res.init(res.OUT, dc.PULL_NONE, value=0)
if cs is not None:
cs.init(cs.OUT, cs.PULL_NONE, value=0)
def __init__(self, height, spi, dc, res, cs, external_vcc=False):
self.rate = 10 * 1024 * 1024
dc.init(dc.OUT, value=0)
res.init(res.OUT, value=0)
cs.init(cs.OUT, value=1)
self.spi = spi
self.dc = dc
self.res = res
self.cs = cs
super().__init__(height, external_vcc)
def write_cmd(self, cmd):
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
self.cs.high()
self.dc.low()
self.spi.send(cmd)
self.cs.low()
self.spi.write(bytearray([cmd]))
self.cs.high()
def write_data(self, buf):
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
self.cs.high()
self.dc.high()
self.spi.send(buf)
self.cs.low()
self.spi.write(buf)
self.cs.high()
def poweron(self):
self.res.high()
@@ -142,4 +152,3 @@ class SSD1306_SPI(SSD1306):
self.res.low()
time.sleep_ms(10)
self.res.high()
time.sleep_ms(10)

View File

@@ -26,7 +26,7 @@ INC += -I$(BUILD)
INC += -I$(ESP_SDK)/include
# UART for "os" messages. 0 is normal UART as used by MicroPython REPL,
# 1 is debug UART (tx only).
# 1 is debug UART (tx only), -1 to disable.
UART_OS = 0
CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \
@@ -65,6 +65,7 @@ SRC_C = \
esppwm.c \
esponewire.c \
espneopixel.c \
espapa102.c \
intr.c \
modpyb.c \
modpybpin.c \
@@ -123,6 +124,10 @@ LIB_SRC_C = $(addprefix lib/,\
fatfs/option/ccsbcs.c \
)
DRIVERS_SRC_C = $(addprefix drivers/,\
dht/dht.c \
)
SRC_S = \
gchelper.s \
@@ -133,10 +138,11 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
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)/pins_$(BOARD).o
# List of sources for qstr extraction
SRC_QSTR += $(SRC_C) $(STM_SRC_C) $(EXTMOD_SRC_C)
SRC_QSTR += $(SRC_C) $(STM_SRC_C) $(EXTMOD_SRC_C) $(DRIVERS_SRC_C)
# Append any auto-generated sources that are needed by sources listed in SRC_QSTR
SRC_QSTR_AUTO_DEPS +=

View File

@@ -69,6 +69,34 @@ $ make PORT=/dev/ttyUSB0 deploy
The image produced is `firmware-combined.bin`, to be flashed at 0x00000.
First start
-----------
__Serial prompt__
You can access the REPL (Python prompt) over UART (the same as used for
programming).
- Baudrate: 115200
__WiFi__
Initally, the device configures itself as a WiFi access point (AP).
- ESSID: MicroPython-xxxxxx (xs are replaced with part of the MAC address).
- Password: micropythoN (note the upper-case N).
- IP address of the board: 192.168.4.1.
- DHCP-server is activated.
__WebREPL__
Python prompt over WiFi, connecting through a browser.
- Hosted at http://micropython.org/webrepl.
- GitHub repository https://github.com/micropython/webrepl.
Please follow the instructions there.
More detailed instructions can be found at
http://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/intro.html
Troubleshooting
---------------

View File

@@ -166,21 +166,24 @@ static int call_dupterm_read(void) {
read_m[2] = MP_OBJ_NEW_SMALL_INT(1);
mp_obj_t res = mp_call_method_n_kw(1, 0, read_m);
if (res == mp_const_none) {
nlr_pop();
return -2;
}
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ);
if (bufinfo.len == 0) {
MP_STATE_PORT(term_obj) = NULL;
mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n");
mp_uos_deactivate("dupterm: EOF received, deactivating\n", MP_OBJ_NULL);
nlr_pop();
return -1;
}
nlr_pop();
if (*(byte*)bufinfo.buf == interrupt_char) {
mp_keyboard_interrupt();
return -2;
}
return *(byte*)bufinfo.buf;
} else {
MP_STATE_PORT(term_obj) = NULL;
mp_printf(&mp_plat_print, "dupterm: Exception in read() method, deactivating: ");
mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
mp_uos_deactivate("dupterm: Exception in read() method, deactivating: ", nlr.ret_val);
}
return -1;
@@ -213,7 +216,7 @@ void mp_hal_signal_dupterm_input(void) {
system_os_post(DUPTERM_TASK_ID, 0, 0);
}
void mp_hal_pin_config_od(mp_hal_pin_obj_t pin_id) {
void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin_id) {
const pyb_pin_obj_t *pin = &pyb_pin_obj[pin_id];
if (pin->phys_port == 16) {

View File

@@ -28,6 +28,10 @@
#define _INCLUDED_MPHAL_H_
#include "py/ringbuf.h"
#include "xtirq.h"
void mp_keyboard_interrupt(void);
extern int interrupt_char;
struct _mp_print_t;
// Structure for UART-only output via mp_printf()
@@ -59,14 +63,19 @@ void ets_event_poll(void);
#include "osapi.h"
#define mp_hal_delay_us_fast(us) os_delay_us(us)
#define mp_hal_quiet_timing_enter() disable_irq()
#define mp_hal_quiet_timing_exit(irq_state) enable_irq(irq_state)
// C-level pin HAL
#include "etshal.h"
#include "gpio.h"
#include "esp8266/modpyb.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_config_od(mp_hal_pin_obj_t pin);
#define mp_hal_pin_low(p) do { \
void mp_hal_pin_input(mp_hal_pin_obj_t pin);
void mp_hal_pin_output(mp_hal_pin_obj_t pin);
void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin);
#define mp_hal_pin_od_low(p) do { \
if ((p) == 16) { WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | 1); } \
else { gpio_output_set(0, 1 << (p), 1 << (p), 0); } \
} while (0)

110
esp8266/espapa102.c Normal file
View File

@@ -0,0 +1,110 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Robert Foss, Daniel Busch
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include "c_types.h"
#include "eagle_soc.h"
#include "user_interface.h"
#include "espapa102.h"
#define NOP asm volatile(" nop \n\t")
static inline void _esp_apa102_send_byte(uint32_t clockPinMask, uint32_t dataPinMask, uint8_t byte) {
for (uint32_t i = 0; i < 8; i++) {
if (byte & 0x80) {
// set data pin high
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, dataPinMask);
} else {
// set data pin low
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, dataPinMask);
}
// set clock pin high
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, clockPinMask);
byte <<= 1;
NOP;
NOP;
// set clock pin low
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, clockPinMask);
NOP;
NOP;
}
}
static inline void _esp_apa102_send_colors(uint32_t clockPinMask, uint32_t dataPinMask, uint8_t *pixels, uint32_t numBytes) {
for (uint32_t i = 0; i < numBytes / 4; i++) {
_esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 3] | 0xE0);
_esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 2]);
_esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 1]);
_esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4]);
}
}
static inline void _esp_apa102_start_frame(uint32_t clockPinMask, uint32_t dataPinMask) {
for (uint32_t i = 0; i < 4; i++) {
_esp_apa102_send_byte(clockPinMask, dataPinMask, 0x00);
}
}
static inline void _esp_apa102_append_additionial_cycles(uint32_t clockPinMask, uint32_t dataPinMask, uint32_t numBytes) {
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, dataPinMask);
// we need to write some more clock cycles, because each led
// delays the data by one edge after inverting the clock
for (uint32_t i = 0; i < numBytes / 8 + ((numBytes / 4) % 2); i++) {
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, clockPinMask);
NOP;
NOP;
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, clockPinMask);
NOP;
NOP;
}
}
static inline void _esp_apa102_end_frame(uint32_t clockPinMask, uint32_t dataPinMask) {
for (uint32_t i = 0; i < 4; i++) {
_esp_apa102_send_byte(clockPinMask, dataPinMask, 0xFF);
}
}
void esp_apa102_write(uint8_t clockPin, uint8_t dataPin, uint8_t *pixels, uint32_t numBytes) {
uint32_t clockPinMask, dataPinMask;
clockPinMask = 1 << clockPin;
dataPinMask = 1 << dataPin;
// start the frame
_esp_apa102_start_frame(clockPinMask, dataPinMask);
// write pixels
_esp_apa102_send_colors(clockPinMask, dataPinMask, pixels, numBytes);
// end the frame
_esp_apa102_append_additionial_cycles(clockPinMask, dataPinMask, numBytes);
_esp_apa102_end_frame(clockPinMask, dataPinMask);
}

27
esp8266/espapa102.h Normal file
View File

@@ -0,0 +1,27 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Robert Foss, Daniel Busch
*
* 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.
*/
void esp_apa102_write(uint8_t clockPin, uint8_t dataPin, uint8_t *pixels, uint32_t numBytes);

View File

@@ -5,6 +5,7 @@
#include <esp_sdk_ver.h>
#include "etshal.h"
#include "user_interface.h"
#include "ets_alt_task.h"
// Use standard ets_task or alternative impl
#define USE_ETS_TASK 0
@@ -107,7 +108,12 @@ bool ets_post(uint8 prio, os_signal_t sig, os_param_t param) {
#endif
}
int ets_loop_iter_disable = 0;
bool ets_loop_iter(void) {
if (ets_loop_iter_disable) {
return false;
}
//static unsigned cnt;
bool progress = false;
for (volatile struct task_entry *t = emu_tasks; t < &emu_tasks[MP_ARRAY_SIZE(emu_tasks)]; t++) {

View File

@@ -1 +1,2 @@
extern int ets_loop_iter_disable;
bool ets_loop_iter(void);

View File

@@ -37,7 +37,7 @@ STATIC const char *help_text =
"Basic WiFi configuration:\n"
"\n"
"import network\n"
"sta_if = network.WLAN(network.STA_IF)\n"
"sta_if = network.WLAN(network.STA_IF); sta_if.active(True)\n"
"sta_if.scan() # Scan for available access points\n"
"sta_if.connect(\"<AP_name>\", \"<password>\") # Connect to an AP\n"
"sta_if.isconnected() # Check for successful connection\n"

View File

@@ -38,7 +38,7 @@
#include "gccollect.h"
#include "user_interface.h"
STATIC char heap[24 * 1024];
STATIC char heap[28 * 1024];
STATIC void mp_reset(void) {
mp_stack_set_top((void*)0x40000000);
@@ -58,7 +58,7 @@ STATIC void mp_reset(void) {
MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
pin_init0();
#if MICROPY_MODULE_FROZEN
pyexec_frozen_module("_boot");
pyexec_frozen_module("_boot.py");
pyexec_file("boot.py");
pyexec_file("main.py");
#endif

View File

@@ -27,13 +27,14 @@
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include "py/nlr.h"
#include "py/obj.h"
#include "py/gc.h"
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "drivers/dht/dht.h"
#include "netutils.h"
#include "queue.h"
#include "ets_sys.h"
@@ -43,6 +44,7 @@
#include "spi_flash.h"
#include "mem.h"
#include "espneopixel.h"
#include "espapa102.h"
#include "modpyb.h"
#define MODESP_ESPCONN (0)
@@ -577,7 +579,7 @@ STATIC mp_obj_t esp_flash_read(mp_obj_t offset_in, mp_obj_t len_or_buf_in) {
if (alloc_buf) {
m_del(byte, buf, len);
}
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? ETIMEDOUT : EIO)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_read_obj, esp_flash_read);
@@ -594,7 +596,7 @@ STATIC mp_obj_t esp_flash_write(mp_obj_t offset_in, const mp_obj_t buf_in) {
}
nlr_raise(mp_obj_new_exception_arg1(
&mp_type_OSError,
MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? ETIMEDOUT : EIO)));
MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_write_obj, esp_flash_write);
@@ -606,7 +608,7 @@ STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) {
}
nlr_raise(mp_obj_new_exception_arg1(
&mp_type_OSError,
MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? ETIMEDOUT : EIO)));
MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_flash_erase_obj, esp_flash_erase);
@@ -636,6 +638,16 @@ STATIC mp_obj_t esp_neopixel_write_(mp_obj_t pin, mp_obj_t buf, mp_obj_t is800k)
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_neopixel_write_obj, esp_neopixel_write_);
STATIC mp_obj_t esp_apa102_write_(mp_obj_t clockPin, mp_obj_t dataPin, mp_obj_t buf) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
esp_apa102_write(mp_obj_get_pin_obj(clockPin)->phys_port,
mp_obj_get_pin_obj(dataPin)->phys_port,
(uint8_t*)bufinfo.buf, bufinfo.len);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_apa102_write_obj, esp_apa102_write_);
STATIC mp_obj_t esp_freemem() {
return MP_OBJ_NEW_SMALL_INT(system_get_free_heap_size());
}
@@ -679,6 +691,8 @@ STATIC const mp_map_elem_t esp_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_getaddrinfo_obj },
#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&esp_neopixel_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_apa102_write), (mp_obj_t)&esp_apa102_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_dht_readinto), (mp_obj_t)&dht_readinto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_freemem), (mp_obj_t)&esp_freemem_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_meminfo), (mp_obj_t)&esp_meminfo_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_info_obj }, // TODO delete/rename/move elsewhere

View File

@@ -30,10 +30,12 @@
#include "py/obj.h"
#include "py/runtime.h"
#include "extmod/machine_mem.h"
#include "extmod/machine_pulse.h"
#include "extmod/machine_i2c.h"
#include "modpyb.h"
#include "modpybrtc.h"
#include "xtirq.h"
#include "os_type.h"
#include "osapi.h"
#include "etshal.h"
@@ -189,6 +191,25 @@ const mp_obj_type_t esp_timer_type = {
.locals_dict = (mp_obj_t)&esp_timer_locals_dict,
};
// this bit is unused in the Xtensa PS register
#define ETS_LOOP_ITER_BIT (12)
STATIC mp_obj_t machine_disable_irq(void) {
uint32_t state = disable_irq();
state = (state & ~(1 << ETS_LOOP_ITER_BIT)) | (ets_loop_iter_disable << ETS_LOOP_ITER_BIT);
ets_loop_iter_disable = 1;
return mp_obj_new_int(state);
}
MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq);
STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) {
uint32_t state = mp_obj_get_int(state_in);
ets_loop_iter_disable = (state >> ETS_LOOP_ITER_BIT) & 1;
enable_irq(state & ~(1 << ETS_LOOP_ITER_BIT));
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq);
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
{ MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
@@ -201,6 +222,11 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
{ MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) },
{ MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) },
{ MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) },
{ MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) },
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&esp_timer_type) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pyb_pin_type) },

View File

@@ -27,7 +27,6 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include "py/nlr.h"
#include "py/objlist.h"
@@ -137,16 +136,25 @@ STATIC void esp_scan_cb(scaninfo *si, STATUS status) {
return;
}
if (si->pbss && status == 0) {
struct bss_info *bs;
STAILQ_FOREACH(bs, si->pbss, next) {
mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL);
t->items[0] = mp_obj_new_bytes(bs->ssid, strlen((char*)bs->ssid));
t->items[1] = mp_obj_new_bytes(bs->bssid, sizeof(bs->bssid));
t->items[2] = MP_OBJ_NEW_SMALL_INT(bs->channel);
t->items[3] = MP_OBJ_NEW_SMALL_INT(bs->rssi);
t->items[4] = MP_OBJ_NEW_SMALL_INT(bs->authmode);
t->items[5] = MP_OBJ_NEW_SMALL_INT(bs->is_hidden);
mp_obj_list_append(*esp_scan_list, MP_OBJ_FROM_PTR(t));
// we need to catch any memory errors
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
struct bss_info *bs;
STAILQ_FOREACH(bs, si->pbss, next) {
mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL);
t->items[0] = mp_obj_new_bytes(bs->ssid, strlen((char*)bs->ssid));
t->items[1] = mp_obj_new_bytes(bs->bssid, sizeof(bs->bssid));
t->items[2] = MP_OBJ_NEW_SMALL_INT(bs->channel);
t->items[3] = MP_OBJ_NEW_SMALL_INT(bs->rssi);
t->items[4] = MP_OBJ_NEW_SMALL_INT(bs->authmode);
t->items[5] = MP_OBJ_NEW_SMALL_INT(bs->is_hidden);
mp_obj_list_append(*esp_scan_list, MP_OBJ_FROM_PTR(t));
}
nlr_pop();
} else {
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
// indicate error
*esp_scan_list = MP_OBJ_NULL;
}
} else {
// indicate error
@@ -156,14 +164,25 @@ STATIC void esp_scan_cb(scaninfo *si, STATUS status) {
}
STATIC mp_obj_t esp_scan(mp_obj_t self_in) {
if (wifi_get_opmode() == SOFTAP_MODE) {
require_if(self_in, STATION_IF);
if ((wifi_get_opmode() & STATION_MODE) == 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
"scan unsupported in AP mode"));
"STA must be active"));
}
mp_obj_t list = mp_obj_new_list(0, NULL);
esp_scan_list = &list;
wifi_station_scan(NULL, (scan_done_cb_t)esp_scan_cb);
ETS_POLL_WHILE(esp_scan_list != NULL);
while (esp_scan_list != NULL) {
// our esp_scan_cb is called via ets_loop_iter so it's safe to set the
// esp_scan_list variable to NULL without disabling interrupts
if (MP_STATE_VM(mp_pending_exception) != NULL) {
esp_scan_list = NULL;
mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
nlr_raise(obj);
}
ets_loop_iter();
}
if (list == MP_OBJ_NULL) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "scan failed"));
}

View File

@@ -36,6 +36,7 @@
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/gc.h"
#include "py/mphal.h"
#include "modpyb.h"
#define GET_TRIGGER(phys_port) \
@@ -123,6 +124,34 @@ uint mp_obj_get_pin(mp_obj_t pin_in) {
return mp_obj_get_pin_obj(pin_in)->phys_port;
}
void mp_hal_pin_input(mp_hal_pin_obj_t pin_id) {
pin_mode[pin_id] = GPIO_MODE_INPUT;
if (pin_id == 16) {
WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1);
WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1);
WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); // input
} else {
const pyb_pin_obj_t *self = &pyb_pin_obj[pin_id];
PIN_FUNC_SELECT(self->periph, self->func);
PIN_PULLUP_DIS(self->periph);
gpio_output_set(0, 0, 0, 1 << self->phys_port);
}
}
void mp_hal_pin_output(mp_hal_pin_obj_t pin_id) {
pin_mode[pin_id] = GPIO_MODE_OUTPUT;
if (pin_id == 16) {
WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1);
WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1);
WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | 1); // output
} else {
const pyb_pin_obj_t *self = &pyb_pin_obj[pin_id];
PIN_FUNC_SELECT(self->periph, self->func);
PIN_PULLUP_DIS(self->periph);
gpio_output_set(0, 0, 1 << self->phys_port, 0);
}
}
int pin_get(uint pin) {
if (pin == 16) {
return READ_PERI_REG(RTC_GPIO_IN_DATA) & 1;

View File

@@ -53,6 +53,9 @@ STATIC const pyb_rtc_obj_t pyb_rtc_obj = {{&pyb_rtc_type}};
uint32_t pyb_rtc_alarm0_wake; // see MACHINE_WAKE_xxx constants
uint64_t pyb_rtc_alarm0_expiry; // in microseconds
// RTC overflow checking
STATIC uint32_t rtc_last_ticks;
void mp_hal_rtc_init(void) {
uint32_t magic;
@@ -64,7 +67,11 @@ void mp_hal_rtc_init(void) {
int64_t delta = 0;
system_rtc_mem_write(MEM_CAL_ADDR, &cal, sizeof(cal));
system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta));
uint32_t len = 0;
system_rtc_mem_write(MEM_USER_LEN_ADDR, &len, sizeof(len));
}
// system_get_rtc_time() is always 0 after reset/deepsleep
rtc_last_ticks = system_get_rtc_time();
// reset ALARM0 state
pyb_rtc_alarm0_wake = 0;
@@ -79,13 +86,11 @@ STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp
return (mp_obj_t)&pyb_rtc_obj;
}
STATIC uint64_t pyb_rtc_raw_us(uint64_t cal) {
return (system_get_rtc_time() * cal) >> 12;
};
void pyb_rtc_set_us_since_2000(uint64_t nowus) {
uint32_t cal = system_rtc_clock_cali_proc();
int64_t delta = nowus - pyb_rtc_raw_us(cal);
// Save RTC ticks for overflow detection.
rtc_last_ticks = system_get_rtc_time();
int64_t delta = nowus - (((uint64_t)rtc_last_ticks * cal) >> 12);
// As the calibration value jitters quite a bit, to make the
// clock at least somewhat practially usable, we need to store it
@@ -96,11 +101,23 @@ void pyb_rtc_set_us_since_2000(uint64_t nowus) {
uint64_t pyb_rtc_get_us_since_2000() {
uint32_t cal;
int64_t delta;
uint32_t rtc_ticks;
system_rtc_mem_read(MEM_CAL_ADDR, &cal, sizeof(cal));
system_rtc_mem_read(MEM_DELTA_ADDR, &delta, sizeof(delta));
return pyb_rtc_raw_us(cal) + delta;
// ESP-SDK system_get_rtc_time() only returns uint32 and therefore
// overflow about every 7:45h. Thus, we have to check for
// overflow and handle it.
rtc_ticks = system_get_rtc_time();
if (rtc_ticks < rtc_last_ticks) {
// Adjust delta because of RTC overflow.
delta += (uint64_t)cal << 20;
system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta));
}
rtc_last_ticks = rtc_ticks;
return (((uint64_t)rtc_ticks * cal) >> 12) + delta;
};
STATIC mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
@@ -145,20 +162,17 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_d
STATIC mp_obj_t pyb_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) {
uint8_t rtcram[MEM_USER_MAXLEN];
uint32_t len;
uint32_t magic;
if (n_args == 1) {
system_rtc_mem_read(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic));
if (magic != MEM_MAGIC) {
return mp_const_none;
}
// read RTC memory
system_rtc_mem_read(MEM_USER_LEN_ADDR, &len, sizeof(len));
system_rtc_mem_read(MEM_USER_DATA_ADDR, rtcram, len + (4 - len % 4));
return mp_obj_new_bytes(rtcram, len);
} else {
// write RTC memory
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
@@ -167,8 +181,6 @@ STATIC mp_obj_t pyb_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) {
"buffer too long"));
}
magic = MEM_MAGIC;
system_rtc_mem_write(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic));
len = bufinfo.len;
system_rtc_mem_write(MEM_USER_LEN_ADDR, &len, sizeof(len));

View File

@@ -27,7 +27,6 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include "ets_sys.h"
#include "etshal.h"
@@ -124,6 +123,12 @@ STATIC void pyb_spi_init_helper(pyb_spi_obj_t *self, size_t n_args, const mp_obj
if (args[ARG_miso].u_obj != MP_OBJ_NULL) {
self->miso = mp_hal_get_pin_obj(args[ARG_miso].u_obj);
}
// configure pins
mp_hal_pin_write(self->sck, self->polarity);
mp_hal_pin_output(self->sck);
mp_hal_pin_output(self->mosi);
mp_hal_pin_input(self->miso);
}
STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {

View File

@@ -27,13 +27,13 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include "ets_sys.h"
#include "uart.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mperrno.h"
#include "modpyb.h"
// baudrate is currently fixed to this value
@@ -136,7 +136,7 @@ STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, i
// wait for first char to become available
if (!uart_rx_wait(self->timeout * 1000)) {
*errcode = EAGAIN;
*errcode = MP_EAGAIN;
return MP_STREAM_ERROR;
}
@@ -173,7 +173,7 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t
}
STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
*errcode = EINVAL;
*errcode = MP_EINVAL;
return MP_STREAM_ERROR;
}

View File

@@ -25,7 +25,6 @@
*/
#include <string.h>
#include <errno.h>
#include "py/mpconfig.h"
#include "py/nlr.h"
@@ -33,6 +32,7 @@
#include "py/objtuple.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "py/mperrno.h"
#include "extmod/misc.h"
#include "genhdr/mpversion.h"
#include "esp_mphal.h"
@@ -74,12 +74,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname);
#if MICROPY_VFS_FAT
mp_obj_t vfs_proxy_call(qstr method_name, mp_uint_t n_args, const mp_obj_t *args) {
if (MP_STATE_PORT(fs_user_mount)[0] == NULL) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENODEV)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENODEV)));
}
mp_obj_t meth[n_args + 2];
mp_load_method(MP_STATE_PORT(fs_user_mount)[0], method_name, meth);
memcpy(meth + 2, args, n_args * sizeof(*args));
if (args != NULL) {
memcpy(meth + 2, args, n_args * sizeof(*args));
}
return mp_call_method_n_kw(n_args, 0, meth);
}
@@ -93,10 +95,29 @@ STATIC mp_obj_t os_mkdir(mp_obj_t path_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir);
STATIC mp_obj_t os_chdir(mp_obj_t path_in) {
return vfs_proxy_call(MP_QSTR_chdir, 1, &path_in);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_chdir_obj, os_chdir);
STATIC mp_obj_t os_getcwd(void) {
return vfs_proxy_call(MP_QSTR_getcwd, 0, NULL);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd);
STATIC mp_obj_t os_remove(mp_obj_t path_in) {
return vfs_proxy_call(MP_QSTR_remove, 1, &path_in);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove);
STATIC mp_obj_t os_rename(mp_obj_t path_old, mp_obj_t path_new) {
mp_obj_t args[2];
args[0] = path_old;
args[1] = path_new;
return vfs_proxy_call(MP_QSTR_rename, 2, args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename);
#endif
STATIC mp_obj_t os_urandom(mp_obj_t num) {
@@ -117,6 +138,11 @@ STATIC mp_obj_t os_dupterm_notify(mp_obj_t obj_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_dupterm_notify_obj, os_dupterm_notify);
STATIC mp_obj_t os_stat(mp_obj_t path_in) {
return vfs_proxy_call(MP_QSTR_stat, 1, &path_in);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_stat_obj, os_stat);
STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },
{ MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) },
@@ -129,7 +155,11 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&os_listdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&os_mkdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&os_chdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&os_getcwd_obj) },
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&os_remove_obj) },
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&os_rename_obj) },
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&os_stat_obj) },
#endif
};

View File

@@ -4,6 +4,11 @@
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C)
#define MICROPY_ALLOC_PATH_MAX (128)
#define MICROPY_ALLOC_LEXER_INDENT_INIT (8)
#define MICROPY_ALLOC_PARSE_RULE_INIT (48)
#define MICROPY_ALLOC_PARSE_RULE_INC (8)
#define MICROPY_ALLOC_PARSE_RESULT_INC (8)
#define MICROPY_ALLOC_PARSE_CHUNK_INIT (64)
#define MICROPY_EMIT_X64 (0)
#define MICROPY_EMIT_THUMB (0)
#define MICROPY_EMIT_INLINE_THUMB (0)
@@ -19,6 +24,7 @@
#define MICROPY_ENABLE_SOURCE_LINE (1)
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
#define MICROPY_USE_INTERNAL_ERRNO (1)
#define MICROPY_PY_BUILTINS_COMPLEX (0)
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
@@ -32,14 +38,17 @@
#define MICROPY_PY_ARRAY (1)
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
#define MICROPY_PY_COLLECTIONS (1)
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
#define MICROPY_PY_MATH (1)
#define MICROPY_PY_CMATH (0)
#define MICROPY_PY_IO (1)
#define MICROPY_PY_IO_FILEIO (1)
#define MICROPY_PY_STRUCT (1)
#define MICROPY_PY_SYS (1)
#define MICROPY_PY_SYS_MAXSIZE (1)
#define MICROPY_PY_SYS_EXIT (1)
#define MICROPY_PY_SYS_STDFILES (1)
#define MICROPY_PY_UERRNO (1)
#define MICROPY_PY_UBINASCII (1)
#define MICROPY_PY_UCTYPES (1)
#define MICROPY_PY_UHASHLIB (1)
@@ -51,6 +60,7 @@
#define MICROPY_PY_UZLIB (1)
#define MICROPY_PY_LWIP (1)
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_MACHINE_PULSE (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_WEBSOCKET (1)
#define MICROPY_PY_WEBREPL (1)
@@ -105,6 +115,9 @@ typedef uint32_t sys_prot_t; // for modlwip
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
#define mp_type_fileio fatfs_type_fileio
#define mp_type_textio fatfs_type_textio
// extra built in names to add to the global namespace
#define MICROPY_PORT_BUILTINS \
{ MP_OBJ_NEW_QSTR(MP_QSTR_help), (mp_obj_t)&mp_builtin_help_obj }, \
@@ -135,6 +148,7 @@ extern const struct _mp_obj_module_t onewire_module;
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&utime_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&uos_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_errno), (mp_obj_t)&mp_module_uerrno }, \
#define MP_STATE_PORT MP_STATE_VM

28
esp8266/scripts/apa102.py Normal file
View File

@@ -0,0 +1,28 @@
# APA102 driver for MicroPython on ESP8266
# MIT license; Copyright (c) 2016 Robert Foss, Daniel Busch
from esp import apa102_write
class APA102:
def __init__(self, clock_pin, data_pin, n):
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)

32
esp8266/scripts/dht.py Normal file
View File

@@ -0,0 +1,32 @@
# DHT11/DHT22 driver for MicroPython on ESP8266
# MIT license; Copyright (c) 2016 Damien P. George
import esp
class DHTBase:
def __init__(self, pin):
self.pin = pin
self.buf = bytearray(5)
def measure(self):
buf = self.buf
esp.dht_readinto(self.pin, buf)
if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xff != buf[4]:
raise Exception("checksum error")
class DHT11(DHTBase):
def humidity(self):
return self.buf[0]
def temperature(self):
return self.buf[2]
class DHT22(DHTBase):
def humidity(self):
return (self.buf[0] << 8 | self.buf[1]) * 0.1
def temperature(self):
t = ((self.buf[2] & 0x7f) << 8 | self.buf[3]) * 0.1
if self.buf[2] & 0x80:
t = -t
return t

View File

@@ -40,7 +40,7 @@ def setup():
with open("/boot.py", "w") as f:
f.write("""\
# This file is executed on every boot (including wake-boot from deepsleep)
import webrepl
webrepl.start()
#import webrepl
#webrepl.start()
""")
return vfs

View File

@@ -8,7 +8,7 @@ class NeoPixel:
self.pin = pin
self.n = n
self.buf = bytearray(n * 3)
self.pin.init(pin.OUT, pin.PULL_NONE)
self.pin.init(pin.OUT)
def __setitem__(self, index, val):
r, g, b = val
@@ -20,5 +20,12 @@ class NeoPixel:
i = index * 3
return self.buf[i + 1], self.buf[i], self.buf[i + 2]
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
def write(self):
neopixel_write(self.pin, self.buf, True)

View File

@@ -10,10 +10,12 @@ except:
# (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60
NTP_DELTA = 3155673600
host = "pool.ntp.org"
def time():
NTP_QUERY = bytearray(48)
NTP_QUERY[0] = 0x1b
addr = socket.getaddrinfo('pool.ntp.org', 123)[0][-1]
addr = socket.getaddrinfo(host, 123)[0][-1]
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimeout(1)
res = s.sendto(NTP_QUERY, addr)

View File

@@ -13,7 +13,7 @@ class OneWire:
def __init__(self, pin):
self.pin = pin
self.pin.init(pin.OPEN_DRAIN, pin.PULL_NONE)
self.pin.init(pin.OPEN_DRAIN)
def reset(self):
return _ow.reset(self.pin)

View File

@@ -1,5 +1,7 @@
import esp
import uctypes
import network
import lwip
def main():
@@ -7,6 +9,7 @@ def main():
ROM = uctypes.bytearray_at(0x40200000, 16)
fid = esp.flash_id()
print("FlashROM:")
print("Flash ID: %x (Vendor: %x Device: %x)" % (fid, fid & 0xff, fid & 0xff00 | fid >> 16))
print("Flash bootloader data:")
@@ -15,5 +18,14 @@ def main():
print("Byte @2: %02x" % ROM[2])
print("Byte @3: %02x (Flash size: %s Flash freq: %s)" % (ROM[3], SZ_MAP.get(ROM[3] >> 4, "?"), FREQ_MAP.get(ROM[3] & 0xf)))
print("\nNetworking:")
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)))
print("lwIP PCBs:")
lwip.print_pcbs()
main()

View File

@@ -10,7 +10,7 @@ listen_s = None
client_s = None
def setup_conn(port, accept_handler):
global listen_s, client_s
global listen_s
listen_s = socket.socket()
listen_s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
@@ -19,11 +19,13 @@ def setup_conn(port, accept_handler):
listen_s.bind(addr)
listen_s.listen(1)
listen_s.setsockopt(socket.SOL_SOCKET, 20, accept_handler)
if accept_handler:
listen_s.setsockopt(socket.SOL_SOCKET, 20, accept_handler)
for i in (network.AP_IF, network.STA_IF):
iface = network.WLAN(i)
if iface.active():
print("WebREPL daemon started on ws://%s:%d" % (iface.ifconfig()[0], port))
return listen_s
def accept_conn(listen_sock):
@@ -49,14 +51,25 @@ def stop():
listen_s.close()
def start(port=8266):
def start(port=8266, password=None):
stop()
try:
import port_config
_webrepl.password(port_config.WEBREPL_PASS)
if password is None:
try:
import port_config
_webrepl.password(port_config.WEBREPL_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")
else:
_webrepl.password(password)
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")
def start_foreground(port=8266):
stop()
s = setup_conn(port, None)
accept_conn(s)

View File

@@ -26,7 +26,7 @@ def getpass(stream, prompt):
stream.write("\r\n")
return passwd
passwd += c
# stream.write("*")
stream.write("*")
def handle_conn(listen_sock):
cl, remote_addr = listen_sock.accept()
@@ -60,6 +60,9 @@ some boards, you may need to press reset button or reconnect power.\r
if len(passwd1) < 4:
ws.write("Password too short\r\n")
continue
elif len(passwd1) > 9:
ws.write("Password too long\r\n")
continue
passwd2 = getpass(ws, "Confirm password: ")
if passwd1 == passwd2:
break

View File

@@ -19,6 +19,9 @@
#include "user_interface.h"
#include "esp_mphal.h"
// seems that this is missing in the Espressif SDK
#define FUNC_U0RXD 0
#define UART_REPL UART0
// UartDev is defined and initialized in rom code.
@@ -53,7 +56,7 @@ static void ICACHE_FLASH_ATTR uart_config(uint8 uart_no) {
ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, NULL);
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD);
}
uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate));

60
esp8266/xtirq.h Normal file
View File

@@ -0,0 +1,60 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __MICROPY_INCLUDED_ESP8266_XTIRQ_H__
#define __MICROPY_INCLUDED_ESP8266_XTIRQ_H__
#include <stdint.h>
// returns the value of "intlevel" from the PS register
static inline uint32_t query_irq(void) {
uint32_t ps;
__asm__ volatile("rsr %0, ps" : "=a" (ps));
return ps & 0xf;
}
// irqs with a priority value lower or equal to "intlevel" will be disabled
// "intlevel" should be between 0 and 15 inclusive, and should be an integer
static inline uint32_t raise_irq_pri(uint32_t intlevel) {
uint32_t old_ps;
__asm__ volatile ("rsil %0, %1" : "=a" (old_ps) : "I" (intlevel));
return old_ps;
}
// "ps" should be the value returned from raise_irq_pri
static inline void restore_irq_pri(uint32_t ps) {
__asm__ volatile ("wsr %0, ps; rsync" :: "a" (ps));
}
static inline uint32_t disable_irq(void) {
return raise_irq_pri(15);
}
static inline void enable_irq(uint32_t irq_state) {
restore_irq_pri(irq_state);
}
#endif // __MICROPY_INCLUDED_ESP8266_XTIRQ_H__

View File

@@ -32,7 +32,7 @@
#include "py/nlr.h"
#include "py/runtime.h"
#include "lib/fatfs/ff.h"
#include "fsusermount.h"
#include "extmod/fsusermount.h"
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) {
static const mp_arg_t allowed_args[] = {

View File

@@ -48,7 +48,7 @@ STATIC void mp_hal_i2c_delay(machine_i2c_obj_t *self) {
}
STATIC void mp_hal_i2c_scl_low(machine_i2c_obj_t *self) {
mp_hal_pin_low(self->scl);
mp_hal_pin_od_low(self->scl);
}
STATIC void mp_hal_i2c_scl_release(machine_i2c_obj_t *self) {
@@ -56,7 +56,7 @@ STATIC void mp_hal_i2c_scl_release(machine_i2c_obj_t *self) {
}
STATIC void mp_hal_i2c_sda_low(machine_i2c_obj_t *self) {
mp_hal_pin_low(self->sda);
mp_hal_pin_od_low(self->sda);
}
STATIC void mp_hal_i2c_sda_release(machine_i2c_obj_t *self) {
@@ -91,8 +91,8 @@ STATIC void mp_hal_i2c_init(machine_i2c_obj_t *self, uint32_t freq) {
if (self->us_delay == 0) {
self->us_delay = 1;
}
mp_hal_pin_config_od(self->scl);
mp_hal_pin_config_od(self->sda);
mp_hal_pin_open_drain(self->scl);
mp_hal_pin_open_drain(self->sda);
mp_hal_i2c_stop(self);
}

67
extmod/machine_pulse.c Normal file
View File

@@ -0,0 +1,67 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "py/mperrno.h"
#include "extmod/machine_pulse.h"
#if MICROPY_PY_MACHINE_PULSE
mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) {
mp_uint_t start = mp_hal_ticks_us();
while (mp_hal_pin_read(pin) != pulse_level) {
if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {
return (mp_uint_t)-1;
}
}
start = mp_hal_ticks_us();
while (mp_hal_pin_read(pin) == pulse_level) {
if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {
return (mp_uint_t)-1;
}
}
return mp_hal_ticks_us() - start;
}
STATIC mp_obj_t machine_time_pulse_us_(size_t n_args, const mp_obj_t *args) {
mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(args[0]);
int level = 0;
if (mp_obj_is_true(args[1])) {
level = 1;
}
mp_uint_t timeout_us = 1000000;
if (n_args > 2) {
timeout_us = mp_obj_get_int(args[2]);
}
mp_uint_t us = machine_time_pulse_us(pin, level, timeout_us);
if (us == (mp_uint_t)-1) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ETIMEDOUT)));
}
return mp_obj_new_int(us);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj, 2, 3, machine_time_pulse_us_);
#endif

37
extmod/machine_pulse.h Normal file
View File

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

View File

@@ -34,6 +34,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_uos_dupterm_obj);
#if MICROPY_PY_OS_DUPTERM
void mp_uos_dupterm_tx_strn(const char *str, size_t len);
void mp_uos_deactivate(const char *msg, mp_obj_t exc);
#else
#define mp_uos_dupterm_tx_strn(s, l)
#endif

View File

@@ -26,13 +26,13 @@
*/
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include "py/nlr.h"
#include "py/objlist.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "netutils.h"
@@ -172,45 +172,45 @@ STATIC const mp_obj_type_t lwip_slip_type = {
// investigate in more detail.
#if LWIP_VERSION < 0x01040100
static const int error_lookup_table[] = {
0, /* ERR_OK 0 No error, everything OK. */
ENOMEM, /* ERR_MEM -1 Out of memory error. */
ENOBUFS, /* ERR_BUF -2 Buffer error. */
EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
EINVAL, /* ERR_VAL -6 Illegal value. */
EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
0, /* ERR_OK 0 No error, everything OK. */
MP_ENOMEM, /* ERR_MEM -1 Out of memory error. */
MP_ENOBUFS, /* ERR_BUF -2 Buffer error. */
MP_EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
MP_EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
MP_EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
MP_EINVAL, /* ERR_VAL -6 Illegal value. */
MP_EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
ECONNABORTED, /* ERR_ABRT -8 Connection aborted. */
ECONNRESET, /* ERR_RST -9 Connection reset. */
ENOTCONN, /* ERR_CLSD -10 Connection closed. */
ENOTCONN, /* ERR_CONN -11 Not connected. */
EIO, /* ERR_ARG -12 Illegal argument. */
EADDRINUSE, /* ERR_USE -13 Address in use. */
-1, /* ERR_IF -14 Low-level netif error */
EALREADY, /* ERR_ISCONN -15 Already connected. */
EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */
MP_ECONNABORTED, /* ERR_ABRT -8 Connection aborted. */
MP_ECONNRESET, /* ERR_RST -9 Connection reset. */
MP_ENOTCONN, /* ERR_CLSD -10 Connection closed. */
MP_ENOTCONN, /* ERR_CONN -11 Not connected. */
MP_EIO, /* ERR_ARG -12 Illegal argument. */
MP_EADDRINUSE, /* ERR_USE -13 Address in use. */
-1, /* ERR_IF -14 Low-level netif error */
MP_EALREADY, /* ERR_ISCONN -15 Already connected. */
MP_EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */
};
#else
static const int error_lookup_table[] = {
0, /* ERR_OK 0 No error, everything OK. */
ENOMEM, /* ERR_MEM -1 Out of memory error. */
ENOBUFS, /* ERR_BUF -2 Buffer error. */
EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
EINVAL, /* ERR_VAL -6 Illegal value. */
EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
0, /* ERR_OK 0 No error, everything OK. */
MP_ENOMEM, /* ERR_MEM -1 Out of memory error. */
MP_ENOBUFS, /* ERR_BUF -2 Buffer error. */
MP_EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
MP_EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
MP_EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
MP_EINVAL, /* ERR_VAL -6 Illegal value. */
MP_EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
EADDRINUSE, /* ERR_USE -8 Address in use. */
EALREADY, /* ERR_ISCONN -9 Already connected. */
ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */
ECONNRESET, /* ERR_RST -11 Connection reset. */
ENOTCONN, /* ERR_CLSD -12 Connection closed. */
ENOTCONN, /* ERR_CONN -13 Not connected. */
EIO, /* ERR_ARG -14 Illegal argument. */
-1, /* ERR_IF -15 Low-level netif error */
EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */
MP_EADDRINUSE, /* ERR_USE -8 Address in use. */
MP_EALREADY, /* ERR_ISCONN -9 Already connected. */
MP_ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */
MP_ECONNRESET, /* ERR_RST -11 Connection reset. */
MP_ENOTCONN, /* ERR_CLSD -12 Connection closed. */
MP_ENOTCONN, /* ERR_CONN -13 Not connected. */
MP_EIO, /* ERR_ARG -14 Illegal argument. */
-1, /* ERR_IF -15 Low-level netif error */
MP_EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */
};
#endif
@@ -311,6 +311,17 @@ STATIC err_t _lwip_tcp_recv_unaccepted(void *arg, struct tcp_pcb *pcb, struct pb
return ERR_BUF;
}
// "Poll" (idle) callback to be called ASAP after accept callback
// to execute Python callback function, as it can't be executed
// from accept callback itself.
STATIC err_t _lwip_tcp_accept_finished(void *arg, struct tcp_pcb *pcb)
{
lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg;
tcp_poll(pcb, NULL, 0);
exec_user_callback(socket);
return ERR_OK;
}
// Callback for incoming tcp connections.
STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg;
@@ -323,7 +334,12 @@ STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
return ERR_BUF;
} else {
socket->incoming.connection = newpcb;
exec_user_callback(socket);
if (socket->callback != MP_OBJ_NULL) {
// Schedule accept callback to be called when lwIP is done
// with processing this incoming connection on its side and
// is idle.
tcp_poll(newpcb, _lwip_tcp_accept_finished, 1);
}
return ERR_OK;
}
}
@@ -363,7 +379,7 @@ STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
// FIXME: maybe PBUF_ROM?
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
if (p == NULL) {
*_errno = ENOMEM;
*_errno = MP_ENOMEM;
return -1;
}
@@ -401,7 +417,7 @@ STATIC mp_uint_t lwip_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
if (socket->incoming.pbuf != NULL) break;
}
if (socket->incoming.pbuf == NULL) {
*_errno = ETIMEDOUT;
*_errno = MP_ETIMEDOUT;
return -1;
}
} else {
@@ -444,7 +460,7 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
if (available == 0) {
// Non-blocking socket
if (socket->timeout == 0) {
*_errno = EAGAIN;
*_errno = MP_EAGAIN;
return MP_STREAM_ERROR;
}
@@ -457,7 +473,7 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
// Avoid sending too small packets, so wait until at least 16 bytes available
while (socket->state >= STATE_CONNECTED && (available = tcp_sndbuf(socket->pcb.tcp)) < 16) {
if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) {
*_errno = ETIMEDOUT;
*_errno = MP_ETIMEDOUT;
return MP_STREAM_ERROR;
}
poll_sockets();
@@ -491,14 +507,14 @@ STATIC mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
if (socket->state == STATE_PEER_CLOSED) {
return 0;
}
*_errno = EAGAIN;
*_errno = MP_EAGAIN;
return -1;
}
mp_uint_t start = mp_hal_ticks_ms();
while (socket->state == STATE_CONNECTED && socket->incoming.pbuf == NULL) {
if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) {
*_errno = ETIMEDOUT;
*_errno = MP_ETIMEDOUT;
return -1;
}
poll_sockets();
@@ -570,11 +586,11 @@ STATIC mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, mp_uint_t n_args
case MOD_NETWORK_SOCK_STREAM: socket->pcb.tcp = tcp_new(); break;
case MOD_NETWORK_SOCK_DGRAM: socket->pcb.udp = udp_new(); break;
//case MOD_NETWORK_SOCK_RAW: socket->pcb.raw = raw_new(); break;
default: nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL)));
default: nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EINVAL)));
}
if (socket->pcb.tcp == NULL) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOMEM)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENOMEM)));
}
switch (socket->type) {
@@ -670,15 +686,15 @@ STATIC mp_obj_t lwip_socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) {
mp_int_t backlog = mp_obj_get_int(backlog_in);
if (socket->pcb.tcp == NULL) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EBADF)));
}
if (socket->type != MOD_NETWORK_SOCK_STREAM) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EOPNOTSUPP)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EOPNOTSUPP)));
}
struct tcp_pcb *new_pcb = tcp_listen_with_backlog(socket->pcb.tcp, (u8_t)backlog);
if (new_pcb == NULL) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOMEM)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENOMEM)));
}
socket->pcb.tcp = new_pcb;
tcp_accept(new_pcb, _lwip_tcp_accept);
@@ -691,15 +707,15 @@ STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
lwip_socket_obj_t *socket = self_in;
if (socket->pcb.tcp == NULL) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EBADF)));
}
if (socket->type != MOD_NETWORK_SOCK_STREAM) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EOPNOTSUPP)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EOPNOTSUPP)));
}
// I need to do this because "tcp_accepted", later, is a macro.
struct tcp_pcb *listener = socket->pcb.tcp;
if (listener->state != LISTEN) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EINVAL)));
}
// accept incoming connection
@@ -710,7 +726,7 @@ STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
if (socket->incoming.connection != NULL) break;
}
if (socket->incoming.connection == NULL) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ETIMEDOUT)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ETIMEDOUT)));
}
} else {
while (socket->incoming.connection == NULL) {
@@ -757,7 +773,7 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
lwip_socket_obj_t *socket = self_in;
if (socket->pcb.tcp == NULL) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EBADF)));
}
// get address
@@ -772,9 +788,9 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
case MOD_NETWORK_SOCK_STREAM: {
if (socket->state != STATE_NEW) {
if (socket->state == STATE_CONNECTED) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EALREADY)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EALREADY)));
} else {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINPROGRESS)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EINPROGRESS)));
}
}
// Register our recieve callback.
@@ -794,7 +810,7 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
if (socket->state != STATE_CONNECTING) break;
}
if (socket->state == STATE_CONNECTING) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ETIMEDOUT)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ETIMEDOUT)));
}
} else {
while (socket->state == STATE_CONNECTING) {
@@ -982,7 +998,7 @@ STATIC mp_obj_t lwip_socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) {
// most useful behavior is: check whether we will be able to send all of input
// data without EAGAIN, and if won't be, raise it without sending any.
if (bufinfo.len > tcp_sndbuf(socket->pcb.tcp)) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EAGAIN)));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EAGAIN)));
}
}
// TODO: In CPython3.5, socket timeout should apply to the

View File

@@ -31,7 +31,7 @@
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/binary.h"
#include "modubinascii.h"
#include "extmod/modubinascii.h"
mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {

View File

@@ -31,9 +31,20 @@
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/objtuple.h"
#include "py/stream.h"
#if MICROPY_PY_OS_DUPTERM
void mp_uos_deactivate(const char *msg, mp_obj_t exc) {
mp_obj_t term = MP_STATE_PORT(term_obj);
MP_STATE_PORT(term_obj) = NULL;
mp_printf(&mp_plat_print, msg);
if (exc != MP_OBJ_NULL) {
mp_obj_print_exception(&mp_plat_print, exc);
}
mp_stream_close(term);
}
void mp_uos_dupterm_tx_strn(const char *str, size_t len) {
if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) {
nlr_buf_t nlr;
@@ -44,9 +55,7 @@ void mp_uos_dupterm_tx_strn(const char *str, size_t len) {
mp_call_method_n_kw(1, 0, write_m);
nlr_pop();
} else {
MP_STATE_PORT(term_obj) = NULL;
mp_printf(&mp_plat_print, "dupterm: Exception in write() method, deactivating: ");
mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
mp_uos_deactivate("dupterm: Exception in write() method, deactivating: ", nlr.ret_val);
}
}
}

View File

@@ -78,12 +78,12 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, bool server_side) {
STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_ssl_socket_t *self = self_in;
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "<_SSLSocket %p>", self->ssl_sock);
}
STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
mp_obj_ssl_socket_t *o = o_in;
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
while (o->bytes_left == 0) {
mp_int_t r = ssl_read(o->ssl_sock, &o->buf);
@@ -113,7 +113,7 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
}
STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
mp_obj_ssl_socket_t *o = o_in;
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
mp_int_t r = ssl_write(o->ssl_sock, buf, size);
if (r < 0) {
*errcode = r;
@@ -123,7 +123,7 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
}
STATIC mp_obj_t socket_close(mp_obj_t self_in) {
mp_obj_ssl_socket_t *self = self_in;
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
ssl_free(self->ssl_sock);
ssl_ctx_free(self->ssl_ctx);
@@ -133,13 +133,13 @@ STATIC mp_obj_t socket_close(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close);
STATIC const mp_map_elem_t ussl_socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj },
STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readall), MP_ROM_PTR(&mp_stream_readall_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socket_close_obj) },
};
STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table);
@@ -157,10 +157,10 @@ STATIC const mp_obj_type_t ussl_socket_type = {
.getiter = NULL,
.iternext = NULL,
.stream_p = &ussl_socket_stream_p,
.locals_dict = (mp_obj_t)&ussl_socket_locals_dict,
.locals_dict = (void*)&ussl_socket_locals_dict,
};
STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// TODO: Implement more args
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
@@ -175,13 +175,13 @@ STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args,
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
return socket_new(sock, args.server_side.u_bool);
return MP_OBJ_FROM_PTR(socket_new(sock, args.server_side.u_bool));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
STATIC const mp_map_elem_t mp_module_ssl_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ussl) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wrap_socket), (mp_obj_t)&mod_ssl_wrap_socket_obj },
STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) },
{ MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
@@ -195,6 +195,8 @@ const mp_obj_module_t mp_module_ussl = {
// These functions might be split to stream_posix.c. They are referenced by
// axtls os_port.h .
ssize_t mp_stream_posix_write(void *sock_obj, const void *buf, size_t len);
ssize_t mp_stream_posix_read(void *sock_obj, void *buf, size_t len);
int mp_stream_errno;

View File

@@ -250,8 +250,8 @@ STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int
DEBUG_printf("webrepl: Writing %lu bytes to file\n", buf_sz);
int err;
mp_uint_t res = mp_stream_writeall(self->cur_file, filebuf, buf_sz, &err);
if(res == MP_STREAM_ERROR) {
mp_uint_t res = mp_stream_write_exactly(self->cur_file, filebuf, buf_sz, &err);
if (err != 0 || res != buf_sz) {
assert(0);
}
@@ -284,6 +284,13 @@ STATIC mp_uint_t webrepl_write(mp_obj_t self_in, const void *buf, mp_uint_t size
return stream_p->write(self->sock, buf, size, errcode);
}
STATIC mp_obj_t webrepl_close(mp_obj_t self_in) {
mp_obj_webrepl_t *self = MP_OBJ_TO_PTR(self_in);
// TODO: This is a place to do cleanup
return mp_stream_close(self->sock);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(webrepl_close_obj, webrepl_close);
STATIC mp_obj_t webrepl_set_password(mp_obj_t passwd_in) {
mp_uint_t len;
const char *passwd = mp_obj_str_get_data(passwd_in, &len);
@@ -297,6 +304,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(webrepl_set_password_obj, webrepl_set_password)
STATIC const mp_map_elem_t webrepl_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&webrepl_close_obj },
};
STATIC MP_DEFINE_CONST_DICT(webrepl_locals_dict, webrepl_locals_dict_table);

View File

@@ -240,9 +240,9 @@ STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t si
mp_call_method_n_kw(1, 0, dest);
}
mp_uint_t out_sz = mp_stream_writeall(self->sock, header, hdr_sz, errcode);
if (out_sz != MP_STREAM_ERROR) {
out_sz = mp_stream_writeall(self->sock, buf, size, errcode);
mp_uint_t out_sz = mp_stream_write_exactly(self->sock, header, hdr_sz, errcode);
if (*errcode == 0) {
out_sz = mp_stream_write_exactly(self->sock, buf, size, errcode);
}
if (self->opts & BLOCKING_WRITE) {
@@ -250,6 +250,9 @@ STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t si
mp_call_method_n_kw(1, 0, dest);
}
if (*errcode != 0) {
return MP_STREAM_ERROR;
}
return out_sz;
}
@@ -269,10 +272,19 @@ STATIC mp_uint_t websocket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t
}
}
STATIC mp_obj_t websocket_close(mp_obj_t self_in) {
mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
// TODO: Send close signaling to the other side, otherwise it's
// abrupt close (connection abort).
return mp_stream_close(self->sock);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(websocket_close_obj, websocket_close);
STATIC const mp_map_elem_t websocket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ioctl), (mp_obj_t)&mp_stream_ioctl_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&websocket_close_obj },
};
STATIC MP_DEFINE_CONST_DICT(websocket_locals_dict, websocket_locals_dict_table);

View File

@@ -28,12 +28,14 @@
#include "py/mpconfig.h"
#if MICROPY_VFS_FAT
#include <string.h>
#include "py/nlr.h"
#include "py/runtime.h"
#include "lib/fatfs/ff.h"
#include "lib/fatfs/diskio.h"
#include "extmod/vfs_fat_file.h"
#include "fsusermount.h"
#include "extmod/fsusermount.h"
#include "timeutils.h"
#define mp_obj_fat_vfs_t fs_user_mount_t
@@ -79,12 +81,11 @@ STATIC mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) {
const char *path = mp_obj_str_get_str(path_in);
// TODO check that path is actually a file before trying to unlink it
FRESULT res = f_unlink(path);
switch (res) {
case FR_OK:
return mp_const_none;
default:
// TODO: standard errno's
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing file '%s'", path));
if (res == FR_OK) {
return mp_const_none;
} else {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_remove_obj, fat_vfs_remove);
@@ -94,11 +95,11 @@ STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_
const char *old_path = mp_obj_str_get_str(path_in);
const char *new_path = mp_obj_str_get_str(path_out);
FRESULT res = f_rename(old_path, new_path);
switch (res) {
case FR_OK:
return mp_const_none;
default:
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error renaming file '%s' to '%s'", old_path, new_path));
if (res == FR_OK) {
return mp_const_none;
} else {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
}
@@ -108,25 +109,149 @@ STATIC mp_obj_t fat_vfs_mkdir(mp_obj_t vfs_in, mp_obj_t path_o) {
(void)vfs_in;
const char *path = mp_obj_str_get_str(path_o);
FRESULT res = f_mkdir(path);
switch (res) {
case FR_OK:
return mp_const_none;
case FR_EXIST:
// TODO should be FileExistsError
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "File exists: '%s'", path));
default:
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error creating directory '%s'", path));
if (res == FR_OK) {
return mp_const_none;
} else {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_mkdir_obj, fat_vfs_mkdir);
/// Change current directory.
STATIC mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) {
(void)vfs_in;
const char *path;
path = mp_obj_str_get_str(path_in);
FRESULT res = f_chdrive(path);
if (res == FR_OK) {
res = f_chdir(path);
}
if (res != FR_OK) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_chdir_obj, fat_vfs_chdir);
/// Get the current directory.
STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) {
(void)vfs_in;
char buf[MICROPY_ALLOC_PATH_MAX + 1];
FRESULT res = f_getcwd(buf, sizeof buf);
if (res != FR_OK) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
return mp_obj_new_str(buf, strlen(buf), false);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd);
// Checks for path equality, ignoring trailing slashes:
// path_equal(/, /) -> true
// second argument must be in canonical form (meaning no trailing slash, unless it's just /)
STATIC bool path_equal(const char *path, const char *path_canonical) {
while (*path_canonical != '\0' && *path == *path_canonical) {
++path;
++path_canonical;
}
if (*path_canonical != '\0') {
return false;
}
while (*path == '/') {
++path;
}
return *path == '\0';
}
/// \function stat(path)
/// Get the status of a file or directory.
STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
(void)vfs_in;
const char *path = mp_obj_str_get_str(path_in);
FILINFO fno;
#if _USE_LFN
fno.lfname = NULL;
fno.lfsize = 0;
#endif
FRESULT res;
if (path_equal(path, "/")) {
// stat root directory
fno.fsize = 0;
fno.fdate = 0;
fno.ftime = 0;
fno.fattrib = AM_DIR;
} else {
res = FR_NO_PATH;
for (size_t i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount)); ++i) {
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i];
if (vfs != NULL && path_equal(path, vfs->str)) {
// stat mounted device directory
fno.fsize = 0;
fno.fdate = 0;
fno.ftime = 0;
fno.fattrib = AM_DIR;
res = FR_OK;
}
}
if (res == FR_NO_PATH) {
// stat normal file
res = f_stat(path, &fno);
}
if (res != FR_OK) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
}
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
mp_int_t mode = 0;
if (fno.fattrib & AM_DIR) {
mode |= 0x4000; // stat.S_IFDIR
} else {
mode |= 0x8000; // stat.S_IFREG
}
mp_int_t seconds = timeutils_seconds_since_2000(
1980 + ((fno.fdate >> 9) & 0x7f),
(fno.fdate >> 5) & 0x0f,
fno.fdate & 0x1f,
(fno.ftime >> 11) & 0x1f,
(fno.ftime >> 5) & 0x3f,
2 * (fno.ftime & 0x1f)
);
t->items[0] = MP_OBJ_NEW_SMALL_INT(mode); // st_mode
t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino
t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev
t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlink
t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid
t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid
t->items[6] = MP_OBJ_NEW_SMALL_INT(fno.fsize); // st_size
t->items[7] = MP_OBJ_NEW_SMALL_INT(seconds); // st_atime
t->items[8] = MP_OBJ_NEW_SMALL_INT(seconds); // st_mtime
t->items[9] = MP_OBJ_NEW_SMALL_INT(seconds); // st_ctime
return MP_OBJ_FROM_PTR(t);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_stat_obj, fat_vfs_stat);
STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) },
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) },
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&fat_vfs_listdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&fat_vfs_mkdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&fat_vfs_chdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&fat_vfs_getcwd_obj) },
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&fat_vfs_remove_obj) },
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&fat_vfs_rename_obj) },
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&fat_vfs_stat_obj) },
};
STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table);

View File

@@ -35,7 +35,7 @@
#include "lib/fatfs/ff.h"
#include "lib/fatfs/diskio.h"
#include "extmod/vfs_fat_file.h"
#include "fsusermount.h"
#include "extmod/fsusermount.h"
#include "py/lexer.h"
#if _USE_LFN
@@ -54,8 +54,9 @@ mp_obj_t fat_vfs_listdir(const char *path, bool is_str_type) {
res = f_opendir(&dir, path); /* Open the directory */
if (res != FR_OK) {
// TODO should be mp_type_FileNotFoundError
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path));
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
mp_obj_t dir_list = mp_obj_new_list(0, NULL);

39
extmod/virtpin.c Normal file
View File

@@ -0,0 +1,39 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "extmod/virtpin.h"
int mp_virtual_pin_read(mp_obj_t pin) {
mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(pin);
mp_pin_p_t *pin_p = (mp_pin_p_t*)s->type->stream_p;
return pin_p->ioctl(pin, MP_PIN_READ, 0, NULL);
}
void mp_virtual_pin_write(mp_obj_t pin, int value) {
mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(pin);
mp_pin_p_t *pin_p = (mp_pin_p_t*)s->type->stream_p;
pin_p->ioctl(pin, MP_PIN_WRITE, value, NULL);
}

40
extmod/virtpin.h Normal file
View File

@@ -0,0 +1,40 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/obj.h"
#define MP_PIN_READ (1)
#define MP_PIN_WRITE (2)
#define MP_PIN_INPUT (3)
#define MP_PIN_OUTPUT (4)
// Pin protocol
typedef struct _mp_pin_p_t {
mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);
} mp_pin_p_t;
int mp_virtual_pin_read(mp_obj_t pin);
void mp_virtual_pin_write(mp_obj_t pin, int value);

View File

@@ -158,8 +158,8 @@ mp_uint_t timeutils_seconds_since_2000(mp_uint_t year, mp_uint_t month,
+ (year - 2000) * 31536000;
}
mp_uint_t timeutils_mktime(mp_uint_t year, mp_uint_t month, mp_uint_t mday,
mp_uint_t hours, mp_uint_t minutes, mp_uint_t seconds) {
mp_uint_t timeutils_mktime(mp_uint_t year, mp_int_t month, mp_int_t mday,
mp_int_t hours, mp_int_t minutes, mp_int_t seconds) {
// Normalize the tuple. This allows things like:
//
@@ -204,7 +204,7 @@ mp_uint_t timeutils_mktime(mp_uint_t year, mp_uint_t month, mp_uint_t mday,
}
mday += timeutils_days_in_month(year, month);
}
while (mday > timeutils_days_in_month(year, month)) {
while ((mp_uint_t)mday > timeutils_days_in_month(year, month)) {
mday -= timeutils_days_in_month(year, month);
if (++month == 13) {
month = 1;

View File

@@ -49,7 +49,7 @@ void timeutils_seconds_since_2000_to_struct_time(mp_uint_t t,
mp_uint_t timeutils_seconds_since_2000(mp_uint_t year, mp_uint_t month,
mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second);
mp_uint_t timeutils_mktime(mp_uint_t year, mp_uint_t month, mp_uint_t mday,
mp_uint_t hours, mp_uint_t minutes, mp_uint_t seconds);
mp_uint_t timeutils_mktime(mp_uint_t year, mp_int_t month, mp_int_t mday,
mp_int_t hours, mp_int_t minutes, mp_int_t seconds);
#endif // __MICROPY_INCLUDED_LIB_TIMEUTILS_H__

View File

@@ -52,7 +52,7 @@ STATIC void stderr_print_strn(void *env, const char *str, mp_uint_t len) {
STATIC const mp_print_t mp_stderr_print = {NULL, stderr_print_strn};
STATIC int compile_and_save(const char *file, const char *output_file) {
STATIC int compile_and_save(const char *file, const char *output_file, const char *source_file) {
mp_lexer_t *lex = mp_lexer_new_from_file(file);
if (lex == NULL) {
printf("could not open file '%s' for reading\n", file);
@@ -61,7 +61,12 @@ STATIC int compile_and_save(const char *file, const char *output_file) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
qstr source_name = lex->source_name;
qstr source_name;
if (source_file == NULL) {
source_name = lex->source_name;
} else {
source_name = qstr_from_str(source_file);
}
#if MICROPY_PY___FILE__
if (input_kind == MP_PARSE_FILE_INPUT) {
@@ -97,7 +102,8 @@ STATIC int usage(char **argv) {
printf(
"usage: %s [<opts>] [-X <implopt>] <input filename>\n"
"Options:\n"
"-o : output file for compiled bytecode\n"
"-o : output file for compiled bytecode (defaults to input with .mpy extension)\n"
"-s : source filename to embed in the compiled bytecode (defaults to input file)\n"
"-v : verbose (trace various operations); can be multiple\n"
"-O[N] : apply bytecode optimizations of level N\n"
"\n"
@@ -189,6 +195,7 @@ MP_NOINLINE int main_(int argc, char **argv) {
const char *input_file = NULL;
const char *output_file = NULL;
const char *source_file = NULL;
// parse main options
for (int a = 1; a < argc; a++) {
@@ -210,6 +217,12 @@ MP_NOINLINE int main_(int argc, char **argv) {
}
a += 1;
output_file = argv[a];
} else if (strcmp(argv[a], "-s") == 0) {
if (a + 1 >= argc) {
exit(usage(argv));
}
a += 1;
source_file = argv[a];
} else if (strncmp(argv[a], "-msmall-int-bits=", sizeof("-msmall-int-bits=") - 1) == 0) {
char *end;
mp_dynamic_compiler.small_int_bits =
@@ -243,7 +256,7 @@ MP_NOINLINE int main_(int argc, char **argv) {
exit(1);
}
int ret = compile_and_save(input_file, output_file);
int ret = compile_and_save(input_file, output_file, source_file);
#if MICROPY_PY_MICROPYTHON_MEM_INFO
if (mp_verbose_flag) {

View File

@@ -98,6 +98,7 @@ extern const mp_obj_module_t mp_module_gc;
extern const mp_obj_dict_t mp_module_builtins_globals;
// extmod modules
extern const mp_obj_module_t mp_module_uerrno;
extern const mp_obj_module_t mp_module_uctypes;
extern const mp_obj_module_t mp_module_uzlib;
extern const mp_obj_module_t mp_module_ujson;

View File

@@ -60,22 +60,34 @@ bool mp_obj_is_package(mp_obj_t module) {
return dest[0] != MP_OBJ_NULL;
}
// Stat either frozen or normal module by a given path
// (whatever is available, if at all).
STATIC mp_import_stat_t mp_import_stat_any(const char *path) {
#if MICROPY_MODULE_FROZEN
mp_import_stat_t st = mp_frozen_stat(path);
if (st != MP_IMPORT_STAT_NO_EXIST) {
return st;
}
#endif
return mp_import_stat(path);
}
STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) {
mp_import_stat_t stat = mp_import_stat(vstr_null_terminated_str(path));
mp_import_stat_t stat = mp_import_stat_any(vstr_null_terminated_str(path));
DEBUG_printf("stat %s: %d\n", vstr_str(path), stat);
if (stat == MP_IMPORT_STAT_DIR) {
return stat;
}
vstr_add_str(path, ".py");
stat = mp_import_stat(vstr_null_terminated_str(path));
stat = mp_import_stat_any(vstr_null_terminated_str(path));
if (stat == MP_IMPORT_STAT_FILE) {
return stat;
}
#if MICROPY_PERSISTENT_CODE_LOAD
vstr_ins_byte(path, path->len - 2, 'm');
stat = mp_import_stat(vstr_null_terminated_str(path));
stat = mp_import_stat_any(vstr_null_terminated_str(path));
if (stat == MP_IMPORT_STAT_FILE) {
return stat;
}
@@ -182,10 +194,37 @@ STATIC void do_execute_raw_code(mp_obj_t module_obj, mp_raw_code_t *raw_code) {
#endif
STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
#if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_ENABLE_COMPILER
#if MICROPY_MODULE_FROZEN || MICROPY_PERSISTENT_CODE_LOAD || MICROPY_ENABLE_COMPILER
char *file_str = vstr_null_terminated_str(file);
#endif
// If we support frozen modules (either as str or mpy) then try to find the
// requested filename in the list of frozen module filenames.
#if MICROPY_MODULE_FROZEN
void *modref;
int frozen_type = mp_find_frozen_module(file_str, file->len, &modref);
#endif
// If we support frozen str modules and the compiler is enabled, and we
// found the filename in the list of frozen files, then load and execute it.
#if MICROPY_MODULE_FROZEN_STR
if (frozen_type == MP_FROZEN_STR) {
do_load_from_lexer(module_obj, modref, file_str);
return;
}
#endif
// If we support frozen mpy modules and we found a corresponding file (and
// its data) in the list of frozen files, execute it.
#if MICROPY_MODULE_FROZEN_MPY
if (frozen_type == MP_FROZEN_MPY) {
do_execute_raw_code(module_obj, modref);
return;
}
#endif
// If we support loading .mpy files then check if the file extension is of
// the correct format and, if so, load and execute the file.
#if MICROPY_PERSISTENT_CODE_LOAD
if (file_str[file->len - 3] == 'm') {
mp_raw_code_t *raw_code = mp_raw_code_load_file(file_str);
@@ -194,15 +233,18 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
}
#endif
// If we can compile scripts then load the file and compile and execute it.
#if MICROPY_ENABLE_COMPILER
{
mp_lexer_t *lex = mp_lexer_new_from_file(file_str);
do_load_from_lexer(module_obj, lex, file_str);
return;
}
#else
#endif
// If we get here then the file was not frozen and we can't compile scripts.
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
"script compilation not supported"));
#endif
}
STATIC void chop_component(const char *start, const char **end) {
@@ -340,33 +382,6 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
}
DEBUG_printf("Module not yet loaded\n");
#if MICROPY_MODULE_FROZEN
void *frozen_data;
int frozen_type = mp_find_frozen_module(mod_str, mod_len, &frozen_data);
if (frozen_type != MP_FROZEN_NONE) {
module_obj = mp_obj_new_module(module_name_qstr);
// if args[3] (fromtuple) has magic value False, set up
// this module for command-line "-m" option (set module's
// name to __main__ instead of real name).
// TODO: Duplicated below too.
if (fromtuple == mp_const_false) {
mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj);
mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
}
#if MICROPY_MODULE_FROZEN_STR
if (frozen_type == MP_FROZEN_STR) {
do_load_from_lexer(module_obj, frozen_data, mod_str);
}
#endif
#if MICROPY_MODULE_FROZEN_MPY
if (frozen_type == MP_FROZEN_MPY) {
do_execute_raw_code(module_obj, frozen_data);
}
#endif
return module_obj;
}
#endif
uint last = 0;
VSTR_FIXED(path, MICROPY_ALLOC_PATH_MAX)
module_obj = MP_OBJ_NULL;
@@ -445,7 +460,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path), false));
vstr_add_char(&path, PATH_SEP_CHAR);
vstr_add_str(&path, "__init__.py");
if (mp_import_stat(vstr_null_terminated_str(&path)) != MP_IMPORT_STAT_FILE) {
if (mp_import_stat_any(vstr_null_terminated_str(&path)) != MP_IMPORT_STAT_FILE) {
vstr_cut_tail_bytes(&path, sizeof("/__init__.py") - 1); // cut off /__init__.py
mp_warning("%s is imported as namespace package", vstr_str(&path));
} else {

View File

@@ -2649,7 +2649,7 @@ STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns)
}
typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
STATIC compile_function_t compile_function[] = {
STATIC const compile_function_t compile_function[] = {
#define nc NULL
#define c(f) compile_##f
#define DEF_RULE(rule, comp, kind, ...) comp,

View File

@@ -381,7 +381,7 @@ mp_raw_code_t *mp_raw_code_load_mem(const byte *buf, size_t len) {
// here we define mp_raw_code_load_file depending on the port
// TODO abstract this away properly
#if defined(__i386__) || defined(__x86_64__) || (defined(__arm__) && (defined(__unix__)))
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || (defined(__arm__) && (defined(__unix__)))
// unix file reader
#include <sys/stat.h>

View File

@@ -85,6 +85,43 @@ STATIC const mp_raw_code_t *mp_find_frozen_mpy(const char *str, size_t len) {
#if MICROPY_MODULE_FROZEN
STATIC mp_import_stat_t mp_frozen_stat_helper(const char *name, const char *str) {
size_t len = strlen(str);
for (int i = 0; *name != 0; i++) {
size_t l = strlen(name);
if (l >= len && !memcmp(str, name, len)) {
if (name[len] == 0) {
return MP_IMPORT_STAT_FILE;
} else if (name[len] == '/') {
return MP_IMPORT_STAT_DIR;
}
}
name += l + 1;
}
return MP_IMPORT_STAT_NO_EXIST;
}
mp_import_stat_t mp_frozen_stat(const char *str) {
mp_import_stat_t stat;
#if MICROPY_MODULE_FROZEN_STR
stat = mp_frozen_stat_helper(mp_frozen_str_names, str);
if (stat != MP_IMPORT_STAT_NO_EXIST) {
return stat;
}
#endif
#if MICROPY_MODULE_FROZEN_MPY
stat = mp_frozen_stat_helper(mp_frozen_mpy_names, str);
if (stat != MP_IMPORT_STAT_NO_EXIST) {
return stat;
}
#endif
return MP_IMPORT_STAT_NO_EXIST;
}
int mp_find_frozen_module(const char *str, size_t len, void **data) {
#if MICROPY_MODULE_FROZEN_STR
mp_lexer_t *lex = mp_find_frozen_str(str, len);

View File

@@ -31,3 +31,4 @@ enum {
};
int mp_find_frozen_module(const char *str, size_t len, void **data);
mp_import_stat_t mp_frozen_stat(const char *str);

14
py/gc.c
View File

@@ -693,11 +693,8 @@ void gc_dump_alloc_table(void) {
}
// print header for new line of blocks
// (the cast to uint32_t is for 16-bit ports)
#if EXTENSIVE_HEAP_PROFILING
//mp_printf(&mp_plat_print, "\n%05x: ", (uint)(PTR_FROM_BLOCK(bl) & (uint32_t)0xfffff));
mp_printf(&mp_plat_print, "\n%05x: ", (uint)((bl * BYTES_PER_BLOCK) & (uint32_t)0xfffff));
#else
mp_printf(&mp_plat_print, "\n%05x: ", (uint)(PTR_FROM_BLOCK(bl) & (uint32_t)0xfffff));
#endif
}
int c = ' ';
switch (ATB_GET_KIND(bl)) {
@@ -734,6 +731,13 @@ void gc_dump_alloc_table(void) {
if (*ptr == &mp_type_tuple) { c = 'T'; }
else if (*ptr == &mp_type_list) { c = 'L'; }
else if (*ptr == &mp_type_dict) { c = 'D'; }
else if (*ptr == &mp_type_str || *ptr == &mp_type_bytes) { c = 'S'; }
#if MICROPY_PY_BUILTINS_BYTEARRAY
else if (*ptr == &mp_type_bytearray) { c = 'A'; }
#endif
#if MICROPY_PY_ARRAY
else if (*ptr == &mp_type_array) { c = 'A'; }
#endif
#if MICROPY_PY_BUILTINS_FLOAT
else if (*ptr == &mp_type_float) { c = 'F'; }
#endif
@@ -761,7 +765,7 @@ void gc_dump_alloc_table(void) {
}
break;
}
case AT_TAIL: c = 't'; break;
case AT_TAIL: c = '='; break;
case AT_MARK: c = 'm'; break;
}
mp_printf(&mp_plat_print, "%c", c);

View File

@@ -190,7 +190,7 @@ STATIC void indent_pop(mp_lexer_t *lex) {
// c<op> = continue with <op>, if this opchar matches then continue matching
// this means if the start of two ops are the same then they are equal til the last char
STATIC const char *tok_enc =
STATIC const char *const tok_enc =
"()[]{},:;@~" // singles
"<e=c<e=" // < <= << <<=
">e=c>e=" // > >= >> >>=
@@ -227,7 +227,7 @@ STATIC const uint8_t tok_enc_kind[] = {
};
// must have the same order as enum in lexer.h
STATIC const char *tok_kw[] = {
STATIC const char *const tok_kw[] = {
"False",
"None",
"True",

View File

@@ -116,7 +116,7 @@ def parse_input_headers(infiles):
def make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr):
qhash = compute_hash(qstr, cfg_bytes_hash)
if all(32 <= ord(c) <= 126 and c != '\\' for c in qstr):
if all(32 <= ord(c) <= 126 and c != '\\' and c != '"' for c in qstr):
# qstr is all printable ASCII so render it as-is (for easier debugging)
qlen = len(qstr)
qdata = qstr

View File

@@ -49,7 +49,7 @@ const mp_map_t mp_const_empty_map = {
// The first set of sizes are chosen so the allocation fits exactly in a
// 4-word GC block, and it's not so important for these small values to be
// prime. The latter sizes are prime and increase at an increasing rate.
STATIC uint16_t hash_allocation_sizes[] = {
STATIC const uint16_t hash_allocation_sizes[] = {
0, 2, 4, 6, 8, 10, 12, // +2
17, 23, 29, 37, 47, 59, 73, // *1.25
97, 127, 167, 223, 293, 389, 521, 691, 919, 1223, 1627, 2161, // *1.33

View File

@@ -78,10 +78,13 @@ STATIC mp_uint_t bufwriter_write(mp_obj_t self_in, const void *buf, mp_uint_t si
memcpy(self->buf + self->len, buf, rem);
buf = (byte*)buf + rem;
size -= rem;
mp_uint_t out_sz = mp_stream_writeall(self->stream, self->buf, self->alloc, errcode);
if (out_sz == MP_STREAM_ERROR) {
mp_uint_t out_sz = mp_stream_write_exactly(self->stream, self->buf, self->alloc, errcode);
if (*errcode != 0) {
return MP_STREAM_ERROR;
}
// TODO: try to recover from a case of non-blocking stream, e.g. move
// remaining chunk to the beginning of buffer.
assert(out_sz == self->alloc);
self->len = 0;
}
@@ -93,9 +96,12 @@ STATIC mp_obj_t bufwriter_flush(mp_obj_t self_in) {
if (self->len != 0) {
int err;
mp_uint_t out_sz = mp_stream_writeall(self->stream, self->buf, self->len, &err);
mp_uint_t out_sz = mp_stream_write_exactly(self->stream, self->buf, self->len, &err);
// TODO: try to recover from a case of non-blocking stream, e.g. move
// remaining chunk to the beginning of buffer.
assert(out_sz == self->len);
self->len = 0;
if (out_sz == MP_STREAM_ERROR) {
if (err != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(err)));
}
}

View File

@@ -31,6 +31,11 @@
#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
/// \module math - mathematical functions
///
/// The `math` module provides some basic mathematical funtions for

View File

@@ -103,29 +103,24 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
char fmt_type = get_fmt_type(&fmt);
mp_uint_t size;
for (size = 0; *fmt; fmt++) {
mp_uint_t align = 1;
mp_uint_t cnt = 1;
if (unichar_isdigit(*fmt)) {
cnt = get_fmt_num(&fmt);
}
mp_uint_t sz = 0;
if (*fmt == 's') {
sz = cnt;
cnt = 1;
}
while (cnt--) {
// If we already have size for 's' case, don't set it again
size += cnt;
} else {
mp_uint_t align;
size_t sz = mp_binary_get_size(fmt_type, *fmt, &align);
if (sz == 0) {
sz = (mp_uint_t)mp_binary_get_size(fmt_type, *fmt, &align);
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "unsupported format"));
}
while (cnt--) {
// Apply alignment
size = (size + align - 1) & ~(align - 1);
size += sz;
}
// TODO
assert(sz != (mp_uint_t)-1);
// Apply alignment
size = (size + align - 1) & ~(align - 1);
size += sz;
sz = 0;
}
}
return MP_OBJ_NEW_SMALL_INT(size);

105
py/moduerrno.c Normal file
View File

@@ -0,0 +1,105 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <assert.h>
#include <string.h>
#include "py/obj.h"
#include "py/mperrno.h"
#if MICROPY_PY_UERRNO
// This list could be defined per port in mpconfigport.h to tailor it to a
// specific port's needs. But for now we have a common list.
#define ERRNO_LIST \
X(EPERM) \
X(ENOENT) \
X(EIO) \
X(EBADF) \
X(EAGAIN) \
X(ENOMEM) \
X(EACCES) \
X(EEXIST) \
X(ENODEV) \
X(EISDIR) \
X(EINVAL) \
X(EOPNOTSUPP) \
X(EADDRINUSE) \
X(ECONNABORTED) \
X(ECONNRESET) \
X(ENOBUFS) \
X(ENOTCONN) \
X(ETIMEDOUT) \
X(ECONNREFUSED) \
X(EHOSTUNREACH) \
X(EALREADY) \
X(EINPROGRESS) \
STATIC const mp_rom_map_elem_t errorcode_table[] = {
#define X(e) { MP_ROM_INT(MP_ ## e), MP_ROM_QSTR(MP_QSTR_## e) },
ERRNO_LIST
#undef X
};
STATIC const mp_obj_dict_t errorcode_dict = {
.base = {&mp_type_dict},
.map = {
.all_keys_are_qstrs = 0, // keys are integers
.is_fixed = 1,
.is_ordered = 1,
.used = MP_ARRAY_SIZE(errorcode_table),
.alloc = MP_ARRAY_SIZE(errorcode_table),
.table = (mp_map_elem_t*)(mp_rom_map_elem_t*)errorcode_table,
},
};
STATIC const mp_rom_map_elem_t mp_module_uerrno_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uerrno) },
{ MP_ROM_QSTR(MP_QSTR_errorcode), MP_ROM_PTR(&errorcode_dict) },
#define X(e) { MP_ROM_QSTR(MP_QSTR_## e), MP_ROM_INT(MP_ ## e) },
ERRNO_LIST
#undef X
};
STATIC MP_DEFINE_CONST_DICT(mp_module_uerrno_globals, mp_module_uerrno_globals_table);
const mp_obj_module_t mp_module_uerrno = {
.base = { &mp_type_module },
.name = MP_QSTR_uerrno,
.globals = (mp_obj_dict_t*)&mp_module_uerrno_globals,
};
qstr mp_errno_to_str(mp_obj_t errno_val) {
mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&errorcode_dict.map, errno_val, MP_MAP_LOOKUP);
if (elem == NULL) {
return MP_QSTR_NULL;
} else {
return MP_OBJ_QSTR_VALUE(elem->value);
}
}
#endif //MICROPY_PY_UERRNO

View File

@@ -555,6 +555,11 @@ typedef double mp_float_t;
#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (1)
#endif
// Whether to use internally defined errno's (otherwise system provided ones)
#ifndef MICROPY_USE_INTERNAL_ERRNO
#define MICROPY_USE_INTERNAL_ERRNO (0)
#endif
// Support for user-space VFS mount (selected ports)
#ifndef MICROPY_FSUSERMOUNT
#define MICROPY_FSUSERMOUNT (0)
@@ -584,6 +589,11 @@ typedef double mp_float_t;
#define MICROPY_PY_BUILTINS_STR_UNICODE (0)
#endif
// Whether str.center() method provided
#ifndef MICROPY_PY_BUILTINS_STR_CENTER
#define MICROPY_PY_BUILTINS_STR_CENTER (0)
#endif
// Whether str.splitlines() method provided
#ifndef MICROPY_PY_BUILTINS_STR_SPLITLINES
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (0)
@@ -809,6 +819,11 @@ typedef double mp_float_t;
#define MICROPY_PY_SYS_STDIO_BUFFER (0)
#endif
// Whether to provide "uerrno" module
#ifndef MICROPY_PY_UERRNO
#define MICROPY_PY_UERRNO (0)
#endif
// Extended modules
#ifndef MICROPY_PY_UCTYPES
@@ -852,6 +867,11 @@ typedef double mp_float_t;
#define MICROPY_PY_MACHINE (0)
#endif
// Whether to include: time_pulse_us
#ifndef MICROPY_PY_MACHINE_PULSE
#define MICROPY_PY_MACHINE_PULSE (0)
#endif
#ifndef MICROPY_PY_MACHINE_I2C
#define MICROPY_PY_MACHINE_I2C (0)
#endif

143
py/mperrno.h Normal file
View File

@@ -0,0 +1,143 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __MICROPY_INCLUDED_PY_MPERRNO_H__
#define __MICROPY_INCLUDED_PY_MPERRNO_H__
#if MICROPY_USE_INTERNAL_ERRNO
// MP_Exxx errno's are defined directly as numeric values
// (Linux constants are used as a reference)
#define MP_EPERM (1) // Operation not permitted
#define MP_ENOENT (2) // No such file or directory
#define MP_ESRCH (3) // No such process
#define MP_EINTR (4) // Interrupted system call
#define MP_EIO (5) // I/O error
#define MP_ENXIO (6) // No such device or address
#define MP_E2BIG (7) // Argument list too long
#define MP_ENOEXEC (8) // Exec format error
#define MP_EBADF (9) // Bad file number
#define MP_ECHILD (10) // No child processes
#define MP_EAGAIN (11) // Try again
#define MP_ENOMEM (12) // Out of memory
#define MP_EACCES (13) // Permission denied
#define MP_EFAULT (14) // Bad address
#define MP_ENOTBLK (15) // Block device required
#define MP_EBUSY (16) // Device or resource busy
#define MP_EEXIST (17) // File exists
#define MP_EXDEV (18) // Cross-device link
#define MP_ENODEV (19) // No such device
#define MP_ENOTDIR (20) // Not a directory
#define MP_EISDIR (21) // Is a directory
#define MP_EINVAL (22) // Invalid argument
#define MP_ENFILE (23) // File table overflow
#define MP_EMFILE (24) // Too many open files
#define MP_ENOTTY (25) // Not a typewriter
#define MP_ETXTBSY (26) // Text file busy
#define MP_EFBIG (27) // File too large
#define MP_ENOSPC (28) // No space left on device
#define MP_ESPIPE (29) // Illegal seek
#define MP_EROFS (30) // Read-only file system
#define MP_EMLINK (31) // Too many links
#define MP_EPIPE (32) // Broken pipe
#define MP_EDOM (33) // Math argument out of domain of func
#define MP_ERANGE (34) // Math result not representable
#define MP_EWOULDBLOCK MP_EAGAIN // Operation would block
#define MP_EOPNOTSUPP (95) // Operation not supported on transport endpoint
#define MP_EAFNOSUPPORT (97) // Address family not supported by protocol
#define MP_EADDRINUSE (98) // Address already in use
#define MP_ECONNABORTED (103) // Software caused connection abort
#define MP_ECONNRESET (104) // Connection reset by peer
#define MP_ENOBUFS (105) // No buffer space available
#define MP_ENOTCONN (107) // Transport endpoint is not connected
#define MP_ETIMEDOUT (110) // Connection timed out
#define MP_ECONNREFUSED (111) // Connection refused
#define MP_EHOSTUNREACH (113) // No route to host
#define MP_EALREADY (114) // Operation already in progress
#define MP_EINPROGRESS (115) // Operation now in progress
#else
// MP_Exxx errno's are defined in terms of system supplied ones
#include <errno.h>
#define MP_EPERM EPERM
#define MP_ENOENT ENOENT
#define MP_ESRCH ESRCH
#define MP_EINTR EINTR
#define MP_EIO EIO
#define MP_ENXIO ENXIO
#define MP_E2BIG E2BIG
#define MP_ENOEXEC ENOEXEC
#define MP_EBADF EBADF
#define MP_ECHILD ECHILD
#define MP_EAGAIN EAGAIN
#define MP_ENOMEM ENOMEM
#define MP_EACCES EACCES
#define MP_EFAULT EFAULT
#define MP_ENOTBLK ENOTBLK
#define MP_EBUSY EBUSY
#define MP_EEXIST EEXIST
#define MP_EXDEV EXDEV
#define MP_ENODEV ENODEV
#define MP_ENOTDIR ENOTDIR
#define MP_EISDIR EISDIR
#define MP_EINVAL EINVAL
#define MP_ENFILE ENFILE
#define MP_EMFILE EMFILE
#define MP_ENOTTY ENOTTY
#define MP_ETXTBSY ETXTBSY
#define MP_EFBIG EFBIG
#define MP_ENOSPC ENOSPC
#define MP_ESPIPE ESPIPE
#define MP_EROFS EROFS
#define MP_EMLINK EMLINK
#define MP_EPIPE EPIPE
#define MP_EDOM EDOM
#define MP_ERANGE ERANGE
#define MP_EWOULDBLOCK EAGAIN
#define MP_EOPNOTSUPP EOPNOTSUPP
#define MP_EAFNOSUPPORT EAFNOSUPPORT
#define MP_EADDRINUSE EADDRINUSE
#define MP_ECONNABORTED ECONNABORTED
#define MP_ECONNRESET ECONNRESET
#define MP_ENOBUFS ENOBUFS
#define MP_ENOTCONN ENOTCONN
#define MP_ETIMEDOUT ETIMEDOUT
#define MP_ECONNREFUSED ECONNREFUSED
#define MP_EHOSTUNREACH EHOSTUNREACH
#define MP_EALREADY EALREADY
#define MP_EINPROGRESS EINPROGRESS
#endif
#if MICROPY_PY_UERRNO
qstr mp_errno_to_str(mp_obj_t errno_val);
#endif
#endif // __MICROPY_INCLUDED_PY_MPERRNO_H__

View File

@@ -54,8 +54,25 @@ void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len);
void mp_hal_delay_ms(mp_uint_t ms);
#endif
#ifndef mp_hal_delay_us
void mp_hal_delay_us(mp_uint_t us);
#endif
#ifndef mp_hal_ticks_ms
mp_uint_t mp_hal_ticks_ms(void);
#endif
#ifndef mp_hal_ticks_us
mp_uint_t mp_hal_ticks_us(void);
#endif
// If port HAL didn't define its own pin API, use generic
// "virtual pin" API from the core.
#ifndef mp_hal_pin_obj_t
#define mp_hal_pin_obj_t mp_obj_t
#define mp_hal_get_pin_obj(pin) (pin)
#define mp_hal_pin_read(pin) mp_virtual_pin_read(pin)
#define mp_hal_pin_write(pin, v) mp_virtual_pin_write(pin, v)
#endif
#endif // __MICROPY_INCLUDED_PY_MPHAL_H__

View File

@@ -454,10 +454,8 @@ STATIC mp_uint_t mpn_mul(mpz_dig_t *idig, mpz_dig_t *jdig, mp_uint_t jlen, mpz_d
assumes num_dig has enough memory to be extended by 1 digit
assumes quo_dig has enough memory (as many digits as num)
assumes quo_dig is filled with zeros
modifies den_dig memory, but restors it to original state at end
*/
STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig, mp_uint_t den_len, mpz_dig_t *quo_dig, mp_uint_t *quo_len) {
STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, const mpz_dig_t *den_dig, mp_uint_t den_len, mpz_dig_t *quo_dig, mp_uint_t *quo_len) {
mpz_dig_t *orig_num_dig = num_dig;
mpz_dig_t *orig_quo_dig = quo_dig;
mpz_dig_t norm_shift = 0;
@@ -478,6 +476,11 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
}
}
// We need to normalise the denominator (leading bit of leading digit is 1)
// so that the division routine works. Since the denominator memory is
// read-only we do the normalisation on the fly, each time a digit of the
// denominator is needed. We need to know is how many bits to shift by.
// count number of leading zeros in leading digit of denominator
{
mpz_dig_t d = den_dig[den_len - 1];
@@ -487,13 +490,6 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
}
}
// normalise denomenator (leading bit of leading digit is 1)
for (mpz_dig_t *den = den_dig, carry = 0; den < den_dig + den_len; ++den) {
mpz_dig_t d = *den;
*den = ((d << norm_shift) | carry) & DIG_MASK;
carry = d >> (DIG_SIZE - norm_shift);
}
// now need to shift numerator by same amount as denominator
// first, increase length of numerator in case we need more room to shift
num_dig[*num_len] = 0;
@@ -501,11 +497,14 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
for (mpz_dig_t *num = num_dig, carry = 0; num < num_dig + *num_len; ++num) {
mpz_dig_t n = *num;
*num = ((n << norm_shift) | carry) & DIG_MASK;
carry = n >> (DIG_SIZE - norm_shift);
carry = (mpz_dbl_dig_t)n >> (DIG_SIZE - norm_shift);
}
// cache the leading digit of the denominator
lead_den_digit = den_dig[den_len - 1];
lead_den_digit = (mpz_dbl_dig_t)den_dig[den_len - 1] << norm_shift;
if (den_len >= 2) {
lead_den_digit |= (mpz_dbl_dig_t)den_dig[den_len - 2] >> (DIG_SIZE - norm_shift);
}
// point num_dig to last digit in numerator
num_dig += *num_len - 1;
@@ -540,10 +539,13 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
// round up).
if (DIG_SIZE < 8 * sizeof(mpz_dbl_dig_t) / 2) {
const mpz_dig_t *d = den_dig;
mpz_dbl_dig_t d_norm = 0;
mpz_dbl_dig_signed_t borrow = 0;
for (mpz_dig_t *n = num_dig - den_len, *d = den_dig; n < num_dig; ++n, ++d) {
borrow += (mpz_dbl_dig_t)*n - (mpz_dbl_dig_t)quo * (mpz_dbl_dig_t)*d; // will overflow if DIG_SIZE >= 8*sizeof(mpz_dbl_dig_t)/2
for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {
d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);
borrow += (mpz_dbl_dig_t)*n - (mpz_dbl_dig_t)quo * (d_norm & DIG_MASK); // will overflow if DIG_SIZE >= 8*sizeof(mpz_dbl_dig_t)/2
*n = borrow & DIG_MASK;
borrow >>= DIG_SIZE;
}
@@ -553,9 +555,12 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
// adjust quotient if it is too big
for (; borrow != 0; --quo) {
d = den_dig;
d_norm = 0;
mpz_dbl_dig_t carry = 0;
for (mpz_dig_t *n = num_dig - den_len, *d = den_dig; n < num_dig; ++n, ++d) {
carry += (mpz_dbl_dig_t)*n + (mpz_dbl_dig_t)*d;
for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {
d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);
carry += (mpz_dbl_dig_t)*n + (d_norm & DIG_MASK);
*n = carry & DIG_MASK;
carry >>= DIG_SIZE;
}
@@ -566,10 +571,13 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
borrow += carry;
}
} else { // DIG_SIZE == 8 * sizeof(mpz_dbl_dig_t) / 2
const mpz_dig_t *d = den_dig;
mpz_dbl_dig_t d_norm = 0;
mpz_dbl_dig_t borrow = 0;
for (mpz_dig_t *n = num_dig - den_len, *d = den_dig; n < num_dig; ++n, ++d) {
mpz_dbl_dig_t x = (mpz_dbl_dig_t)quo * (mpz_dbl_dig_t)(*d);
for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {
d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);
mpz_dbl_dig_t x = (mpz_dbl_dig_t)quo * (d_norm & DIG_MASK);
if (x >= *n || *n - x <= borrow) {
borrow += (mpz_dbl_dig_t)x - (mpz_dbl_dig_t)*n;
*n = (-borrow) & DIG_MASK;
@@ -590,9 +598,12 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
// adjust quotient if it is too big
for (; borrow != 0; --quo) {
d = den_dig;
d_norm = 0;
mpz_dbl_dig_t carry = 0;
for (mpz_dig_t *n = num_dig - den_len, *d = den_dig; n < num_dig; ++n, ++d) {
carry += (mpz_dbl_dig_t)*n + (mpz_dbl_dig_t)*d;
for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {
d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);
carry += (mpz_dbl_dig_t)*n + (d_norm & DIG_MASK);
*n = carry & DIG_MASK;
carry >>= DIG_SIZE;
}
@@ -614,18 +625,11 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
--(*num_len);
}
// unnormalise denomenator
for (mpz_dig_t *den = den_dig + den_len - 1, carry = 0; den >= den_dig; --den) {
mpz_dig_t d = *den;
*den = ((d >> norm_shift) | carry) & DIG_MASK;
carry = d << (DIG_SIZE - norm_shift);
}
// unnormalise numerator (remainder now)
for (mpz_dig_t *num = orig_num_dig + *num_len - 1, carry = 0; num >= orig_num_dig; --num) {
mpz_dig_t n = *num;
*num = ((n >> norm_shift) | carry) & DIG_MASK;
carry = n << (DIG_SIZE - norm_shift);
carry = (mpz_dbl_dig_t)n << (DIG_SIZE - norm_shift);
}
// strip trailing zeros
@@ -1506,11 +1510,16 @@ void mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const m
dest_quo->len = 0;
mpz_need_dig(dest_rem, lhs->len + 1); // +1 necessary?
mpz_set(dest_rem, lhs);
//rhs->dig[rhs->len] = 0;
mpn_div(dest_rem->dig, &dest_rem->len, rhs->dig, rhs->len, dest_quo->dig, &dest_quo->len);
// check signs and do Python style modulo
if (lhs->neg != rhs->neg) {
dest_quo->neg = 1;
if (!mpz_is_zero(dest_rem)) {
mpz_t mpzone; mpz_init_from_int(&mpzone, -1);
mpz_add_inpl(dest_quo, dest_quo, &mpzone);
mpz_add_inpl(dest_rem, dest_rem, rhs);
}
}
}

View File

@@ -317,6 +317,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
#endif
#endif
// note: returned value in *items may point to the interior of a GC block
void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items) {
if (MP_OBJ_IS_TYPE(o, &mp_type_tuple)) {
mp_obj_tuple_get(o, len, items);
@@ -333,6 +334,7 @@ void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items) {
}
}
// note: returned value in *items may point to the interior of a GC block
void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items) {
mp_uint_t seq_len;
mp_obj_get_array(o, &seq_len, items);

View File

@@ -651,8 +651,8 @@ mp_float_t mp_obj_get_float(mp_obj_t self_in);
void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
#endif
//qstr mp_obj_get_qstr(mp_obj_t arg);
void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items);
void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items);
void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items); // *items may point inside a GC block
void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items); // *items may point inside a GC block
mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, bool is_slice);
mp_obj_t mp_obj_id(mp_obj_t o_in);
mp_obj_t mp_obj_len(mp_obj_t o_in);

View File

@@ -414,7 +414,7 @@ typedef enum _mp_dict_view_kind_t {
MP_DICT_VIEW_VALUES,
} mp_dict_view_kind_t;
STATIC char *mp_dict_view_names[] = {"dict_items", "dict_keys", "dict_values"};
STATIC const char *const mp_dict_view_names[] = {"dict_items", "dict_keys", "dict_values"};
typedef struct _mp_obj_dict_view_it_t {
mp_obj_base_t base;

View File

@@ -36,6 +36,7 @@
#include "py/objtype.h"
#include "py/runtime.h"
#include "py/gc.h"
#include "py/mperrno.h"
// Instance of MemoryError exception - needed by mp_malloc_fail
const mp_obj_exception_t mp_const_MemoryError_obj = {{&mp_type_MemoryError}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj};
@@ -107,6 +108,16 @@ STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr
mp_print_str(print, "");
return;
} else if (o->args->len == 1) {
#if MICROPY_PY_UERRNO
// try to provide a nice OSError error message
if (o->base.type == &mp_type_OSError && MP_OBJ_IS_SMALL_INT(o->args->items[0])) {
qstr qst = mp_errno_to_str(o->args->items[0]);
if (qst != MP_QSTR_NULL) {
mp_printf(print, "[Errno %d] %q", MP_OBJ_SMALL_INT_VALUE(o->args->items[0]), qst);
return;
}
}
#endif
mp_obj_print_helper(print, o->args->items[0], PRINT_STR);
return;
}

View File

@@ -41,6 +41,14 @@
#if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D
// M_E and M_PI are not part of the math.h standard and may not be defined
#ifndef M_E
#define M_E (2.7182818284590452354)
#endif
#ifndef M_PI
#define M_PI (3.14159265358979323846)
#endif
typedef struct _mp_obj_float_t {
mp_obj_base_t base;
mp_float_t value;

View File

@@ -239,12 +239,6 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
}
mpz_t rem; mpz_init_zero(&rem);
mpz_divmod_inpl(&res->mpz, &rem, zlhs, zrhs);
if (zlhs->neg != zrhs->neg) {
if (!mpz_is_zero(&rem)) {
mpz_t mpzone; mpz_init_from_int(&mpzone, -1);
mpz_add_inpl(&res->mpz, &res->mpz, &mpzone);
}
}
mpz_deinit(&rem);
break;
}
@@ -256,10 +250,6 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mpz_t quo; mpz_init_zero(&quo);
mpz_divmod_inpl(&quo, &res->mpz, zlhs, zrhs);
mpz_deinit(&quo);
// Check signs and do Python style modulo
if (zlhs->neg != zrhs->neg) {
mpz_add_inpl(&res->mpz, &res->mpz, zrhs);
}
break;
}
@@ -303,10 +293,6 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
}
mp_obj_int_t *quo = mp_obj_int_new_mpz();
mpz_divmod_inpl(&quo->mpz, &res->mpz, zlhs, zrhs);
// Check signs and do Python style modulo
if (zlhs->neg != zrhs->neg) {
mpz_add_inpl(&res->mpz, &res->mpz, zrhs);
}
mp_obj_t tuple[2] = {MP_OBJ_FROM_PTR(quo), MP_OBJ_FROM_PTR(res)};
return mp_obj_new_tuple(2, tuple);
}

View File

@@ -163,6 +163,9 @@ STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = {
// extmod modules
#if MICROPY_PY_UERRNO
{ MP_ROM_QSTR(MP_QSTR_uerrno), MP_ROM_PTR(&mp_module_uerrno) },
#endif
#if MICROPY_PY_UCTYPES
{ MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) },
#endif

View File

@@ -165,10 +165,7 @@ STATIC mp_obj_t new_namedtuple_type(mp_obj_t name_in, mp_obj_t fields_in) {
fields_in = mp_obj_str_split(1, &fields_in);
}
#endif
if (!MP_OBJ_IS_TYPE(fields_in, &mp_type_list)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "list required"));
}
mp_obj_list_get(fields_in, &n_fields, &fields);
mp_obj_get_array(fields_in, &n_fields, &fields);
return mp_obj_new_namedtuple_type(name, n_fields, fields);
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_namedtuple_obj, new_namedtuple_type);

View File

@@ -464,9 +464,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
return mp_obj_new_str_from_vstr(self_type, &vstr);
}
enum {SPLIT = 0, KEEP = 1, SPLITLINES = 2};
STATIC inline mp_obj_t str_split_internal(mp_uint_t n_args, const mp_obj_t *args, int type) {
mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args) {
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
mp_int_t splits = -1;
mp_obj_t sep = mp_const_none;
@@ -527,13 +525,7 @@ STATIC inline mp_obj_t str_split_internal(mp_uint_t n_args, const mp_obj_t *args
}
s++;
}
mp_uint_t sub_len = s - start;
if (MP_LIKELY(!(sub_len == 0 && s == top && (type && SPLITLINES)))) {
if (start + sub_len != top && (type & KEEP)) {
sub_len++;
}
mp_obj_list_append(res, mp_obj_new_str_of_type(self_type, start, sub_len));
}
mp_obj_list_append(res, mp_obj_new_str_of_type(self_type, start, s - start));
if (s >= top) {
break;
}
@@ -547,25 +539,49 @@ STATIC inline mp_obj_t str_split_internal(mp_uint_t n_args, const mp_obj_t *args
return res;
}
mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args) {
return str_split_internal(n_args, args, SPLIT);
}
#if MICROPY_PY_BUILTINS_STR_SPLITLINES
STATIC mp_obj_t str_splitlines(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_keepends };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_keepends, MP_ARG_BOOL, {.u_bool = false} },
};
// parse args
struct {
mp_arg_val_t keepends;
} args;
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_obj_t new_args[2] = {pos_args[0], MP_OBJ_NEW_QSTR(MP_QSTR__0x0a_)};
return str_split_internal(2, new_args, SPLITLINES | (args.keepends.u_bool ? KEEP : 0));
const mp_obj_type_t *self_type = mp_obj_get_type(pos_args[0]);
mp_obj_t res = mp_obj_new_list(0, NULL);
GET_STR_DATA_LEN(pos_args[0], s, len);
const byte *top = s + len;
while (s < top) {
const byte *start = s;
size_t match = 0;
while (s < top) {
if (*s == '\n') {
match = 1;
break;
} else if (*s == '\r') {
if (s[1] == '\n') {
match = 2;
} else {
match = 1;
}
break;
}
s++;
}
size_t sub_len = s - start;
if (args[ARG_keepends].u_bool) {
sub_len += match;
}
mp_obj_list_append(res, mp_obj_new_str_of_type(self_type, start, sub_len));
s += match;
}
return res;
}
#endif
@@ -801,6 +817,23 @@ STATIC mp_obj_t str_rstrip(size_t n_args, const mp_obj_t *args) {
return str_uni_strip(RSTRIP, n_args, args);
}
#if MICROPY_PY_BUILTINS_STR_CENTER
STATIC mp_obj_t str_center(mp_obj_t str_in, mp_obj_t width_in) {
GET_STR_DATA_LEN(str_in, str, str_len);
mp_uint_t width = mp_obj_get_int(width_in);
if (str_len >= width) {
return str_in;
}
vstr_t vstr;
vstr_init_len(&vstr, width);
memset(vstr.buf, ' ', width);
int left = (width - str_len) / 2;
memcpy(vstr.buf + left, str, str_len);
return mp_obj_new_str_from_vstr(mp_obj_get_type(str_in), &vstr);
}
#endif
// Takes an int arg, but only parses unsigned numbers, and only changes
// *num if at least one digit was parsed.
STATIC const char *str_to_int(const char *str, const char *top, int *num) {
@@ -1806,7 +1839,7 @@ mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_u
GET_STR_DATA_LEN(self_in, str_data, str_len);
bufinfo->buf = (void*)str_data;
bufinfo->len = str_len;
bufinfo->typecode = 'b';
bufinfo->typecode = 'B'; // bytes should be unsigned, so should unicode byte-access
return 0;
} else {
// can't write to a string
@@ -1830,6 +1863,9 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, mp_obj_str_split);
#if MICROPY_PY_BUILTINS_STR_SPLITLINES
MP_DEFINE_CONST_FUN_OBJ_KW(str_splitlines_obj, 1, str_splitlines);
#endif
#if MICROPY_PY_BUILTINS_STR_CENTER
MP_DEFINE_CONST_FUN_OBJ_2(str_center_obj, str_center);
#endif
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj, 1, 3, str_rsplit);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith);
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith);
@@ -1881,6 +1917,9 @@ STATIC const mp_rom_map_elem_t str8_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&str_count_obj) },
{ MP_ROM_QSTR(MP_QSTR_partition), MP_ROM_PTR(&str_partition_obj) },
{ MP_ROM_QSTR(MP_QSTR_rpartition), MP_ROM_PTR(&str_rpartition_obj) },
#if MICROPY_PY_BUILTINS_STR_CENTER
{ MP_ROM_QSTR(MP_QSTR_center), MP_ROM_PTR(&str_center_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_lower), MP_ROM_PTR(&str_lower_obj) },
{ MP_ROM_QSTR(MP_QSTR_upper), MP_ROM_PTR(&str_upper_obj) },
{ MP_ROM_QSTR(MP_QSTR_isspace), MP_ROM_PTR(&str_isspace_obj) },

Some files were not shown because too many files have changed in this diff Show More