Compare commits

...

347 Commits

Author SHA1 Message Date
Damien George
c8d31585a0 docs: Bump version to 1.8.5. 2016-10-17 15:32:43 +11:00
Damien George
1e3a7c4ac5 tests/run-tests: Enable extmod/machine1.py on pyboard.
It now works.
2016-10-17 13:18:27 +11:00
Damien George
48feb8ac6e stmhal: Enable str.center(), str.[r]partition() and builtin compile().
Also adds "machine" to the list of modules that the parser can search for
constants.
2016-10-17 13:17:19 +11:00
Damien George
57226a2b7f stmhal: Implement machine.soft_reset(). 2016-10-17 13:16:47 +11:00
Damien George
ad3724e0bc lib/utils/pyexec: Allow behaviour of SystemExit to be configurable.
Setting the pyexec_system_exit variable to PYEXEC_FORCED_EXT allows
SystemExit exceptions to terminate the pyexec functions.
2016-10-17 13:14:59 +11:00
Damien George
7d0d7215d2 py: Use mp_raise_msg helper function where appropriate.
Saves the following number of bytes of code space: 176 for bare-arm, 352
for minimal, 272 for unix x86-64, 140 for stmhal, 120 for esp8266.
2016-10-17 12:17:37 +11:00
Damien George
6caca3259f tests: Add test to print full KeyError exc from failed dict lookup. 2016-10-17 12:01:18 +11:00
Damien George
2750a7b38e py/objdict: Actually provide the key that failed in KeyError exception.
The failed key is available as exc.args[0], as per CPython.
2016-10-17 12:00:19 +11:00
Damien George
a3edeb9ea5 py/objdict: Fix optimisation for allocating result in fromkeys.
Iterables don't respond to __len__, so call __len__ on the original
argument.
2016-10-17 11:58:57 +11:00
Damien George
e9404e5f5f tests: Improve coverage of array, range, dict, slice, exc, unicode. 2016-10-17 11:43:47 +11:00
Damien George
453c2e8f55 tests/cmdline: Improve coverage test for printing bytecode. 2016-10-17 11:23:37 +11:00
Paul Sokolovsky
799ccdc789 esp8266, stmhal, unix: MAKE_FROZEN is consistently defined in mkenv.mk. 2016-10-16 10:49:36 +03:00
Paul Sokolovsky
06234a6115 extmod/modussl_mbedtls: Add dummy setblocking() method.
Accepts only value of True.
2016-10-15 23:46:13 +03:00
Paul Sokolovsky
36f97f19b4 extmod/utime_mphal: sleep_us/ms(): Don't wait on negative argument. 2016-10-14 22:19:45 +03:00
Paul Sokolovsky
f059563507 stmhal/modutime: Refactor to use extmod/utime_mphal.c.
This includes making sure that utime_mphal's sleep_ms() and sleep_us()
don't sleep on negative arguments.
2016-10-14 20:42:42 +03:00
Paul Sokolovsky
a97284423e extmod/utime_mphal: Factor out implementations in terms of mp_hal_* for reuse.
As long as a port implement mp_hal_sleep_ms(), mp_hal_ticks_ms(), etc.
functions, it can just use standard implementations of utime.sleel_ms(),
utime.ticks_ms(), etc. Python-level functions.
2016-10-14 20:14:01 +03:00
Damien George
824f5c5a32 py/vstr: Combine vstr_new_size with vstr_new since they are rarely used.
Now there is just one function to allocate a new vstr, namely vstr_new
(in addition to vstr_init etc).  The caller of this function should know
what initial size to allocate for the buffer, or at least have some policy
or config option, instead of leaving it to a default (as it was before).
2016-10-14 16:46:34 +11:00
Damien George
ed878275b0 esp8266: Enable micropython.alloc_emergency_exception_buf(). 2016-10-14 01:27:53 +11:00
Damien George
34d0b3f85c tests/micropython: Add tests for heap_lock, and emergency exceptions. 2016-10-14 00:32:34 +11:00
Damien George
6a4c6fc023 qemu-arm: Remove SRC_TEST_C from SRC_QSTR list, it's not needed.
And it gives problems with header dependencies for auto-qstr generation.
2016-10-14 00:30:38 +11:00
Damien George
b0a15aa735 qemu-arm: Enable lots of extmods and enable tests for them.
The qemu-arm port is used for testing of ARM Thumb architecture on a
desktop so should have many features enabled.
2016-10-14 00:08:19 +11:00
Damien George
8298251215 stmhal/pybstdio: Use size_t instead of mp_uint_t. 2016-10-14 00:07:32 +11:00
Alex March
e42186d356 tests/extmod/vfs_fat: Replace asserts with prints and expected outputs. 2016-10-13 14:56:47 +03:00
Damien George
f2f8ae110b extmod/modujson: Fix nanbox build. 2016-10-13 12:09:18 +11:00
Damien George
11ab807d76 tests/extmod: Add test for ujson.load(). 2016-10-13 11:46:49 +11:00
Damien George
e93c1ca5da extmod/modujson: Implement ujson.load() to load JSON from a stream.
This refactors ujson.loads(s) to behave as ujson.load(StringIO(s)).

Increase in code size is: 366 bytes for unix x86-64, 180 bytes for
stmhal, 84 bytes for esp8266.
2016-10-13 11:46:14 +11:00
Paul Sokolovsky
f17f3314d0 zephyr: Add copyright blurbs. 2016-10-12 22:51:17 +03:00
Paul Sokolovsky
1a01ed0d2a zephyr/mpconfigport.h: Fix rebasing artifacts. 2016-10-12 19:42:55 +03:00
Daniel Thompson
b6a544b917 zephyr: Implement the help() function.
The boot issue text mentions a help() function and encourages
the user to run it. It is very disconcerting to find that the
function does not exist...

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
2016-10-12 19:31:39 +03:00
Paul Sokolovsky
06ee5e947f zephyr/Makefile: Be sure to extra qstr's from port sources. 2016-10-12 19:15:32 +03:00
Paul Sokolovsky
998578a2b8 README: Mention _thread module availability in select ports. 2016-10-12 19:12:20 +03:00
Paul Sokolovsky
cdbeee0c50 tools: Upgrade upip to 1.1.3.
Initial support for running on a baremetal, low-heap systems (like esp8266),
using Python module interface.
2016-10-12 18:55:31 +03:00
Paul Sokolovsky
4021b1e1b8 lib/utils/pyexec: Don't treat SystemExit as "forced exit".
"Forced exit" is treated as soft-reboot (Ctrl+D). But expected effect of
calling sys.exit() is termination of the current script, not any further
and more serious actions like mentioned soft reboot.
2016-10-12 18:00:32 +03:00
Damien George
af8d791bd0 esp8266: Enable importing of precompiled .mpy files. 2016-10-12 11:03:58 +11:00
Damien George
11fc6553e8 esp8266: Enable sys.{stdin,stdout,stderr}.buffer for raw serial access. 2016-10-12 11:03:58 +11:00
Damien George
31101d91ce py/lexer: Remove unnecessary code, and unreachable code.
Setting emit_dent=0 is unnecessary because arriving in that part of the
if-logic will guarantee that emit_dent is already zero.

The block to check indent_top(lex)>0 is unreachable because a newline is
always inserted an the end of the input stream, and hence dedents are
always processed before EOF.
2016-10-12 11:00:17 +11:00
Damien George
deaa57acf3 py/compile: Remove debugging code for compiler dispatch.
It was a relic from the days of developing the compiler and is no longer
needed, and it's impossible to trigger via a test.
2016-10-12 10:20:48 +11:00
Radomir Dopieralski
db4e009217 esp8266/mpconfigport: Enable MICROPY_PY_BUILTINS_SLICE_ATTRS 2016-10-11 12:22:36 +02:00
Alex March
f274561e16 tests/extmod/vfs_fat: Test coverage for remove() and rmdir(). 2016-10-11 16:03:52 +11:00
Alex March
d02f3a57f4 extmod/vfs_fat: Add file and directory checks for remove and rmdir. 2016-10-11 16:03:52 +11:00
Radomir Dopieralski
eaef6b5324 extmod/machine_i2c: Use writes not reads in i2c.scan().
As per discussion in #2449, using write requests instead of read requests
for I2C.scan() seems to support a larger number of devices, especially
ones that are write-only.  Even a read-only I2C device has to implement
writes in order to be able to receive the address of the register to read.
2016-10-11 15:30:46 +11:00
Peter Hinch
9e1dec1818 docs/reference: Add constrained.rst doc.
It contains detailed information about writing scripts to run efficiently
on microcontrollers (and other constrained systems).
2016-10-11 15:27:20 +11:00
Paul Sokolovsky
39968aaaff extmod/uzlib: Update to upstream v2.1.
Adds check that LZ offsets fall into the sliding dictionary used. This
catches a case when uzlib.DecompIO with a smaller dictionary is used
to decompress data which was compressed with a larger dictionary.
Previously, this would lead to producing invalid data or crash, now
an exception will be thrown.
2016-10-11 07:13:23 +03:00
Damien George
6dff3df501 py/objint: Use size_t for arguments that measure bytes/sizes. 2016-10-11 13:20:11 +11:00
Damien George
8bb7d958f1 py: Factor duplicated function to calculate size of formatted int. 2016-10-11 13:11:32 +11:00
Damien George
df3e5d2b2f py/mpz: Use assert to verify mpz does not have a fixed digit buffer. 2016-10-11 13:00:56 +11:00
Damien George
48874942f0 py/mpz: In divmod, replace check for rhs!=0 with assert.
The check for division by zero is made by the caller of this function.
2016-10-11 13:00:01 +11:00
Damien George
5e22afce41 tests: Improve test coverage of py/compile.c. 2016-10-11 12:30:32 +11:00
Damien George
e49153fb98 py/compile: Remove unreachable code. 2016-10-11 12:29:54 +11:00
Damien George
7f0e563de3 tests/micropython: Add test for micropython.opt_level() function. 2016-10-11 11:01:22 +11:00
Damien George
7dc2345715 py/modmicropython: Add micropython.opt_level([value]) function.
This allows to get/set at runtime the optimisation level of the compiler.
2016-10-11 10:56:22 +11:00
Paul Sokolovsky
93c76d2b06 zephyr: Add Ctrl+C handling. 2016-10-10 23:02:51 +03:00
Paul Sokolovsky
1b76f88e7a zephyr/zephyr_getchar: Add support for Ctrl+C handling.
Patch on top of upstream Zephyr console helpers.
2016-10-10 23:02:36 +03:00
Paul Sokolovsky
aa7828f822 zephyr/main: Execute main.py frozen module on boot, if available. 2016-10-10 22:59:34 +03:00
Paul Sokolovsky
7e3b21ec54 zephyr: Enable frozen modules support. 2016-10-10 21:40:08 +03:00
Paul Sokolovsky
b3a65791b1 zephyr: Enable stack checking and micropython.mem_info(). 2016-10-10 21:36:38 +03:00
Paul Sokolovsky
ac70119779 zephyr: Add README. 2016-10-10 21:23:58 +03:00
daniel
a181340ad8 docs/wipy: Correct deep sleep current figure. 2016-10-10 14:22:39 +02:00
Daniel Thompson
5a699a7017 zephyr: Use recently added "make outputexports" Zephyr target.
The outputexpors target, which exports Zephyr environment variables, was
recently added to Zephyr. By exploiting this feature we can hugely simplify
the build system, improving robustness at the same time.

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
2016-10-10 02:47:32 +03:00
Paul Sokolovsky
244b02f744 zephyr/Makefile: Automatically derive target-specific CFLAGS.
By tricking Zephyt arch Makefiles compute them for us (not just for
Zephyr). This make potentially break as Zephyr evolves.
2016-10-10 02:06:06 +03:00
Daniel Thompson
cbc0bf6fec zephyr: Support extra make targets
The two variables, GENERIC_TARGETS and CONFIG_TARGETS come, respectively,
from the the lists shown during "make help" and "make kconfig-help".

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
2016-10-10 02:02:50 +03:00
Daniel Thompson
2ea52cb045 zephyr: Automatically derive ARCH.
Currently to compile for anything that except ARCH=x86 we have to
provide ARCH via the environment or make arguments. We can do better
than that!

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
2016-10-10 01:44:23 +03:00
Paul Sokolovsky
7df9f313c6 zephyr: Switch to microkernel, required for network to work in background. 2016-10-10 01:41:38 +03:00
Paul Sokolovsky
9ad5032164 zephyr: Add zephyr_getchar module to handle console input.
From https://github.com/pfalcon/zephyr_getchar .
2016-10-10 01:35:39 +03:00
Paul Sokolovsky
9d9efc0c5a zephyr: Initial Zephyr RTOS port, Zephyr part. 2016-10-10 01:35:24 +03:00
Paul Sokolovsky
cff9f02cd7 zephyr: Initial Zephyr RTOS port, MicroPython part. 2016-10-10 01:35:14 +03:00
Paul Sokolovsky
fa5ac678fc examples/network/http_client*: Use \r\n line-endings in request. 2016-10-09 19:36:04 +03:00
Paul Sokolovsky
3dabaae47d tests/io/bytesio_ext: Add test for readinto(). 2016-10-09 12:01:02 +03:00
Paul Sokolovsky
d22a04d9c4 py/objstringio: Add readinto() method.
Also, drop deprecated (as for MicroPython) readall() method.
2016-10-09 11:56:11 +03:00
Paul Sokolovsky
49e140488d tests/io/write_ext: Add description comment. 2016-10-09 11:55:28 +03:00
Paul Sokolovsky
3b3612c65b esp8266: Make neopixel support configurable.
To save iRAM.
2016-10-09 00:56:46 +03:00
Damien George
dc43508cc2 extmod/vfs_fat_file: Use MP_Exxx errno constants. 2016-10-07 14:14:41 +11:00
Damien George
016dba0e98 unix: Use common RAISE_ERRNO macro from mphalport.h. 2016-10-07 14:09:59 +11:00
Damien George
503089ea9d unix: Use mp_raise_OSError helper function. 2016-10-07 14:05:15 +11:00
Damien George
23a568240d esp8266: Use mp_raise_OSError helper function. 2016-10-07 14:00:51 +11:00
Damien George
a2bfcbe029 stmhal: Use mp_raise_OSError helper function. 2016-10-07 13:58:25 +11:00
Damien George
e3d29996b3 driver/dht: Use mp_raise_OSError helper function. 2016-10-07 13:53:34 +11:00
Damien George
75af908c0e extmod: Use mp_raise_OSError helper function. 2016-10-07 13:52:14 +11:00
Damien George
06d0083468 extmod/modlwip: Use mp_raise_OSError helper function.
Reduces esp8266 code size by about 230 bytes.
2016-10-07 13:47:57 +11:00
Damien George
620c4c32bf extmod/vfs_fat: Use mp_raise_OSError helper function. 2016-10-07 13:44:55 +11:00
Damien George
3a0a771730 py: Add mp_raise_OSError(errno) helper function.
This is an often used code pattern, and its use reduces code size of the
core by about 100 bytes.
2016-10-07 13:31:59 +11:00
dmanso
0363e1d7b5 esp8266: Add FLASH_MODE,FLASH_SIZE options for make deploy target.
Added options to make deploy so it can be used for ESP8266 boards with
other flash configurations.  For example NodeMCU DEVKIT V1.0 can now use:

    $ make FLASH_MODE=dio FLASH_SIZE=32m deploy
2016-10-07 13:18:48 +11:00
Alex March
00c1fc6d77 docs/uos: Add uos.statvfs() documentation. 2016-10-07 13:16:54 +11:00
Damien George
82af4d6749 tests: Improve coverage of struct with test for non-compliant behaviour. 2016-10-07 12:57:25 +11:00
Damien George
dffa383b06 py/modstruct: Remove unreachable code, and add comment about CPy diff.
The deleted code is unreachable because calcsize_items guarantees that
num_items corresponds to how many items there are in fmt to unpack.
2016-10-07 12:54:14 +11:00
Alex March
9fdba0e09c tests/extmod/uzlib: Test adaptive huffman tree for tinflate coverage. 2016-10-07 01:02:11 +11:00
Damien George
056da75a8a esp8266: Make PY_UHASHLIB_SHA1 config depend on PY_USSL and SSL_AXTLS.
SHA1 can only be supported if ussl module is compiled in, and it uses
axtls.
2016-10-06 12:28:28 +11:00
Damien George
0bb3c7d3b7 stmhal: Enable machine.time_pulse_us() function. 2016-10-06 12:12:20 +11:00
Dave Hylands
c08f50bcf7 stmhal: Disable network and usocket for ESPRUINO_PICO 2016-10-06 11:47:45 +11:00
stijn
7f19b1c3eb tests: Fix expected output of verbose cmdline test
The output might contain more than one line ending in 5b so properly skip
everything until the next known point.
This fixes test failures in appveyor debug builds.
2016-10-05 12:58:50 +02:00
Damien George
b89ac9db78 stmhal/moduos: Implement total-number-of-blocks field in statvfs. 2016-10-05 15:52:36 +11:00
Damien George
b1537a5752 stmhal/mphalport: Change pin obj type to const pointer, to avoid casts. 2016-10-05 15:51:40 +11:00
puuu
bcf60b43ee esp8266/modpybrtc.c: Implement machine.RTC.alarm_left()
Implementation of machine.RTC.alarm_left(), like described in the
documentation.
2016-10-05 12:20:30 +11:00
Dave Hylands
7a9c183c20 stmhal: Fix ESPRUINO_PICO by adding ld scripts with correct flash size. 2016-10-05 11:42:50 +11:00
Paul Sokolovsky
cecf6bee97 tools: Upgrade upip to 1.0.
Fully self-hosted release (without fallbacks), and uses stream gzip
decompression (step towards support for limited-heap baremetal systems).
2016-10-05 00:34:09 +03:00
Paul Sokolovsky
161e9f4115 esp8266/main: Put /lib before / in sys.path.
upip will use first non-empty component in sys.path as an install path
(if MICROPYPATH envvar is not set, like it will be for baremetal targets).
2016-10-05 00:02:51 +03:00
Paul Sokolovsky
52784bf595 esp8266/modmachine: idle(): Return number of CPU cycles spent idling.
Useful to better understand esp8266 inner workings and compare behavior
in different cases.
2016-10-04 21:20:47 +03:00
Alex March
addd1d3db1 tests/extmod/btree1: Checks for put, seq, string print and unsupported binary op. 2016-10-05 00:17:22 +11:00
Pavol Rusnak
99d62c4def stmhal/usb: Use real packet size (not maximum) in HID receive. 2016-10-04 15:39:31 +11:00
Pavol Rusnak
8f3cf6e6a8 stmhal/usb: Use correct ClassData structure for HID receive. 2016-10-04 15:38:32 +11:00
Philip Potter
eb239b8398 stmhal/usb: Add support to receive USB HID messages from host. 2016-10-04 15:38:01 +11:00
Philip Potter
03de5a13cf stmhal/usbdev: Add OUT endpoint to HID interface. 2016-10-04 15:20:11 +11:00
Damien George
cd20027f56 tests/run-tests: Disable cmdline/cmd_showbc test on Windows.
Disabled until a proper fix is found.
2016-10-04 14:42:51 +11:00
Dave Hylands
1f433c719b stmhal: Fix linker map for STM32L476 chips.
In particular, this makes the L4 .isr_vector section 16K in size so it's
the same as the F4/F7 MCUs.  The patch also moves the L4 filesystem to
the end of flash, which allows for 512K filesystem on the 1Mb devices
like the STM32L476DISC.
2016-10-04 14:31:19 +11:00
Damien George
bd925b59c3 stmhal/spi: Enable use of fast software SPI. 2016-10-04 13:51:30 +11:00
Damien George
b0eb0d6153 extmod/machine_spi: Add optional support for fast software SPI.
If a port defines MICROPY_PY_MACHINE_SPI_MIN_DELAY then it can use a
faster software SPI loop that does not make calls to the delay_us
function.
2016-10-04 13:46:40 +11:00
Damien George
b932b2dd1f extmod/machine_spi: Use delay_half, not baudrate, for internal timing.
The delay_half parameter must be specified by the port to set up the
timing of the software SPI.  This allows the port to adjust the timing
value to better suit its timing characteristics, as well as provide a
more accurate printing of the baudrate.
2016-10-04 13:43:02 +11:00
Damien George
9f1e395c16 stmhal/spi: Use software SPI if no periph id given, even if pins given.
It's simpler to just default to always using software SPI if no specific
peripheral id/name is given.  To use hardware SPI users must specify a
hardware peripheral id as the first parameter to the SPI constructor.
2016-10-04 13:38:11 +11:00
Damien George
bd87375202 esp8266/moduos: Move stat/statvfs funcs to sit within #if VFS guard. 2016-10-03 21:48:32 +11:00
Damien George
5deedd6685 stmhal/mphalport: Fix mp_hal_pin_write to use correct pin_mask. 2016-10-03 18:06:58 +11:00
Damien George
d4a5ca5056 stmhal/spi: Make machine.SPI class conform to correct API.
Includes both software and hardware SPI implementations.
2016-10-03 17:12:43 +11:00
Damien George
077dbf4a86 stmhal/mphalport: Implement mp_hal_pin_{input,output,write}. 2016-10-03 16:44:34 +11:00
Damien George
d434ce3fca extmod/machine_spi: Factor out software SPI code from esp8266 to extmod. 2016-10-03 16:43:44 +11:00
Damien George
a22a67661a stmhal/spi: Simplify spi_transfer function to take only one buf len arg. 2016-10-03 12:47:56 +11:00
Damien George
5bb28c7f10 extmod/machine_spi: Simplify SPI xfer function to only take one buf len.
There is no need to take src_len and dest_len arguments.  The case of
reading-only with a single output byte (originally src_len=1, dest_len>1)
is now handled by using the output buffer as the input buffer, and using
memset to fill the output byte into this buffer.  This simplifies the
implementations of the spi_transfer protocol function.
2016-10-03 12:39:31 +11:00
daniel
a0d97fe408 cc3200: Add ssl_version argument to ssl.wrap_socket().
This resolves issue #2343.
2016-10-01 21:35:09 +02:00
Damien George
8de270b4fc py/objbool: Make a slight simplification of bool constructor.
Reduces code size for some archs.
2016-09-30 17:02:07 +10:00
Damien George
eca1408f16 py/objbool: Defer bool's unary op implementation to small int.
Similar to how binary op already works.  Common unary operations already
have fast paths for bool so there's no need to have explicit handling of
ops in bool_unary_op, especially since they have the same behaviour as
integers.
2016-09-30 17:02:06 +10:00
Damien George
3be4f886ce py/argcheck: Simplify if-chain so that the last one is the default. 2016-09-30 16:45:43 +10:00
Damien George
9f72a14920 tests/basics: Add test for printing OSError when errno is unknown. 2016-09-30 16:45:10 +10:00
Krzysztof Blazewicz
b04d4a5b13 lib/cmsis: upgrade CMSIS-CORE to V4.30 2016-09-30 16:19:03 +10:00
Krzysztof Blazewicz
fa6f774b2c lib/cmsis: remove CMSIS-DSP headers, they are unused 2016-09-30 16:19:03 +10:00
Krzysztof Blazewicz
6aea34ad89 lib/cmsis: move CMSIS headers to lib/
Files in lib/cmsis are generic for all Cortex-M MCU's
files left in stmhal/cmsis are all STM32 specific.
2016-09-30 16:19:03 +10:00
Damien George
17b4509564 tests/basics: Add test constructing a set from a non-trivial expression. 2016-09-30 15:00:15 +10:00
Damien George
3c582bc7cb tests/import: Add test for compiling "import a.b as c". 2016-09-30 14:48:22 +10:00
Damien George
216a711cd4 py/compile: Fix typo when checking for parse-node kind. 2016-09-30 14:48:06 +10:00
Damien George
6cf2a3966e tests/basics: Add further tests for nonlocal scoping and closures. 2016-09-30 14:20:55 +10:00
Damien George
0d10517a45 py/scope: Factor common code to find locals and close over them.
Saves 50-100 bytes of code.
2016-09-30 13:53:00 +10:00
Damien George
d5495966ce py/scope: Shrink scope_t struct by 1 machine word.
On 32-bit archs this makes the scope_t struct 48 bytes in size, which fits
in 3 GC blocks (previously it used 4 GC blocks).  This will lead to some
savings when compiling scripts because there are usually quite a few scopes,
one for each function and class.

Note that qstrs will fit in 16 bits, this assumption is made in a few other
places.
2016-09-30 12:45:00 +10:00
Damien George
3dea8c9e92 py/scope: Use lookup-table to determine a scope's simple name.
Generates slightly smaller and more efficient code.
2016-09-30 12:34:05 +10:00
Paul Sokolovsky
6ab2c5e6cc lib/interrupt_char: Factor out typical Ctrl+C handling from esp8266 port.
Utility functions for keyboard interrupt handling, to be reused across
(baremetal) ports.
2016-09-29 10:15:38 -07:00
Damien George
53bfcc9e84 stmhal: Remove CMSIS STM32F2xx files, they are unused/unsupported. 2016-09-28 15:09:03 +10:00
Radomir Dopieralski
219245e10f extmod/machine_i2c: Add support for the addrsize parameter in mem xfers.
The memory read/write I2C functions now take an optional keyword-only
parameter that specifies the number of bits in the memory address.
Only mem-addrs that are a multiple of 8-bits are supported (otherwise
the behaviour is undefined).

Due to the integer type used for the address, for values larger than 32
bits, only 32 bits of address will be sent, and the rest will be padded
with 0s. Right now no exception is raised when that happens. For values
smaller than 8, no address is sent. Also no exception then.

Tested with a VL6180 sensor, which has 16-bit register addresses.

Due to code refactoring, this patch reduces stmhal and esp8266 builds
by about 50 bytes.
2016-09-28 14:45:29 +10:00
Nicholas Graumann
7165fbd8f4 stmhal: Add virtual com port support for STM32L476DISC. 2016-09-27 22:08:55 -05:00
Damien George
b32c01b748 py/compile: Fix async-for/async-with to work with simpler exc on stack.
There is now just the exception instance on the stack when an exception is
raised, not the full (type, exc, traceback).
2016-09-28 11:52:13 +10:00
Damien George
443cc0114d tests/basics: Add test for set.difference_update with arg being itself. 2016-09-28 11:10:27 +10:00
Damien George
2c7716fed0 py/objset: Ensure that use of frozenset.update raises an exception. 2016-09-28 11:06:18 +10:00
Damien George
dd4135aeaf py/objset: Use mp_check_self() to check args of set/frozenset methods.
Following how other objects work, set/frozenset methods should use the
mp_check_self() macro to check the type of the self argument, because in
most cases this check can be a null operation.

Saves about 100-180 bytes of code for builds with set and frozenset
enabled.
2016-09-28 10:55:23 +10:00
Damien George
0c595fa094 py/objfun: Use if instead of switch to check return value of VM execute.
It's simpler and improves code coverage.
2016-09-27 23:08:10 +10:00
Damien George
c71edaed73 py/objfun: Remove unnecessary check for viper fun with 5 or more args.
The native emitter/compiler restricts viper functions to 4 args, so there
is no need for an extra check in the dynamic dispatch.
2016-09-27 23:05:51 +10:00
Damien George
88ca7ff565 stmhal/modmachine: Fix clearing of reset-cause flags.
To reset the flags we should write to the single bit only, not the entire
register (otherwise all other settings in the register are cleared).

Fixes #2457.
2016-09-27 15:49:35 +10:00
Damien George
7385b018ed py/emitbc: Remove/refactor unreachable code, to improve coverage. 2016-09-27 15:46:50 +10:00
Damien George
897129a7ff py/objstr: Remove unreachable function used only for terse error msgs. 2016-09-27 15:45:42 +10:00
Damien George
290daa15d9 tests/float: Add test for parsing a float from an empty string. 2016-09-27 15:44:56 +10:00
Alex March
4fb72fe624 esp8266: Add uos.statvfs() to get filesystem status. 2016-09-27 13:49:05 +10:00
Alex March
670376c5cb tests/extmod/vfs_fat_ramdisk: Add test for VFS.statvfs(). 2016-09-27 13:48:58 +10:00
Alex March
dcf14c1b18 extmod/vfs_fat: Add fat_vfs_statvfs(), reused from stmhal. 2016-09-27 13:48:45 +10:00
Damien George
791b65f4b2 py/modmicropython: Add micropython.const, alias for identity function.
Having a micropython.const identity function, and writing "from micropython
import const" at the start of scripts that use the const feature, allows to
write scripts which are compatible with CPython, and with uPy builds that
don't include const optimisation.

This patch adds such a function and updates the tests to do the import.
2016-09-27 13:34:21 +10:00
Damien George
f65e4f0b8f tests/cmdline/cmd_showbc: Fix test now that 1 value is stored on stack.
This corresponds to the change in the way exception values are stored on
the Python value stack.
2016-09-27 13:22:06 +10:00
Damien George
71fec076dc py/vm: Use MP_OBJ_FROM_PTR to cast a type to an object. 2016-09-27 13:21:23 +10:00
Damien George
38b54b65d4 tests/micropython: Add tests for const names being replaced in parser. 2016-09-27 13:03:53 +10:00
Damien George
3f0c1c2452 tests/basics: Add test case for overflowing Py stack in try-finally. 2016-09-27 12:46:50 +10:00
Damien George
f040685b0c py: Only store the exception instance on Py stack in bytecode try block.
When an exception is raised and is to be handled by the VM, it is stored
on the Python value stack so the bytecode can access it.  CPython stores
3 objects on the stack for each exception: exc type, exc instance and
traceback.  uPy followed this approach, but it turns out not to be
necessary.  Instead, it is enough to store just the exception instance on
the Python value stack.  The only place where the 3 values are needed
explicitly is for the __exit__ handler of a with-statement context, but
for these cases the 3 values can be extracted from the single exception
instance.

This patch removes the need to store 3 values on the stack, and instead
just stores the exception instance.

Code size is reduced by about 50-100 bytes, the compiler and VM are
slightly simpler, generate bytecode is smaller (by 2 bytes for each try
block), and the Python value stack is reduced in size for functions that
handle exceptions.
2016-09-27 12:37:21 +10:00
Paul Sokolovsky
67d52d8cb9 extmod/uzlib/: Update uzlib to v2.0.3.
Fixes for more pedantic warnings.
2016-09-24 16:07:18 +03:00
Paul Sokolovsky
d46de80162 tests/uzlib_decompio_gz: Test for DecompIO with gzip bitstream. 2016-09-24 15:43:23 +03:00
Paul Sokolovsky
7b901d6fb7 extmod/moduzlib: DecompIO: Add support for gzip-formatted streams.
This uses extension introduced in CPython 3.5: if wbits (dictionary size
code) has value 16 + 8..15, it means that gzip-formatted stream expected.
2016-09-24 15:30:11 +03:00
Paul Sokolovsky
d8a4d9d67c extmod/uzlib: Add tinfgzip.c (gzip header parsing) from upstream. 2016-09-24 15:28:51 +03:00
Paul Sokolovsky
4c63986101 tools: Update upip to 0.8. Fixes IPv6 support. 2016-09-23 15:35:06 +03:00
Paul Sokolovsky
9cc8ec843e py/py.mk: Add support for building modussl_mbedtls. 2016-09-23 14:30:46 +03:00
Damien George
6d310a5552 py/parse: Only replace constants that are standalone identifiers.
This fixes constant substitution so that only standalone identifiers are
replaced with their constant value (if they have one).  I.e. don't
replace NAME in expressions like obj.NAME or NAME = expr.
2016-09-23 17:23:16 +10:00
Damien George
eeb9d99333 docs/library/machine: Update description of disable/enable IRQ funcs. 2016-09-23 13:15:58 +10:00
Damien George
7df9291b6c py: Update opcode format table because 3 opcodes were removed, 1 added.
LIST_APPEND, MAP_ADD and SET_ADD have been removed, and STORE_COMP has
been added in adaf0d865c.
2016-09-23 12:48:57 +10:00
Damien George
e97df97600 py: Shrink mp_arg_t struct by using reduced-size integer members.
qstrs ids are restricted to fit within 2 bytes already (eg in persistent
bytecode) so it's safe to use a uint16_t to store them in mp_arg_t.  And
the flags member only needs a maximum of 2 bytes so can also use uint16_t.

Savings in code size can be significant when many mp_arg_t structs are
used for argument parsing.  Eg, this patch reduces stmhal by 480 bytes.
2016-09-23 12:13:51 +10:00
Paul Sokolovsky
46ab042230 extmod/modussl_mbedtls: Add server_hostname param for wrap_socket().
In CPython, module-level .wrap_socket() function actually doesn't accept
(or document) this param, only SSLContext.wrap_socket() has.
2016-09-23 01:44:23 +03:00
Radomir Dopieralski
ec078af985 extmod/machine_i2c: Add clock stretching support.
When the clock is too fast for the i2c slave, it can temporarily hold
down the scl line to signal to the master that it needs to wait. The
master should check the scl line when it is releasing it after
transmitting data, and wait for it to be released.

This change has been tested with a logic analyzer and an i2c slace
implemented on an atmega328p using its twi peripheral, clocked at 8Mhz.
Without the change, the i2c communication works up to aboy 150kHz
frequency, and above that results in the slave stuck in an unresponsive
state. With this change, communication has been tested to work up to
400kHz.
2016-09-22 14:10:02 +10:00
Krzysztof Blazewicz
1f69b16d3f stmhal: Remove STM32CubeF2 HAL files, they are unused/unsupported. 2016-09-22 12:11:01 +10:00
Krzysztof Blazewicz
9310dad15d stmhal: Put common definitions from linker files to common.ld. 2016-09-22 12:03:12 +10:00
Damien George
c4a69c75a5 unix: Enable btree module for coverage build. 2016-09-22 11:10:11 +10:00
Damien George
6c79980b0e py/py.mk: Suppress some compiler warnings when building berkeley-db. 2016-09-22 11:09:21 +10:00
Damien George
79ec869f95 py/stream: Remove unnecessary check for NULL return from vstr_extend.
vstr_extend will now only return NULL if the vstr is a fixed buffer, which
in this case it is not.
2016-09-22 10:50:47 +10:00
Damien George
c528489eee README: Remove issue-stats badges, the service is no longer available.
The issue-stats service is not well maintained and likely the situation
won't improve in the future.  See:
https://github.com/hstove/issue_stats/issues/41
https://github.com/hstove/issue_stats/issues/46
2016-09-22 10:38:49 +10:00
Paul Sokolovsky
080e4d44f3 extmod/modussl_mbedtls: Use 2-component include paths.
This is required to use mbedTLS versions from various sources, e.g.
mainline vs embedded into Zephyr RTOS.
2016-09-22 01:30:48 +03:00
Paul Sokolovsky
5f0ecb72c2 extmod/modussl_mbedtls: Implement key= and cert= args to wrap_socket().
Unlike standard keyfile= and certfile=, these accept byte buffer objects
(to not depend on FS implementation).
2016-09-22 00:17:44 +03:00
Pavol Rusnak
7f5a541b84 extmod/modubinascii: Fix crc32() function on 32-bit platforms. 2016-09-21 21:40:18 +03:00
Stefan Agner
b84e1231c9 extmod/uctypes: Allow full 32-bit address range.
Use mp_obj_int_get_truncated to allow the full 32-bit address range
as first parameter.
2016-09-21 21:37:08 +03:00
Paul Sokolovsky
9ea2882317 extmod/modussl_mbedtls: Initial implementation of mbedTLS ussl module. 2016-09-21 21:25:33 +03:00
Damien George
93c4a6a3f7 all: Remove 'name' member from mp_obj_module_t struct.
One can instead lookup __name__ in the modules dict to get the value.
2016-09-22 00:23:16 +10:00
Stefan Agner
b0a46900de stmhal: Use attribute to avoid inlining.
Use MP_NOINLINE macro to avoid inlining of init_flash_fs. This helps
to keep stack usage of main() low.
2016-09-20 20:41:11 -07:00
Paul Sokolovsky
7ea3fa2641 py/builtinimport: Fix nanbox build after change to better handle -m modules. 2016-09-20 17:55:42 +03:00
Delio Brignoli
21c719bd0a builtinimport: add the module specified by -m to sys.modules as '__main__' 2016-09-20 14:01:31 +03:00
Damien George
34e0198436 esp8266: Extend system microsecond counter to 64-bits; use in ticks_ms.
So now ticks_ms can count up to the full 30 bits.  Fixes issue #2412.
2016-09-20 14:28:17 +10:00
Damien George
cc7c311b5e travis: Run feature and coverage test for precompiled mpy files. 2016-09-20 12:21:53 +10:00
Damien George
3f5fe6269e tests/run-tests: Add --via-mpy option to run test from precompiled code.
With mpy-cross built, tests can now be run by first compiling them to .mpy
files, and then executing the .mpy file.  Usage: ./run-tests --via-mpy
2016-09-20 12:19:35 +10:00
Damien George
bb954d80a4 tests: Get cmdline verbose tests running again.
The showbc function now no longer uses the system printf so works
correctly.
2016-09-20 11:33:19 +10:00
Damien George
fbddea929d py/showbc: Make printf's go to the platform print stream.
The system printf is no longer used by the core uPy code.  Instead, the
platform print stream or DEBUG_printf is used.  Using DEBUG_printf in the
showbc functions would mean that the code can't be tested by the test
suite, so use the normal output instead.

This patch also fixes parsing of bytecode-line-number mappings.
2016-09-20 11:30:54 +10:00
Paul Sokolovsky
60592fd23c tests/array1: Add tests for "l", "L" array types to improve coverage. 2016-09-19 17:20:41 +03:00
Paul Sokolovsky
b85bcd671c tests/struct1: Test "l" specifier to improve coverage. 2016-09-19 17:01:02 +03:00
Damien George
e60835bac5 py/qstr: Remove a comment.
qstrs are always null terminated so qstr_str will stay as part of the API.
2016-09-19 13:18:54 +10:00
Damien George
4874bde104 stmhal/boards: For OLIMEX_E407, enable UART1 and fix I2C1 mapping.
UART1 can be used even if the switch is enabled.  The schematics for this
board make I2C1 available on PB8/PB9, even though it can also be mapped
to PB6/PB7.

See #2396 and #2427.
2016-09-19 13:00:15 +10:00
Damien George
8dd5960ac0 py/objnone: Use mp_generic_unary_op instead of custom one. 2016-09-19 12:28:55 +10:00
Damien George
5da0d29d3c py/vstr: Remove vstr.had_error flag and inline basic vstr functions.
The vstr.had_error flag was a relic from the very early days which assumed
that the malloc functions (eg m_new, m_renew) returned NULL if they failed
to allocate.  But that's no longer the case: these functions will raise an
exception if they fail.

Since it was impossible for had_error to be set, this patch introduces no
change in behaviour.

An alternative option would be to change the malloc calls to the _maybe
variants, which return NULL instead of raising, but then a lot of code
will need to explicitly check if the vstr had an error and raise if it
did.

The code-size savings for this patch are, in bytes: bare-arm:188,
minimal:456, unix(NDEBUG,x86-64):368, stmhal:228, esp8266:360.
2016-09-19 12:28:55 +10:00
Damien George
adaf0d865c py: Combine 3 comprehension opcodes (list/dict/set) into 1.
With the previous patch combining 3 emit functions into 1, it now makes
sense to also combine the corresponding VM opcodes, which is what this
patch does.  This eliminates 2 opcodes which simplifies the VM and reduces
code size, in bytes: bare-arm:44, minimal:64, unix(NDEBUG,x86-64):272,
stmhal:92, esp8266:200.  Profiling (with a simple script that creates many
list/dict/set comprehensions) shows no measurable change in performance.
2016-09-19 12:28:03 +10:00
Damien George
a5624bf381 py: Combine 3 comprehension emit functions (list/dict/set) into 1.
The 3 kinds of comprehensions are similar enough that merging their emit
functions reduces code size.  Decreases in code size in bytes are:
bare-arm:24, minimal:96, unix(NDEBUG,x86-64):328, stmhal:80, esp8266:76.
2016-09-19 12:23:31 +10:00
Paul Sokolovsky
4b3f1d712b esp8266/esp_mphal: Add tentative change to mp_hal_stdin_rx_chr() to wait IRQ.
Instead of busy-looping waiting for UART input. Not enabled by default,
needs more testing.
2016-09-19 00:23:38 +03:00
Paul Sokolovsky
3fe047f08f esp8266/ets_alt_task: ets_post: Should return 0 on success, !0 - failure. 2016-09-18 23:01:58 +03:00
Paul Sokolovsky
4ab3eef8d7 docs/library/pyb.SPI: init(): Describe "bits" argument.
Based on https://github.com/micropython/micropython/pull/2210 .
2016-09-18 21:41:21 +03:00
juhasch
a2391b5a74 Small WiPy doc fixes 2016-09-18 21:38:29 +03:00
Paul Sokolovsky
5bf1b4e9d9 unix/modjni: array(): Support creation of object arrays. 2016-09-18 13:37:40 +03:00
Dave Hylands
d08c9d342f Updated FROZEN_DIR support as per f28efa1971 2016-09-17 12:55:11 -07:00
Paul Sokolovsky
f28efa1971 py: Move frozen modules rules from esp8266 port for reuse across ports.
A port now just needs to define FROZEN_DIR var and add $(BUILD)/frozen.c
to SRC_C to support frozen modules.
2016-09-17 21:00:40 +03:00
Paul Sokolovsky
8ae885a0c6 esp8266/Makefile: Rename SCRIPTDIR to FROZEN_DIR for consistency.
With FROZEN_MPY_DIR.
2016-09-17 21:00:04 +03:00
Paul Sokolovsky
ee324c501e unix/modjni: Add array() top-level function to create Java array.
Takes element primitive type encoded as a char per standard JNI encoding,
and array size. TODO: Support object arrays.
2016-09-17 16:14:02 +03:00
Damien George
b9672bcbe8 tests/extmod: Add test for machine.time_pulse_us(). 2016-09-16 23:31:02 +10:00
Damien George
2b7c4a1878 tests/basics: Add errno1 test, to check basics of uerrno module. 2016-09-16 15:33:51 +10:00
Damien George
67a4813601 tests/extmod/urandom: Add urandom tests for error cases. 2016-09-16 12:49:15 +10:00
Damien George
f84b341618 py/objnone: Remove unnecessary handling of MP_UNARY_OP_BOOL.
bool(None) has a fast path in mp_obj_is_true so doesn't need to be
handled in none_unary_op.  The only caveat is that subclassing may
bypass the mp_obj_is_true function, but actually you aren't allowed to
subclass classes that have singleton instances like NoneType (see
https://mail.python.org/pipermail/python-dev/2002-March/020822.html for
reference on this point).
2016-09-16 12:30:09 +10:00
Paul Sokolovsky
3fea1f014c unix/modjni: Implement subscription for object arrays. 2016-09-16 00:59:48 +03:00
Damien George
0fd3d8d19f stmhal/boards: Add pllvalues.py script to compute PLL values for sysclk.
The algorithm here should mirror that in the machine.freq() function.
2016-09-14 13:00:27 +10:00
Renato Aguiar
081c0648ec unix: Fix build for when MICROPY_PY_SOCKET=0. 2016-09-12 16:43:56 +10:00
stijn
dd0e6ddfeb travis: Abandon mingw32 in favour of mingw-w64
This is actually long overdue: the README in the windows directory has been
updated once to indicate mingw32 is abandoned and not ok to use with uPy,
but we forgot travis builds were still using it.
As a bonus the travis build will succeed again since moduerrno.c now compiles.
(see https://github.com/micropython/micropython/pull/2399)
2016-09-10 10:15:30 +10:00
stijn
d14d4cdb8b windows: Enable MICROPY_PY_UERRNO
This also fixes the test failure for vfs_fat_ramdisk.py
2016-09-10 10:15:30 +10:00
Chris Packham
a50b26e4b0 py/makeqstrdefs.py: Use python 2.6 syntax for set creation.
py/makeqstrdefs.py declares that it works with python 2.6 however the
syntax used to initialise of a set with values was only added in python
2.7. This leads to build failures when the host system doesn't have
python 2.7 or newer.

Instead of using the new syntax pass a list of initial values through
set() to achieve the same result. This should work for python versions
from at least 2.6 onwards.

Helped-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Signed-off-by: Chris Packham <judge.packham@gmail.com>
2016-09-09 23:01:23 +10:00
Damien George
b236b1974b tests/pyb: Update exp file for previously updated extint test. 2016-09-09 19:37:45 +10:00
Damien George
2f02960607 tests/pyb: Add test for ExtInt when doing swint while disabled. 2016-09-09 19:36:09 +10:00
Krzysztof Blazewicz
1ba516f475 stmhal/extint: Force 0 to 1 transition on swint().
If a user tries to call `swint()` while interrupt is disabled the flag in
SWIER is set but the interrupt is not triggered and therefore the SWIER bit
is not cleared.  When the interrupt is again enabled the next call to
`swint()` won't trigger the IRQ because a 0 to 1 transition will not occur.
2016-09-09 19:35:21 +10:00
Krzysztof Blazewicz
06a1194300 stmhal/{accel,lcd}: use GPIO_{set,clear}_pin
different HAL versions implement GPIO differently (BSRR vs BSRRH+BSRRL),
this way both drivers are portable between different HAL's
2016-09-09 10:38:08 +02:00
Tom Soulanille
d89de18f40 stmhal/lcd: De-assert chip select after completing SPI transmission.
The LCD interface library fails to deassert the chip select of the LCD
after an SPI transmission.  Consequently using the SPI with other
peripherals disturbs the state of the LCD.  This patch changes
lcd.lcd_out() to deassert CS after each transmission to the LCD.
2016-09-09 14:51:00 +10:00
Antonin ENFRUN
f3b19ef634 py/asmthumb: Flush D-cache, and invalidate I-cache on STM32F7.
Tested on a STM32F7DISCO at 216MHz.  All tests generating code (inlineasm,
native, viper) now pass, except pybnative/while.py, but that's because
there is no LED(2).
2016-09-09 14:48:15 +10:00
Damien George
3611dcc260 docs: Bump version to 1.8.4. 2016-09-09 14:07:09 +10:00
Damien George
763e04bba5 tests/run-tests: Disable thread/stress_recurse.py test on Travis.
It has reliability issues (cause unknown at this time).
2016-09-08 13:06:29 +10:00
Damien George
f3b5480be7 stmhal,cc3200,esp8266: Consistently use PWRON_RESET constant.
machine.POWER_ON is renamed to machine.PWRON_RESET to match other
reset-cause constants that all end in _RESET.  The cc3200 port keeps a
legacy definition of POWER_ON for backwards compatibility.
2016-09-08 12:50:38 +10:00
Peter Hinch
dab0f316d2 docs/reference/isr_rules.rst: Two minor additions to docs for using ISR.
- Refers to the technique of instantiating an object for use in an ISR by
  specifying it as a default argument.

- Footnote detailing the fact that interrupt handlers continue to be
  executed at the REPL.
2016-09-07 17:12:42 +10:00
Paul Sokolovsky
742d8bdbe4 esp8266/modmachine: Map PWR_ON_RESET to vendor's REASON_DEFAULT_RST.
When dealing with a board which controls chip reset with UART's DTR/RTS,
we never see REASON_DEFAULT_RST (0), only REASON_EXT_SYS_RST (6). However,
trying a "raw" module with with just TXD/RXD UART connection, on power up
it has REASON_DEFAULT_RST as a reset reason.
2016-09-07 00:59:02 +03:00
Damien George
b4be5a8f34 esp8266/modnetwork: Fix wlan.scan() method so it returns all networks.
According to the Arduino ESP8266 implementation the first argument to the
wifi scan callback is actually a bss_info pointer.  This patch fixes the
iteration over this data so the first 2 entries are no longer skipped.

Fixes issue #2372.
2016-09-06 15:30:39 +10:00
Damien George
4a9542c0c0 docs/library/machine.WDT: Add that WDT is available on pyboard. 2016-09-06 14:20:52 +10:00
Damien George
9103cbe366 stmhal/modmachine: Implement machine.reset_cause() function, and consts. 2016-09-06 14:20:19 +10:00
Damien George
b88bf6c76b stmhal/wdt: Implement keyword args to WDT constructor. 2016-09-06 14:19:40 +10:00
Torsten Wagner
69768c97c0 esp8266/espneopixel: Disable IRQs during eps.neopixel_write.
Interrupts during neopixel_write causes timing problems and therefore
wrong light patterns.  Switching off IRQs should help to keep the strict
timing schedule.
2016-09-06 11:51:35 +10:00
Damien George
e4d6a10dc9 travis: Build mpy-cross as part of the Travis process.
It's built first in case any ports need to use it.
2016-09-05 17:33:56 +10:00
Damien George
2b882e9aca mpy-cross: Don't use the internal printf functions.
They require mp_hal_stdout_tx_strn_cooked, which requires extra work to
add to mpy-cross.
2016-09-05 17:30:24 +10:00
Peter Hinch
ef47a67cf4 stmhal/dac: Fix DAC (re-)initialisation by resetting DMA.
Fixes issue #2176.
2016-09-05 15:07:23 +10:00
Damien George
9526e24234 unix,stmhal,esp8266: When find'ing frozen files follow symbolic links.
It's useful to be able to use symbolic links to add files and directories
to the set of scripts to be frozen.
2016-09-05 12:35:05 +10:00
Delio Brignoli
e2ac8bb3f1 py: Add MICROPY_USE_INTERNAL_PRINTF option, defaults to enabled.
This new config option allows to control whether MicroPython uses its own
internal printf or not (if not, an external one should be linked in).
Accompanying this new option is the inclusion of lib/utils/printf.c in the
core list of source files, so that ports no longer need to include it
themselves.
2016-09-05 12:18:53 +10:00
Damien George
cac8dc3414 tests/extmod/framebuf1: Add tests for scrolling in the x-direction. 2016-09-05 12:08:25 +10:00
Radomir Dopieralski
778729c597 extmod/framebuf: Add the xstep!=0 case to scroll() method.
Adds horizontal scrolling. Right now, I'm just leaving the margins
created by the scrolling as they were -- so they will repeat the
edge of the framebuf. This is fast, and the user can always fill
the margins themselves.
2016-09-05 12:06:56 +10:00
Paul Sokolovsky
b4df3e74e1 docs/esp8266/quickref: Further improvements for SPI subsections.
Consistency and formatting.
2016-09-04 23:31:05 +03:00
Paul Sokolovsky
20da9064d7 docs/esp8266/quickref: Update information on SPI classes.
SPI(1) is not used for hardware SPI. Few more details are provided.
2016-09-04 21:13:55 +03:00
Paul Sokolovsky
dba40afa70 esp8266/modmachine: Simplify SPI class implementation multiplexing.
modpybhspi now does the needed multiplexing, calling out to modpybspi
(bitbanging SPI) for suitable peripheral ID's. modmachinespi (previous
multiplexer class) thus not needed and removed.

modpybhspi also updated to following standard SPI peripheral naming:
SPI0 is used for FlashROM and thus not supported so far. SPI1 is available
for users, and thus needs to be instantiated as:

spi = machine.SPI(1, ...)
2016-09-04 20:33:11 +03:00
Paul Sokolovsky
7ddd1a58f6 esp8266/modmachine: Don't expose internal SoftSPI and HSPI classes.
There functionality is available via standard SPI class.
2016-09-04 19:57:16 +03:00
Paul Sokolovsky
1708fe3cc7 esp8266/modmachine: Add WDT_RESET and SOFT_RESET constants.
Both tested to work. (WDT_RESET can be seen by issuing machine.disable_irq()
and waiting for WDT reset, SOFT_RESET - by machine.reset()).
2016-09-04 19:45:58 +03:00
Paul Sokolovsky
61e2dfd97d tests/extmod/uzlib_decompio: Add zlib bitstream testcases. 2016-09-04 14:45:27 +03:00
Paul Sokolovsky
1bc5cb4312 extmod/moduzlib: Support wbits arg to DecompIO. 2016-09-04 14:44:12 +03:00
Dave Hylands
fedab995ee stmhal: Set STM32F7DISC CPU Frequency to 216 MHz
This set the CPU frequency to 216 MHz (the max) and
leaves the USB Frequency at 48 MHz.

These settings were copied from one of the HAL examples.
2016-09-04 18:14:41 +10:00
Damien George
2d8740a4d1 tests/extmod: Add a test for framebuf module, tested by coverage build. 2016-09-04 16:40:40 +10:00
Damien George
47899a1ab8 extmod/modframebuf: Include font from stmhal directory explicitly.
So that users of framebuf don't need to have stmhal directory in their
path.  (Eventually the font can be moved elsewhere.)
2016-09-04 16:39:28 +10:00
Chris Packham
8c6856d2e7 py/emitglue.c: provide mp_raw_code_load_file for any unix architecture
Signed-off-by: Chris Packham <chris.packham@alliedtelesis.co.nz>
2016-09-04 16:17:46 +10:00
Paul Sokolovsky
015774a04f esp8266/modmachinewdt: Add .deinit() method. 2016-09-03 20:45:11 +03:00
Paul Sokolovsky
4a33677c97 esp8266/esp8266.ld: Move modmachinewdt to FlashROM. 2016-09-03 20:44:24 +03:00
Damien George
76c366df56 stmhal: Add machine.WDT class.
Usage:

    import machine
    wdt = machine.WDT(0, 5000) # 5 second timeout
    wdt.feed()

Thanks to Moritz for the initial implementation.
2016-09-04 00:12:48 +10:00
Paul Sokolovsky
f7c4611523 extmod/moduzlib: Use mperrno.h for error constants. 2016-09-03 00:34:57 +03:00
Paul Sokolovsky
fafd587514 tests/extmod: Add test for uzlib.DecompIO. 2016-09-03 00:20:30 +03:00
Paul Sokolovsky
a6864a13c7 extmod/moduzlib: Implement zlib stream decompressor class, DecompIO. 2016-09-03 00:19:35 +03:00
Damien George
c51c883cc8 tools/mpy-tool.py: Support freezing of complex numbers. 2016-09-03 00:19:02 +10:00
Radomir Dopieralski
41ec22632d extmod/modframebuf: Fix fill and scroll when height not divisible by 8.
There was a bug in `framebuf1_fill` function, that makes it leave a few
lines unfilled at the bottom if the height is not divisible by 8.

A similar bug is fixed in the scroll method.
2016-09-02 23:58:34 +10:00
Damien George
b6bdf18deb tools/mpy-tool.py: Compute the hash value for str/bytes objects.
This makes it more efficient at runtime to hash str/bytes objects.
2016-09-02 15:10:45 +10:00
Damien George
b4790afdaf tools/mpy-tool.py: Store qstr config values in global config object.
Makes it easier to access them without passing around another dict of the
config values.
2016-09-02 15:09:21 +10:00
Damien George
58f3861358 tests/unix/extra_coverage: Add test for str/bytes with invalid hash. 2016-09-02 15:07:42 +10:00
Damien George
5f3bda422a py: If str/bytes hash is 0 then explicitly compute it. 2016-09-02 14:49:50 +10:00
Damien George
f127bef3e4 py/makeqstrdata.py: Compute the qstr hash from bytes, not characters. 2016-09-02 14:32:47 +10:00
Delio Brignoli
f98bb2ddcb py/mpprint: Fail an assertion with unsupported format specifiers.
Arguments of an unknown type cannot be skipped and continuing to parse a
format string after encountering an unknown format specifier leads to
undefined behaviour.  This patch helps to find use of unsupported formats.
2016-09-01 18:09:44 +10:00
Radomir Dopieralski
ce1c786297 drivers/sdcard: Port the SDCard driver to new machine API.
With backwards compatibility for pyboard.
2016-09-01 17:44:07 +10:00
Damien George
49406b0ac6 stmhal/spi: Support new machine SPI methods in legacy SPI object. 2016-09-01 16:40:35 +10:00
Damien George
9b64d1966b stmhal/spi: Factor out SPI transfer code to a single function. 2016-09-01 16:40:32 +10:00
Damien George
3be8b688c0 esp8266/modpybhspi: Simplify HSPI driver by using 1 function for xfers. 2016-09-01 16:40:12 +10:00
Damien George
5863e15a23 esp8266/modpybspi: Use generic SPI helper methods to implement SPI. 2016-09-01 16:39:42 +10:00
Damien George
0823c1baf8 extmod: Add machine_spi with generic SPI C-protocol and helper methods.
The idea is that all ports can use these helper methods and only need to
provide initialisation of the SPI bus, as well as a single transfer
function.  The coding pattern follows the stream protocol and helper
methods.
2016-09-01 15:07:20 +10:00
Damien George
9c04ef2a67 unix,stmhal,esp8266: When find'ing frozen files don't use extra slash.
This extra forward slash for the starting-point directory is unnecessary
and leads to additional slashes on Max OS X which mean that the frozen
files cannot be imported.

Fixes #2374.
2016-08-31 15:12:57 +10:00
Paul Sokolovsky
1f61fe07a2 py/mkrules.mk: Allow to override name of libmicropython.a
Or alternatively, refer to an exact library file, not just phony target
"lib".
2016-08-30 00:59:17 +03:00
Paul Sokolovsky
bae62d9abe lib/utils/pyexec: qstr_pool_info() requires size_t* parameters. 2016-08-30 00:58:42 +03:00
Damien George
76dcaddc0f docs/esp8266/quickref: Add internal links to docs for some modules. 2016-08-29 17:40:36 +10:00
Damien George
efc904c41d docs/pyboard/quickref: Add section on "delay and timing" for utime mod.
And remove reference to deprecated pyb.delay() and pyb.millis().
2016-08-29 17:33:02 +10:00
Damien George
5c3a2f162e docs/pyboard/quickref: Add links to pinouts for other pyboard variants. 2016-08-29 17:32:38 +10:00
Krzysztof Blazewicz
d1a366fdd4 .gitignore: Add *.pyc, because Python 2 doesn't use __pycache__. 2016-08-29 15:40:00 +10:00
Philip Potter
c777b6950e stmhal: Update boot.py files to use VCP instead of CDC. 2016-08-29 15:17:34 +10:00
Philip Potter
0f8b1ba8a2 docs/library: Add reference for pyb.usb_mode and pyb.USB_HID. 2016-08-29 15:17:20 +10:00
Philip Potter
f2da6467a9 docs/pyboard: Update USB mouse tutorial to use pyb.USB_HID(). 2016-08-29 15:16:51 +10:00
Philip Potter
57c92d90b0 docs/pyboard: Update USB mouse tutorial to use VCP instead of CDC. 2016-08-29 15:15:25 +10:00
Damien George
13c5a228c9 docs/esp8266: Update quickref and tutorial for OneWire/DS18X20 driver. 2016-08-29 12:52:50 +10:00
Damien George
59a9509703 esp8266/modules/ds18x20.py: Add support for DS18S20 devices. 2016-08-29 12:45:07 +10:00
Damien George
8e9b98e974 esp8266/modules/onewire: Change onewire.read() to onewire.readinto().
This allows 1-wire drivers (eg DS18X20) to perform in-place operations and
hence do less memory allocations.
2016-08-29 12:27:21 +10:00
Damien George
9fba618356 esp8266/modules: Split onewire.py into OneWire and DS18X20 driver.
The OneWire class is now in its own onewire.py module, and the temperature
sensor class is in its own ds18x20.py module.  The latter is renamed to
DS18X20 to reflect the fact that it will support both the "S" and "B"
variants of the device.

These files are moved to the modules/ subdirectory to take advantage of
frozen bytecode.
2016-08-29 12:12:49 +10:00
Radomir Dopieralski
ed0a06a93f docs/esp8266/quickref: Fix and update the SPI docs
Use the `SPI` factory function in the examples, and use
proper baud rate of 80 000 000.
2016-08-28 23:14:45 +10:00
Paul Sokolovsky
263aaa7030 esp8266/modmachinewdt: Implement machine.WDT class. 2016-08-28 14:48:49 +03:00
Damien George
8f8f699eb7 tests/run-tests: Disable thread_gc1.py test on Travis.
It has reliability issues (cause unknown at this time).
2016-08-27 23:41:16 +10:00
Damien George
f4ee9f8853 py/bc.h: Rename _mp_code_state to _mp_code_state_t.
This rename was missed in the previous patch.
2016-08-27 23:23:51 +10:00
Damien George
581a59a456 py: Rename struct mp_code_state to mp_code_state_t.
Also at _t to mp_exc_stack pre-declaration in struct typedef.
2016-08-27 23:21:00 +10:00
Damien George
531217a06b extmod/modframebuf: Fix pixel accessor to return a 1-bit result. 2016-08-27 18:31:58 +10:00
Radomir Dopieralski
fea7fe45ea tests/extmod/vfs_fat_ramdisk: Add tests for VFS.umount()
Try to un-mount a file system and re-mount it again.
2016-08-26 23:24:32 +03:00
Damien George
26295e04ff py/emitglue: Use more compact mp_raise_ValueError function. 2016-08-26 23:45:07 +10:00
Damien George
fe3cc5bb53 py/modstruct: Use more compact mp_raise_ValueError function.
Saves a few bytes of code size.
2016-08-26 23:42:40 +10:00
Damien George
3b5affa0d1 tests/cmdline: Add test for -O option to check optimisation value. 2016-08-26 22:29:38 +10:00
Damien George
24df30c133 py/compile: Don't compile assert statements when optimisations enabled.
As per CPython.
2016-08-26 22:28:22 +10:00
Krzysztof Blazewicz
fc73c9b4b2 stmhal/modusocket: set self->nic to MP_OBJ_NULL after socket close
This patch makes second and next calls to <socket>.close() a no-op.
It prevents GC from closing the underlying resource after user
already used <socket>.close() explicitly.

fixes #2355
2016-08-26 10:57:32 +02:00
Damien George
5ffe1d8dc0 py/gc: Add MICROPY_GC_CONSERVATIVE_CLEAR option to always zero memory.
There can be stray pointers in memory blocks that are not properly zero'd
after allocation.  This patch adds a new config option to always zero all
allocated memory (via gc_alloc and gc_realloc) and hence help to eliminate
stray pointers.

See issue #2195.
2016-08-26 15:35:26 +10:00
Radomir Dopieralski
d29ca28288 esp8266/modous: Add os.umount method to unmount a filesystem.
This is an object-oriented approach, where uos is only a proxy for the
methods on the vfs object.  Some internals had to be exposed (the STATIC
keyword removed) for this to work.

Fixes #2338.
2016-08-26 12:45:21 +10:00
Paul Sokolovsky
b0e2106fb8 lib/berkeley-db-1.xx: Update to upstream, fixes MacOSX build. 2016-08-25 21:30:20 +03:00
Radomir Dopieralski
891479e62a esp8266/hspi: Enable duplex operation of hardware SPI
Without this, spi.read(1, 0xff) would use 16 clock cycles,
first to send 0xff and then to receive one byte, as visible
with a logic analyzer.
2016-08-25 21:24:22 +03:00
Paul Sokolovsky
9897bcaa73 lib/utils/stdout_helpers: Fix function signature to match py/mphal.h. 2016-08-25 15:23:50 +03:00
Dave Hylands
a589fa3e0b stmhal: Update pin print to print new constants
This updates the print function for machine.Pin to
print out the new constants from the Hardware API defintion
rather than the legacy definitions.
2016-08-25 16:11:42 +10:00
Damien George
d09b6b9aa1 esp8266/modpybrtc: Use 64-bit arithmetic when computing alarm expiry. 2016-08-25 14:10:25 +10:00
Damien George
78bc31e294 tests/run-tests: Disable thread/stress_heap.py when running on Travis.
It has reliability issues and sometimes fails on Travis (reason currently
unknown).
2016-08-25 14:06:40 +10:00
Matt Brejza
5af6184e72 stmhal: Make ADC channel 16 available on L4 MCUs. 2016-08-25 13:49:51 +10:00
Paul Sokolovsky
c428367543 extmod/modubinascii: Make crc32() support configurable.
Disable by default, enable in unix port.
2016-08-24 18:28:43 +03:00
Pavol Rusnak
39799f7564 extmod/modubinascii: implement binascii.crc32 2016-08-24 10:42:46 +02:00
Krzysztof Blazewicz
6562076454 py/stream.c: use mp_obj_get_type in mp_get_stream_raise
In current state `mp_get_stream_raise` assumes that `self_in` is an object
and always performs a pointer derefence which may cause a segfault.

This function shall throw an exception whenever `self_in` does not implement
a stream protocol, that includes qstr's and numbers.

fixes #2331
2016-08-24 01:33:31 +03:00
Krzysztof Blazewicz
5a5449d4eb extmod/modbtree: do CHECK_ERROR after __bt_seq()
In `btree_seq()`, when `__bt_seq()` gets called with invalid
`flags` argument it will return `RET_ERROR` and it won't
initialize `val`. If field `data` of uninitialized `val`
is passed to `mp_obj_new_bytes()` it causes a segfault.
2016-08-24 01:31:16 +03:00
Dave Hylands
253e1a6f67 teensy: Fix execution of frozen boot.py and main.py 2016-08-22 12:31:33 +10:00
Damien George
d2d9dfcd40 stmhal: Remove obsolete code for special handling of TIM3 irq settings.
TIM3 is no longer special, or at least does not have special IRQ settings.
2016-08-22 12:24:49 +10:00
Dave Hylands
c6983e3ce0 stmhal: Fix timer capture/compare interrupt handling for TIM1 and TIM8.
It turns out that TIM1 and TIM8 have their own Capture/Compare
interrupt vector. For all of the other timers, the capture/compare
interrupt vector is the same as the update vector.

So we need to add handlers for these vectors and enable them
when using capture/compare callbacks.

During testing of this, I also found that passing a channel callback
into the channel constructor would not enable interrupts properly.

I tested using:
```
>>> pyb.Timer(1, freq=4).channel(1, pyb.Timer.OC_TOGGLE, callback=lambda t: print('.', end=''))
```
I tested the above with channels 1, 4, and 8
2016-08-22 12:18:04 +10:00
Paul Sokolovsky
f2a21a2489 esp8266/esp_mphal: No longer disable watchdog on startup.
Disabling it was an omission from early development stages.
2016-08-20 16:33:04 +03:00
Radomir Dopieralski
d076fae219 esp8266/modmachinespi: Add a factory method for SoftSPI/HSPI 2016-08-19 21:19:59 +03:00
Radomir Dopieralski
8e7dfea803 esp8266/modpybhspi: Add a HSPI module for hardware SPI support
This module uses ESP8266's SPI hardware, which allows much higher
speeds. It uses a library from
https://github.com/MetalPhreak/ESP8266_SPI_Driver
2016-08-19 21:19:59 +03:00
Paul Sokolovsky
49dd532180 extmod/uzlib/: Update uzlib to v2.0.2.
Consistently use stdint types. Fixes stmhal build.
2016-08-17 14:47:30 +03:00
Damien George
64c5a9435c docs/library/machine.WDT: Add note that WDT is only available on WiPy. 2016-08-17 14:22:39 +10:00
Damien George
567e7fcd12 tests/run-tests: Disable thread/thread_lock4.py on Travis.
It has reliability issues that need to be worked out.
2016-08-17 13:48:09 +10:00
Paul Sokolovsky
244332df9f extmod/uzlib/: Update uzlib to v2.0.1.
Fixes for pedantic compiler warnings.
2016-08-17 06:24:12 +03:00
Paul Sokolovsky
a6fc90f92a tests/uzlib_decompress: Actually test raw DEFLATE stream. 2016-08-17 06:10:16 +03:00
Paul Sokolovsky
ed4ce196ed extmod/moduzlib: Refactor to new stream-compatible uzlib 2.0 API. 2016-08-17 06:06:34 +03:00
Paul Sokolovsky
ff1c2b03a9 extmod/uzlib/: Update uzlib to v2.0.
New API supporting stream decompression.
2016-08-17 06:06:33 +03:00
Damien George
bb19e7b94b tests/basics/special_methods: Enable tests for extra special methods.
These additional special methods are enabled on most ports so we can test
them in this test.
2016-08-17 12:38:19 +10:00
Damien George
f003310dee qemu-arm: Enable MICROPY_PY_ALL_SPECIAL_METHODS.
The qemu-arm port is for testing, so should have features enabled.
2016-08-17 12:37:28 +10:00
rguillon
ed6a1ada24 tests/basics: Add a test file for overriding special methods. 2016-08-17 12:11:32 +10:00
Paul Sokolovsky
d2cc7c720b extmod/modwebrepl: set_password(): Raise exception for too long password. 2016-08-16 17:02:04 +03:00
Damien George
095e43a9a5 py/sequence: Allow to use bignums as indices in slice objects.
See issue #2264.
2016-08-15 23:26:34 +10:00
Damien George
f6a8e84a25 tests/basics: Add test for break from within try within a for-loop. 2016-08-15 21:28:41 +10:00
Damien George
675d1c9c60 ports: Remove typedef of machine_ptr_t, it's no longer needed.
This type was used only for the typedef of mp_obj_t, which is now defined
by the object representation.  So we can now remove this unused typedef,
to simplify the mpconfigport.h file.
2016-08-15 11:02:59 +10:00
Damien George
41fceae559 py/obj.h: For obj reprs A,B,C use void* explicitly for mp_obj_t typedef.
The machine_ptr_t type is long obsolete as the type of mp_obj_t is now
defined by the object representation, ie by MICROPY_OBJ_REPR.  So just use
void* explicitly for the typedef of mp_obj_t.

If a port wants to use something different then they should define a new
object representation.
2016-08-15 10:56:55 +10:00
Damien George
b359cf2911 tests/misc/non_compliant: Add tests to improve coverage testing. 2016-08-15 10:46:46 +10:00
Damien George
d5f42c9daf tests/basics: Add more list tests to improve coverage testing. 2016-08-15 10:46:35 +10:00
Damien George
3c82d1d34b tests/basics: Add more tuple tests to improve coverage testing. 2016-08-15 10:46:02 +10:00
Damien George
2196799051 py/objstr: Use mp_raise_{Type,Value}Error instead of mp_raise_msg.
This patch does further refactoring using the new mp_raise_TypeError
and mp_raise_ValueError functions.
2016-08-14 16:51:54 +10:00
Damien George
1a0d3fd632 py/runtime.h: Move comment about mp_not_implemented to correct place. 2016-08-14 16:35:10 +10:00
Damien George
4aaa5adf9f py/objtuple: In tuple_cmp_helper, use mp_check_self instead of raising.
Only tuple, namedtuple and attrtuple use the tuple_cmp_helper function,
and they all have getiter=mp_obj_tuple_getiter, so the check here is only
to ensure that the self object is consistent.  Hence use mp_check_self.
2016-08-14 16:28:05 +10:00
Paul Sokolovsky
9cf2949356 esp8266/mpconfigport.h: Enable support for all special methods. 2016-08-14 01:02:35 +03:00
Paul Sokolovsky
0be4a7712d tests: Rename zlibd_decompress.py -> uzlib_decompress.py.
To use the actual current name.
2016-08-12 22:50:45 +03:00
Paul Sokolovsky
c4a8004933 py: Get rid of assert() in method argument checking functions.
Checks for number of args removes where guaranteed by function descriptor,
self checking is replaced with mp_check_self(). In few cases, exception
is raised instead of assert.
2016-08-12 22:39:03 +03:00
Paul Sokolovsky
83e0ebabb4 py/objdict: Get rid of asserts (remove/replace with mp_check_self()). 2016-08-12 22:01:11 +03:00
Paul Sokolovsky
8c50f93a41 py/runtime.h: Define mp_check_self(pred) helper macro.
Indended to replace raw asserts in bunch of files. Expands to empty
if MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG is defined, otehrwise by
default still to assert, though a particular port may define it to
something else.
2016-08-12 21:58:56 +03:00
Paul Sokolovsky
9e1b61dedd py/runtime: Factor out exception raising helpers.
Introduce mp_raise_msg(), mp_raise_ValueError(), mp_raise_TypeError()
instead of previous pattern nlr_raise(mp_obj_new_exception_msg(...)).
Save few bytes on each call, which are many.
2016-08-12 21:28:45 +03:00
Tobias Badertscher
af9889f99a stmhal/adc.c: Get ADC working on STM32L4 MCUs.
Fixing Issue #2243. Main problems were:

- HAL_ADC_GetState(adcHandle) may return other bits set (not only
  HAL_ADC_STATE_EOC_REG) when called - so I AND-ed it out as proposed by
  mattbrejza in Issue #2243.
- ADC Pin has to be configured as GPIO_MODE_ANALOG_ADC_CONTROL not only
  GPIO_MODE_ANALOG.
- Resolved ADC resolution L4 specific (Use L4 define ADC_RESOLUTION_12B).
- Changed setting of Init.EOCSelection toADC_EOC_SINGLE_CONV for L4.
- Added call to ADC_MultiModeTypeDef as this is done on a STM32Cube
  generated project too.
- Clean up: Configuration of ADC is done only in ONE function not the same
  is done in two functions.

Test is done on PA5 pin of STM32L4Discovery-Kit which is connected to the
DOWN button.

Thanks to mattbrejza for discovering the bug.
2016-08-11 13:01:57 +10:00
Damien George
dfb8144037 stmhal/boards: Update STM32L476 pin defs to include ADC channels.
This patch introduces proper ADC Pin definitions in stm32l476_af.csv.
Originally provided by @tobbad.
2016-08-11 13:01:57 +10:00
ilovezfs
4e36dd570b unix/mpconfigport.h: Don't include stdio.h on MacOS.
Fixes build errors such as
"../lib/utils/printf.c:43:5: error: expected parameter declarator"
2016-08-10 21:43:34 +03:00
Paul Sokolovsky
5e01fb01b3 docs/esp8266/intro: Add command to install esptool.py 1.0.1 via pip.
It used a standard BootROM programming algo and may be useful as a
fallback.
2016-08-10 21:40:40 +03:00
Damien George
72ae3c72c7 tools/mpy-tool.py: Support freezing float literals with obj-repr C.
The tool now generates code for freezing floats in obj-repr A, B or C,
with the specific representation detected at compile time using macros.
2016-08-10 13:26:11 +10:00
Damien George
8a15e0b1c7 esp8266: PULL_UP is not supported on Pin(16), so raise an exception. 2016-08-10 12:45:40 +10:00
Damien George
b203c1774e esp8266: Fix reading of pin object for GPIO16.
Pin(16) now works as an input.
2016-08-10 12:44:47 +10:00
Paul Sokolovsky
2146cdab5e docs/esp8266/tutorial/pins: Fix typo in commands for pin input mode. 2016-08-09 21:13:27 +03:00
495 changed files with 21388 additions and 102881 deletions

1
.gitignore vendored
View File

@@ -32,6 +32,7 @@ tests/*.out
# Python cache files
######################
__pycache__/
*.pyc
# Customized Makefile/project overrides
######################

View File

@@ -12,7 +12,7 @@ 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 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 gcc-mingw-w64
- sudo apt-get install -y --force-yes gcc-arm-none-eabi
# For teensy build
- sudo apt-get install realpath
@@ -23,6 +23,7 @@ before_script:
- python3 --version
script:
- make -C mpy-cross
- make -C minimal test
- make -C unix deplibs
- make -C unix
@@ -35,7 +36,7 @@ script:
- make -C teensy
- make -C cc3200 BTARGET=application BTYPE=release
- make -C cc3200 BTARGET=bootloader BTYPE=release
- make -C windows CROSS_COMPILE=i586-mingw32msvc-
- make -C windows CROSS_COMPILE=i686-w64-mingw32-
# run tests without coverage info
#- (cd tests && MICROPY_CPYTHON3=python3.4 ./run-tests)
@@ -46,6 +47,7 @@ script:
- (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests)
- (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests -d thread)
- (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests --emit native)
- (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests --via-mpy -d basics)
after_success:
- (cd unix && coveralls --root .. --build-root . --gcov $(which gcov) --gcov-options '\-o build-coverage/' --include py --include extmod)

View File

@@ -1,12 +1,8 @@
[![Build Status][travis-img]][travis-repo] [![Coverage Status][coveralls-img]][coveralls-repo] [![Issue Stats][istats-pr-img]][istats-pr-repo] [![Issue Stats][istats-issue-img]][istats-issue-repo]
[![Build Status][travis-img]][travis-repo] [![Coverage Status][coveralls-img]][coveralls-repo]
[travis-img]: https://travis-ci.org/micropython/micropython.png?branch=master
[travis-repo]: https://travis-ci.org/micropython/micropython
[coveralls-img]: https://coveralls.io/repos/micropython/micropython/badge.png?branch=master
[coveralls-repo]: https://coveralls.io/r/micropython/micropython?branch=master
[istats-pr-img]: http://issuestats.com/github/micropython/micropython/badge/pr
[istats-pr-repo]: http://issuestats.com/github/micropython/micropython
[istats-issue-img]: http://issuestats.com/github/micropython/micropython/badge/issue
[istats-issue-repo]: http://issuestats.com/github/micropython/micropython
The MicroPython project
=======================
@@ -26,7 +22,8 @@ MicroPython implements the entire Python 3.4 syntax (including exceptions,
The following core datatypes are provided: str (including basic Unicode
support), bytes, bytearray, tuple, list, dict, set, frozenset, array.array,
collections.namedtuple, classes and instances. Builtin modules include sys,
time, and struct. Note that only subset of Python 3.4 functionality
time, and struct, etc. Select ports have support for _thread module
(multithreading). Note that only subset of Python 3.4 functionality
implemented for the data types and modules.
See the repository www.github.com/micropython/pyboard for the Micro

View File

@@ -42,6 +42,7 @@
#define MICROPY_CPYTHON_COMPAT (0)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
#define MICROPY_USE_INTERNAL_PRINTF (0)
// type definitions for the specific machine
@@ -54,8 +55,6 @@
typedef int32_t mp_int_t; // must be pointer size
typedef uint32_t mp_uint_t; // must be pointer size
typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
typedef long mp_off_t;
// dummy print

View File

@@ -154,7 +154,6 @@ APP_LIB_SRC_C = $(addprefix lib/,\
timeutils/timeutils.c \
utils/pyexec.c \
utils/pyhelp.c \
utils/printf.c \
)
APP_STM_SRC_C = $(addprefix stmhal/,\

View File

@@ -198,7 +198,8 @@ STATIC const mp_map_elem_t machine_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_IDLE), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_ACTIVE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_LPDS) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_HIBERNATE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_POWER_ON), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_POWER_ON), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) }, // legacy constant
{ MP_OBJ_NEW_QSTR(MP_QSTR_PWRON_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HARD_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HARD_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WDT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WDT_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HIB_RESET) },
@@ -212,6 +213,5 @@ STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table
const mp_obj_module_t machine_module = {
.base = { &mp_type_module },
.name = MP_QSTR_umachine,
.globals = (mp_obj_dict_t*)&machine_module_globals,
};

View File

@@ -161,7 +161,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals
const mp_obj_module_t mp_module_network = {
.base = { &mp_type_module },
.name = MP_QSTR_network,
.globals = (mp_obj_dict_t*)&mp_module_network_globals,
};

View File

@@ -58,6 +58,5 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globa
const mp_obj_module_t mp_module_ubinascii = {
.base = { &mp_type_module },
.name = MP_QSTR_ubinascii,
.globals = (mp_obj_dict_t*)&mp_module_binascii_globals,
};

View File

@@ -204,7 +204,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_hashlib_globals, mp_module_hashlib_globals
const mp_obj_module_t mp_module_uhashlib = {
.base = { &mp_type_module },
.name = MP_QSTR_uhashlib,
.globals = (mp_obj_dict_t*)&mp_module_hashlib_globals,
};

View File

@@ -602,6 +602,5 @@ STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
const mp_obj_module_t mp_module_uos = {
.base = { &mp_type_module },
.name = MP_QSTR_uos,
.globals = (mp_obj_dict_t*)&os_module_globals,
};

View File

@@ -541,6 +541,5 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals
const mp_obj_module_t mp_module_usocket = {
.base = { &mp_type_module },
.name = MP_QSTR_usocket,
.globals = (mp_obj_dict_t*)&mp_module_usocket_globals,
};

View File

@@ -78,6 +78,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args,
{ MP_QSTR_certfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_cert_reqs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SSL_CERT_NONE} },
{ MP_QSTR_ssl_version, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SL_SO_SEC_METHOD_TLSV1} },
{ MP_QSTR_ca_certs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
@@ -93,17 +94,19 @@ STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args,
// retrieve the file paths (with an 6 byte offset in order to strip it from the '/flash' prefix)
const char *keyfile = (args[1].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[1].u_obj)[6]);
const char *certfile = (args[2].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[2].u_obj)[6]);
const char *cafile = (args[5].u_obj == mp_const_none || args[4].u_int != SSL_CERT_REQUIRED) ?
NULL : &(mp_obj_str_get_str(args[5].u_obj)[6]);
const char *cafile = (args[6].u_obj == mp_const_none || args[4].u_int != SSL_CERT_REQUIRED) ?
NULL : &(mp_obj_str_get_str(args[6].u_obj)[6]);
// server side requires both certfile and keyfile
if (args[3].u_bool && (!keyfile || !certfile)) {
goto arg_error;
}
_i16 sd = ((mod_network_socket_obj_t *)args[0].u_obj)->sock_base.sd;
_i16 _errno;
_u8 method = SL_SO_SEC_METHOD_TLSV1;
_i16 sd = ((mod_network_socket_obj_t *)args[0].u_obj)->sock_base.sd;
// set the requested SSL method
_u8 method = args[5].u_int;
if ((_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECMETHOD, &method, sizeof(method))) < 0) {
goto socket_error;
}
@@ -146,13 +149,17 @@ STATIC const mp_map_elem_t mp_module_ussl_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_CERT_NONE), MP_OBJ_NEW_SMALL_INT(SSL_CERT_NONE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CERT_OPTIONAL), MP_OBJ_NEW_SMALL_INT(SSL_CERT_OPTIONAL) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CERT_REQUIRED), MP_OBJ_NEW_SMALL_INT(SSL_CERT_REQUIRED) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PROTOCOL_SSLv3), MP_OBJ_NEW_SMALL_INT(SL_SO_SEC_METHOD_SSLV3) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PROTOCOL_TLSv1), MP_OBJ_NEW_SMALL_INT(SL_SO_SEC_METHOD_TLSV1) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PROTOCOL_TLSv1_1), MP_OBJ_NEW_SMALL_INT(SL_SO_SEC_METHOD_TLSV1_1) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PROTOCOL_TLSv1_2), MP_OBJ_NEW_SMALL_INT(SL_SO_SEC_METHOD_TLSV1_2) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_ussl_globals, mp_module_ussl_globals_table);
const mp_obj_module_t mp_module_ussl = {
.base = { &mp_type_module },
.name = MP_QSTR_ussl,
.globals = (mp_obj_dict_t*)&mp_module_ussl_globals,
};

View File

@@ -196,6 +196,5 @@ STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);
const mp_obj_module_t mp_module_utime = {
.base = { &mp_type_module },
.name = MP_QSTR_utime,
.globals = (mp_obj_dict_t*)&time_module_globals,
};

View File

@@ -26,6 +26,5 @@ STATIC MP_DEFINE_CONST_DICT(wipy_module_globals, wipy_module_globals_table);
const mp_obj_module_t wipy_module = {
.base = { &mp_type_module },
.name = MP_QSTR_wipy,
.globals = (mp_obj_dict_t*)&wipy_module_globals,
};

View File

@@ -185,8 +185,6 @@ extern const struct _mp_obj_module_t mp_module_ussl;
typedef int32_t mp_int_t; // must be pointer size
typedef unsigned int mp_uint_t; // must be pointer size
typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
typedef long mp_off_t;
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)

View File

@@ -99,7 +99,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.3'
release = '1.8.5'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View File

@@ -23,14 +23,14 @@ Tab-completion is useful to find out what methods an object has.
Paste mode (ctrl-E) is useful to paste a large slab of Python code into
the REPL.
The ``machine`` module::
The :mod:`machine` module::
import machine
machine.freq() # get the current frequency of the CPU
machine.freq(160000000) # set the CPU frequency to 160 MHz
The ``esp`` module::
The :mod:`esp` module::
import esp
@@ -40,7 +40,7 @@ The ``esp`` module::
Networking
----------
The ``network`` module::
The :mod:`network` module::
import network
@@ -69,13 +69,13 @@ A useful function for connecting to your local WiFi network is::
pass
print('network config:', wlan.ifconfig())
Once the network is established the ``socket`` module can be used
Once the network is established the :mod:`socket <usocket>` module can be used
to create and use TCP/UDP sockets as usual.
Delay and timing
----------------
Use the ``time`` module::
Use the :mod:`time <utime>` module::
import time
@@ -162,17 +162,18 @@ Use the ``machine.ADC`` class::
adc = ADC(0) # create ADC object on ADC pin
adc.read() # read value, 0-1024
SPI bus
-------
Software SPI bus
----------------
The SPI driver is implemented in software and works on all pins::
There are two SPI drivers. One is implemented in software (bit-banging)
and works on all pins::
from machine import Pin, SPI
# construct an SPI bus on the given pins
# polarity is the idle state of SCK
# phase=0 means sample on the first edge of SCK, phase=1 means the second
spi = SPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
spi = SPI(-1, baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
spi.init(baudrate=200000) # set the baudrate
@@ -189,6 +190,21 @@ The SPI driver is implemented in software and works on all pins::
spi.write_readinto(b'1234', buf) # write to MOSI and read from MISO into the buffer
spi.write_readinto(buf, buf) # write buf to MOSI and read MISO back into buf
Hardware SPI bus
----------------
The hardware SPI is faster (up to 80Mhz), but only works on following pins:
``MISO`` is GPIO12, ``MOSI`` is GPIO13, and ``SCK`` is GPIO14. It has the same
methods as the bitbanging SPI class above, except for the pin parameters for the
constructor and init (as those are fixed)::
from machine import Pin, SPI
hspi = SPI(1, baudrate=80000000, polarity=0, phase=0)
(``SPI(0)`` is used for FlashROM and not available to users.)
I2C bus
-------
@@ -239,15 +255,14 @@ The OneWire driver is implemented in software and works on all pins::
ow.scan() # return a list of devices on the bus
ow.reset() # reset the bus
ow.readbyte() # read a byte
ow.read(5) # read 5 bytes
ow.writebyte(0x12) # write a byte on the bus
ow.write('123') # write bytes on the bus
ow.select_rom(b'12345678') # select a specific device by its ROM code
There is a specific driver for DS18B20 devices::
There is a specific driver for DS18S20 and DS18B20 devices::
import time
ds = onewire.DS18B20(ow)
import time, ds18x20
ds = ds18x20.DS18X20(ow)
roms = ds.scan()
ds.convert_temp()
time.sleep_ms(750)

View File

@@ -135,6 +135,10 @@ after it, here are troubleshooting recommendations:
rate may be too high and lead to errors. Try a more common 115200 baud
rate instead in such cases.
* If lower baud rate didn't help, you may want to try older version of
esptool.py, which had a different programming algorithm::
pip install esptool==1.0.1
* The ``--flash_size`` option in the commands above is mandatory. Omitting
it will lead to a corrupted firmware.

View File

@@ -6,19 +6,19 @@ The 1-wire bus is a serial bus that uses just a single wire for communication
is a very popular 1-wire device, and here we show how to use the onewire module
to read from such a device.
For the following code to work you need to have at least one DS18B20 temperature
For the following code to work you need to have at least one DS18S20 or DS18B20 temperature
sensor with its data line connected to GPIO12. You must also power the sensors
and connect a 4.7k Ohm resistor between the data pin and the power pin. ::
import time
import machine
import onewire
import onewire, ds18x20
# the device is on GPIO12
dat = machine.Pin(12)
# create the onewire object
ds = onewire.DS18B20(onewire.OneWire(dat))
ds = ds18x20.DS18X20(onewire.OneWire(dat))
# scan for devices on the bus
roms = ds.scan()

View File

@@ -14,7 +14,7 @@ Here, the "0" is the pin that you want to access. Usually you want to
configure the pin to be input or output, and you do this when constructing
it. To make an input pin use::
>>> pin = machine.Pin(0, machine.Pin.OUT, machine.Pin.PULL_UP)
>>> pin = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP)
You can either use PULL_UP or None for the input pull-mode. If it's
not specified then it defaults to None, which is no pull resistor.

View File

@@ -170,8 +170,7 @@ methods are convenience functions to communicate with such devices.
Read `nbytes` from the slave specified by `addr` starting from the memory
address specified by `memaddr`.
The argument `addrsize` specifies the address size in bits (on ESP8266
this argument is not recognised and the address size is always 8 bits).
The argument `addrsize` specifies the address size in bits.
Returns a `bytes` object with the data read.
.. method:: I2C.readfrom_mem_into(addr, memaddr, buf, \*, addrsize=8)

View File

@@ -14,6 +14,8 @@ Example usage::
wdt = WDT(timeout=2000) # enable it with a timeout of 2s
wdt.feed()
Availability of this class: pyboard, WiPy.
Constructors
------------

View File

@@ -24,17 +24,15 @@ Interrupt related functions
.. 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.
Returns the previous IRQ state which should be considered an opaque value.
This return value should be passed to the ``enable_irq`` function to restore
interrupts to their original state, before ``disable_irq`` was called.
.. function:: enable_irq(state=True)
.. function:: enable_irq(state)
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.
Re-enable interrupt requests.
The ``state`` parameter should be the value that was returned from the most
recent call to the ``disable_irq`` function.
Power related functions
-----------------------
@@ -125,7 +123,7 @@ Constants
irq wake values
.. data:: machine.POWER_ON
.. data:: machine.PWRON_RESET
.. data:: machine.HARD_RESET
.. data:: machine.WDT_RESET
.. data:: machine.DEEPSLEEP_RESET

View File

@@ -68,6 +68,7 @@ Methods
- ``polarity`` can be 0 or 1, and is the level the idle clock line sits at.
- ``phase`` can be 0 or 1 to sample data on the first or second clock edge
respectively.
- ``bits`` can be 8 or 16, and is the number of bits in each transferred word.
- ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``.
- ``crc`` can be None for no CRC, or a polynomial specifier.

View File

@@ -0,0 +1,39 @@
.. currentmodule:: pyb
class USB_HID -- USB Human Interface Device (HID)
=================================================
The USB_HID class allows creation of an object representing the USB
Human Interface Device (HID) interface. It can be used to emulate
a peripheral such as a mouse or keyboard.
Before you can use this class, you need to use :meth:`pyb.usb_mode()` to set the USB mode to include the HID interface.
Constructors
------------
.. class:: pyb.USB_HID()
Create a new USB_HID object.
Methods
-------
.. method:: USB_HID.recv(data, \*, timeout=5000)
Receive data on the bus:
- ``data`` can be an integer, which is the number of bytes to receive,
or a mutable buffer, which will be filled with received bytes.
- ``timeout`` is the timeout in milliseconds to wait for the receive.
Return value: if ``data`` is an integer then a new buffer of the bytes received,
otherwise the number of bytes read into ``data`` is returned.
.. method:: USB_HID.send(data)
Send data over the USB HID interface:
- ``data`` is the data to send (a tuple/list of integers, or a
bytearray).

View File

@@ -188,7 +188,7 @@ Miscellaneous functions
Takes a 4-tuple (or list) and sends it to the USB host (the PC) to
signal a HID mouse-motion event.
.. note:: This function is deprecated. Use pyb.USB_HID().send(...) instead.
.. note:: This function is deprecated. Use :meth:`pyb.USB_HID.send()` instead.
.. function:: info([dump_alloc_table])
@@ -254,6 +254,33 @@ Miscellaneous functions
Returns a string of 12 bytes (96 bits), which is the unique ID of the MCU.
.. function:: usb_mode([modestr], vid=0xf055, pid=0x9801, hid=pyb.hid_mouse)
If called with no arguments, return the current USB mode as a string.
If called with ``modestr`` provided, attempts to set USB mode.
This can only be done when called from ``boot.py`` before
:meth:`pyb.main()` has been called. The following values of
``modestr`` are understood:
- ``None``: disables USB
- ``'VCP'``: enable with VCP (Virtual COM Port) interface
- ``'VCP+MSC'``: enable with VCP and MSC (mass storage device class)
- ``'VCP+HID'``: enable with VCP and HID (human interface device)
For backwards compatibility, ``'CDC'`` is understood to mean
``'VCP'`` (and similarly for ``'CDC+MSC'`` and ``'CDC+HID'``).
The ``vid`` and ``pid`` parameters allow you to specify the VID
(vendor id) and PID (product id).
If enabling HID mode, you may also specify the HID details by
passing the ``hid`` keyword parameter. It takes a tuple of
(subclass, protocol, max packet length, polling interval, report
descriptor). By default it will set appropriate values for a USB
mouse. There is also a ``pyb.hid_keyboard`` constant, which is an
appropriate tuple for a USB keyboard.
Classes
-------
@@ -277,4 +304,5 @@ Classes
pyb.Switch.rst
pyb.Timer.rst
pyb.UART.rst
pyb.USB_HID.rst
pyb.USB_VCP.rst

View File

@@ -61,6 +61,29 @@ Functions
Get the status of a file or directory.
.. only:: port_unix or port_pyboard or port_esp8266
.. function:: statvfs(path)
Get the status of a fileystem.
Returns a tuple with the filesystem information in the following order:
* ``f_bsize`` -- file system block size
* ``f_frsize`` -- fragment size
* ``f_blocks`` -- size of fs in f_frsize units
* ``f_bfree`` -- number of free blocks
* ``f_bavail`` -- number of free blocks for unpriviliged users
* ``f_files`` -- number of inodes
* ``f_ffree`` -- number of free inodes
* ``f_favail`` -- number of free inodes for unpriviliged users
* ``f_flag`` -- mount flags
* ``f_namemax`` -- maximum filename length
Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail``
and the ``f_flags`` parameter may return ``0`` as they can be unavailable
in a port-specific implementation.
.. function:: sync()
Sync all filesystems.

View File

@@ -3,6 +3,12 @@
Quick reference for the pyboard
===============================
The below pinout is for PYBv1.0. You can also view pinouts for
other versions of the pyboard:
`PYBv1.1 <http://micropython.org/resources/pybv11-pinout.jpg>`__
or `PYBLITEv1.0-AC <http://micropython.org/resources/pyblitev10ac-pinout.jpg>`__
or `PYBLITEv1.0 <http://micropython.org/resources/pyblitev10-pinout.jpg>`__.
.. image:: http://micropython.org/resources/pybv10-pinout.jpg
:alt: PYBv1.0 pinout
:width: 700px
@@ -14,14 +20,25 @@ See :mod:`pyb`. ::
import pyb
pyb.delay(50) # wait 50 milliseconds
pyb.millis() # number of milliseconds since bootup
pyb.repl_uart(pyb.UART(1, 9600)) # duplicate REPL on UART(1)
pyb.wfi() # pause CPU, waiting for interrupt
pyb.freq() # get CPU and bus frequencies
pyb.freq(60000000) # set CPU freq to 60MHz
pyb.stop() # stop CPU, waiting for external interrupt
Delay and timing
----------------
Use the :mod:`time <utime>` module::
import time
time.sleep(1) # sleep for 1 second
time.sleep_ms(500) # sleep for 500 milliseconds
time.sleep_us(10) # sleep for 10 microseconds
start = time.ticks_ms() # get value of millisecond counter
delta = time.ticks_diff(start, time.ticks_ms()) # compute time difference
LEDs
----

View File

@@ -13,23 +13,23 @@ will look something like this::
import pyb
#pyb.main('main.py') # main script to run after this one
#pyb.usb_mode('CDC+MSC') # act as a serial and a storage device
#pyb.usb_mode('CDC+HID') # act as a serial device and a mouse
#pyb.usb_mode('VCP+MSC') # act as a serial and a storage device
#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse
To enable the mouse mode, uncomment the last line of the file, to
make it look like::
pyb.usb_mode('CDC+HID') # act as a serial device and a mouse
pyb.usb_mode('VCP+HID') # act as a serial device and a mouse
If you already changed your ``boot.py`` file, then the minimum code it
needs to work is::
import pyb
pyb.usb_mode('CDC+HID')
pyb.usb_mode('VCP+HID')
This tells the pyboard to configure itself as a CDC (serial) and HID
(human interface device, in our case a mouse) USB device when it boots
up.
This tells the pyboard to configure itself as a VCP (Virtual COM Port,
ie serial port) and HID (human interface device, in our case a mouse)
USB device when it boots up.
Eject/unmount the pyboard drive and reset it using the RST switch.
Your PC should now detect the pyboard as a mouse!
@@ -41,7 +41,8 @@ To get the py-mouse to do anything we need to send mouse events to the PC.
We will first do this manually using the REPL prompt. Connect to your
pyboard using your serial program and type the following::
>>> pyb.hid((0, 10, 0, 0))
>>> hid = pyb.USB_HID()
>>> hid.send((0, 10, 0, 0))
Your mouse should move 10 pixels to the right! In the command above you
are sending 4 pieces of information: button status, x, y and scroll. The
@@ -52,7 +53,7 @@ Let's make the mouse oscillate left and right::
>>> import math
>>> def osc(n, d):
... for i in range(n):
... pyb.hid((0, int(20 * math.sin(i / 10)), 0, 0))
... hid.send((0, int(20 * math.sin(i / 10)), 0, 0))
... pyb.delay(d)
...
>>> osc(100, 50)
@@ -100,9 +101,10 @@ In ``main.py`` put the following code::
switch = pyb.Switch()
accel = pyb.Accel()
hid = pyb.USB_HID()
while not switch():
pyb.hid((0, accel.x(), accel.y(), 0))
hid.send((0, accel.x(), accel.y(), 0))
pyb.delay(20)
Save your file, eject/unmount your pyboard drive, and reset it using the RST
@@ -112,7 +114,7 @@ the mouse around. Try it out, and see if you can make the mouse stand still!
Press the USR switch to stop the mouse motion.
You'll note that the y-axis is inverted. That's easy to fix: just put a
minus sign in front of the y-coordinate in the ``pyb.hid()`` line above.
minus sign in front of the y-coordinate in the ``hid.send()`` line above.
Restoring your pyboard to normal
--------------------------------
@@ -121,9 +123,9 @@ If you leave your pyboard as-is, it'll behave as a mouse everytime you plug
it in. You probably want to change it back to normal. To do this you need
to first enter safe mode (see above), and then edit the ``boot.py`` file.
In the ``boot.py`` file, comment out (put a # in front of) the line with the
``CDC+HID`` setting, so it looks like::
``VCP+HID`` setting, so it looks like::
#pyb.usb_mode('CDC+HID') # act as a serial device and a mouse
#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse
Save your file, eject/unmount the drive, and reset the pyboard. It is now
back to normal operating mode.

View File

@@ -0,0 +1,456 @@
.. _constrained:
MicroPython on Microcontrollers
===============================
MicroPython is designed to be capable of running on microcontrollers. These
have hardware limitations which may be unfamiliar to programmers more familiar
with conventional computers. In particular the amount of RAM and nonvolatile
"disk" (flash memory) storage is limited. This tutorial offers ways to make
the most of the limited resources. Because MicroPython runs on controllers
based on a variety of architectures, the methods presented are generic: in some
cases it will be necessary to obtain detailed information from platform specific
documentation.
Flash Memory
------------
On the Pyboard the simple way to address the limited capacity is to fit a micro
SD card. In some cases this is impractical, either because the device does not
have an SD card slot or for reasons of cost or power consumption; hence the
on-chip flash must be used. The firmware including the MicroPython subsystem is
stored in the onboard flash. The remaining capacity is available for use. For
reasons connected with the physical architecture of the flash memory part of
this capacity may be inaccessible as a filesystem. In such cases this space may
be employed by incorporating user modules into a firmware build which is then
flashed to the device.
There are two ways to achieve this: frozen modules and frozen bytecode. Frozen
modules store the Python source with the firmware. Frozen bytecode uses the
cross compiler to convert the source to bytecode which is then stored with the
firmware. In either case the module may be accessed with an import statement:
.. code::
import mymodule
The procedure for producing frozen modules and bytecode is platform dependent;
instructions for building the firmware can be found in the README files in the
relevant part of the source tree.
In general terms the steps are as follows:
* Clone the MicroPython `repository <https://github.com/micropython/micropython>`_.
* Acquire the (platform specific) toolchain to build the firmware.
* Build the cross compiler.
* Place the modules to be frozen in a specified directory (dependent on whether
the module is to be frozen as source or as bytecode).
* Build the firmware. A specific command may be required to build frozen
code of either type - see the platform documentation.
* Flash the firmware to the device.
RAM
---
When reducing RAM usage there are two phases to consider: compilation and
execution. In addition to memory consumption, there is also an issue known as
heap fragmentation. In general terms it is best to minimise the repeated
creation and destruction of objects. The reason for this is covered in the
section covering the `heap`_.
Compilation Phase
~~~~~~~~~~~~~~~~~
When a module is imported, MicroPython compiles the code to bytecode which is
then executed by the MicroPython virtual machine (VM). The bytecode is stored
in RAM. The compiler itself requires RAM, but this becomes available for use
when the compilation has completed.
If a number of modules have already been imported the situation can arise where
there is insufficient RAM to run the compiler. In this case the import
statement will produce a memory exception.
If a module instantiates global objects on import it will consume RAM at the
time of import, which is then unavailable for the compiler to use on subsequent
imports. In general it is best to avoid code which runs on import; a better
approach is to have initialisation code which is run by the application after
all modules have been imported. This maximises the RAM available to the
compiler.
If RAM is still insufficient to compile all modules one solution is to
precompile modules. MicroPython has a cross compiler capable of compiling Python
modules to bytecode (see the README in the mpy-cross directory). The resulting
bytecode file has a .mpy extension; it may be copied to the filesystem and
imported in the usual way. Alternatively some or all modules may be implemented
as frozen bytecode: on most platforms this saves even more RAM as the bytecode
is run directly from flash rather than being stored in RAM.
Execution Phase
~~~~~~~~~~~~~~~
There are a number of coding techniques for reducing RAM usage.
**Constants**
MicroPython provides a ``const`` keyword which may be used as follows:
.. code::
from micropython import const
ROWS = const(33)
_COLS = const(0x10)
a = ROWS
b = _COLS
In both instances where the constant is assigned to a variable the compiler
will avoid coding a lookup to the name of the constant by substituting its
literal value. This saves bytecode and hence RAM. However the ``ROWS`` value
will occupy at least two machine words, one each for the key and value in the
globals dictionary. The presence in the dictionary is necessary because another
module might import or use it. This RAM can be saved by prepending the name
with an underscore as in ``_COLS``: this symbol is not visible outside the
module so will not occupy RAM.
The argument to ``const()`` may be anything which, at compile time, evaluates
to an integer e.g. ``0x100`` or ``1 << 8``. It can even include other const
symbols that have already been defined, e.g. ``1 << BIT``.
**Constant data structures**
Where there is a substantial volume of constant data and the platform supports
execution from Flash, RAM may be saved as follows. The data should be located in
Python modules and frozen as bytecode. The data must be defined as ``bytes``
objects. The compiler 'knows' that ``bytes`` objects are immutable and ensures
that the objects remain in flash memory rather than being copied to RAM. The
``ustruct`` module can assist in converting between ``bytes`` types and other
Python built-in types.
When considering the implications of frozen bytecode, note that in Python
strings, floats, bytes, integers and complex numbers are immutable. Accordingly
these will be frozen into flash. Thus, in the line
.. code::
mystring = "The quick brown fox"
the actual string "The quick brown fox" will reside in flash. At runtime a
reference to the string is assigned to the *variable* ``mystring``. The reference
occupies a single machine word. In principle a long integer could be used to
store constant data:
.. code::
bar = 0xDEADBEEF0000DEADBEEF
As in the string example, at runtime a reference to the arbitrarily large
integer is assigned to the variable ``bar``. That reference occupies a
single machine word.
It might be expected that tuples of integers could be employed for the purpose
of storing constant data with minimal RAM use. With the current compiler this
is ineffective (the code works, but RAM is not saved).
.. code::
foo = (1, 2, 3, 4, 5, 6, 100000)
At runtime the tuple will be located in RAM. This may be subject to future
improvement.
**Needless object creation**
There are a number of situations where objects may unwittingly be created and
destroyed. This can reduce the usability of RAM through fragmentation. The
following sections discuss instances of this.
**String concatenation**
Consider the following code fragments which aim to produce constant strings:
.. code::
var = "foo" + "bar"
var1 = "foo" "bar"
var2 = """\
foo\
bar"""
Each produces the same outcome, however the first needlessly creates two string
objects at runtime, allocates more RAM for concatenation before producing the
third. The others perform the concatenation at compile time which is more
efficient, reducing fragmentation.
Where strings must be dynamically created before being fed to a stream such as
a file it will save RAM if this is done in a piecemeal fashion. Rather than
creating a large string object, create a substring and feed it to the stream
before dealing with the next.
The best way to create dynamic strings is by means of the string ``format``
method:
.. code::
var = "Temperature {:5.2f} Pressure {:06d}\n".format(temp, press)
**Buffers**
When accessing devices such as instances of UART, I2C and SPI interfaces, using
pre-allocated buffers avoids the creation of needless objects. Consider these
two loops:
.. code::
while True:
var = spi.read(100)
# process data
buf = bytearray(100)
while True:
spi.readinto(buf)
# process data in buf
The first creates a buffer on each pass whereas the second re-uses a pre-allocated
buffer; this is both faster and more efficient in terms of memory fragmentation.
**Bytes are smaller than ints**
On most platforms an integer consumes four bytes. Consider the two calls to the
function ``foo()``:
.. code::
def foo(bar):
for x in bar:
print(x)
foo((1, 2, 0xff))
foo(b'\1\2\xff')
In the first call a tuple of integers is created in RAM. The second efficiently
creates a ``bytes`` object consuming the minimum amount of RAM. If the module
were frozen as bytecode, the ``bytes`` object would reside in flash.
**Strings Versus Bytes**
Python3 introduced Unicode support. This introduced a distinction between a
string and an array of bytes. MicroPython ensures that Unicode strings take no
additional space so long as all characters in the string are ASCII (i.e. have
a value < 126). If values in the full 8-bit range are required ``bytes`` and
``bytearray`` objects can be used to ensure that no additional space will be
required. Note that most string methods (e.g. ``strip()``) apply also to ``bytes``
instances so the process of eliminating Unicode can be painless.
.. code::
s = 'the quick brown fox' # A string instance
b = b'the quick brown fox' # a bytes instance
Where it is necessary to convert between strings and bytes the string ``encode``
and the bytes ``decode`` methods can be used. Note that both strings and bytes
are immutable. Any operation which takes as input such an object and produces
another implies at least one RAM allocation to produce the result. In the
second line below a new bytes object is allocated. This would also occur if ``foo``
were a string.
.. code::
foo = b' empty whitespace'
foo = foo.lstrip()
**Runtime compiler execution**
The Python keywords ``eval`` and ``exec`` invoke the compiler at runtime, which
requires significant amounts of RAM. Note that the ``pickle`` library employs
``exec``. It may be more RAM efficient to use the ``json`` library for object
serialisation.
**Storing strings in flash**
Python strings are immutable hence have the potential to be stored in read only
memory. The compiler can place in flash strings defined in Python code. As with
frozen modules it is necessary to have a copy of the source tree on the PC and
the toolchain to build the firmware. The procedure will work even if the
modules have not been fully debugged, so long as they can be imported and run.
After importing the modules, execute:
.. code::
micropython.qstr_info(1)
Then copy and paste all the Q(xxx) lines into a text editor. Check for and
remove lines which are obviously invalid. Open the file qstrdefsport.h which
will be found in stmhal (or the equivalent directory for the architecture in
use). Copy and paste the corrected lines at the end of the file. Save the file,
rebuild and flash the firmware. The outcome can be checked by importing the
modules and again issuing:
.. code::
micropython.qstr_info(1)
The Q(xxx) lines should be gone.
.. _heap:
The Heap
--------
When a running program instantiates an object the necessary RAM is allocated
from a fixed size pool known as the heap. When the object goes out of scope (in
other words becomes inaccessible to code) the redundant object is known as
"garbage". A process known as "garbage collection" (GC) reclaims that memory,
returning it to the free heap. This process runs automatically, however it can
be invoked directly by issuing ``gc.collect()``.
The discourse on this is somewhat involved. For a 'quick fix' issue the
following periodically:
.. code::
gc.collect()
gc.threshold(gc.mem_free() // 4 + gc.mem_alloc())
Fragmentation
~~~~~~~~~~~~~
Say a program creates an object ``foo``, then an object ``bar``. Subsequently
``foo`` goes out of scope but ``bar`` remains. The RAM used by ``foo`` will be
reclaimed by GC. However if ``bar`` was allocated to a higher address, the
RAM reclaimed from ``foo`` will only be of use for objects no bigger than
``foo``. In a complex or long running program the heap can become fragmented:
despite there being a substantial amount of RAM available, there is insufficient
contiguous space to allocate a particular object, and the program fails with a
memory error.
The techniques outlined above aim to minimise this. Where large permanent buffers
or other objects are required it is best to instantiate these early in the
process of program execution before fragmentation can occur. Further improvements
may be made by monitoring the state of the heap and by controlling GC; these are
outlined below.
Reporting
~~~~~~~~~
A number of library functions are available to report on memory allocation and
to control GC. These are to be found in the ``gc`` and ``micropython`` modules.
The following example may be pasted at the REPL (``ctrl e`` to enter paste mode,
``ctrl d`` to run it).
.. code::
import gc
import micropython
gc.collect()
micropython.mem_info()
print('-----------------------------')
print('Initial free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
def func():
a = bytearray(10000)
gc.collect()
print('Func definition: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
func()
print('Func run free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
gc.collect()
print('Garbage collect free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc()))
print('-----------------------------')
micropython.mem_info(1)
Methods employed above:
* ``gc.collect()`` Force a garbage collection. See footnote.
* ``micropython.mem_info()`` Print a summary of RAM utilisation.
* ``gc.mem_free()`` Return the free heap size in bytes.
* ``gc.mem_alloc()`` Return the number of bytes currently allocated.
* ``micropython.mem_info(1)`` Print a table of heap utilisation (detailed below).
The numbers produced are dependent on the platform, but it can be seen that
declaring the function uses a small amount of RAM in the form of bytecode
emitted by the compiler (the RAM used by the compiler has been reclaimed).
Running the function uses over 10KiB, but on return ``a`` is garbage because it
is out of scope and cannot be referenced. The final ``gc.collect()`` recovers
that memory.
The final output produced by ``micropython.mem_info(1)`` will vary in detail but
may be interpreted as follows:
====== =================
Symbol Meaning
====== =================
. free block
h head block
= tail block
m marked head block
T tuple
L list
D dict
F float
B byte code
M module
====== =================
Each letter represents a single block of memory, a block being 16 bytes. So each
line of the heap dump represents 0x400 bytes or 1KiB of RAM.
Control of Garbage Collection
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A GC can be demanded at any time by issuing ``gc.collect()``. It is advantageous
to do this at intervals, firstly to pre-empt fragmentation and secondly for
performance. A GC can take several milliseconds but is quicker when there is
little work to do (about 1ms on the Pyboard). An explicit call can minimise that
delay while ensuring it occurs at points in the program when it is acceptable.
Automatic GC is provoked under the following circumstances. When an attempt at
allocation fails, a GC is performed and the allocation re-tried. Only if this
fails is an exception raised. Secondly an automatic GC will be triggered if the
amount of free RAM falls below a threshold. This threshold can be adapted as
execution progresses:
.. code::
gc.collect()
gc.threshold(gc.mem_free() // 4 + gc.mem_alloc())
This will provoke a GC when more than 25% of the currently free heap becomes
occupied.
In general modules should instantiate data objects at runtime using constructors
or other initialisation functions. The reason is that if this occurs on
initialisation the compiler may be starved of RAM when subsequent modules are
imported. If modules do instantiate data on import then ``gc.collect()`` issued
after the import will ameliorate the problem.
String Operations
-----------------
MicroPython handles strings in an efficient manner and understanding this can
help in designing applications to run on microcontrollers. When a module
is compiled, strings which occur multiple times are stored once only, a process
known as string interning. In MicroPython an interned string is known as a ``qstr``.
In a module imported normally that single instance will be located in RAM, but
as described above, in modules frozen as bytecode it will be located in flash.
String comparisons are also performed efficiently using hashing rather than
character by character. The penalty for using strings rather than integers may
hence be small both in terms of performance and RAM usage - a fact which may
come as a surprise to C programmers.
Postscript
----------
MicroPython passes, returns and (by default) copies objects by reference. A
reference occupies a single machine word so these processes are efficient in
RAM usage and speed.
Where variables are required whose size is neither a byte nor a machine word
there are standard libraries which can assist in storing these efficiently and
in performing conversions. See the ``array``, ``ustruct`` and ``uctypes``
modules.
Footnote: gc.collect() return value
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
On Unix and Windows platforms the ``gc.collect()`` method returns an integer
which signifies the number of distinct memory regions that were reclaimed in the
collection (more precisely, the number of heads that were turned into frees). For
efficiency reasons bare metal ports do not return this value.

View File

@@ -15,6 +15,7 @@ MicroPython are described in the sections here.
repl.rst
isr_rules.rst
speed_python.rst
constrained.rst
.. only:: port_pyboard

View File

@@ -110,6 +110,19 @@ the flag. The memory allocation occurs in the main program code when the object
The MicroPython library I/O methods usually provide an option to use a pre-allocated buffer. For
example ``pyb.i2c.recv()`` can accept a mutable buffer as its first argument: this enables its use in an ISR.
A means of creating an object without employing a class or globals is as follows:
.. code:: python
def set_volume(t, buf=bytearray(3)):
buf[0] = 0xa5
buf[1] = t >> 4
buf[2] = 0x5a
return buf
The compiler instantiates the default ``buf`` argument when the function is
loaded for the first time (usually when the module it's in is imported).
Use of Python objects
~~~~~~~~~~~~~~~~~~~~~
@@ -300,3 +313,20 @@ that access to the critical variables is denied. A simple example of a mutex may
but only for the duration of eight machine instructions: the benefit of this approach is that other interrupts are
virtually unaffected.
Interrupts and the REPL
~~~~~~~~~~~~~~~~~~~~~~~
Interrupt handlers, such as those associated with timers, can continue to run
after a program terminates. This may produce unexpected results where you might
have expected the object raising the callback to have gone out of scope. For
example on the Pyboard:
.. code:: python
def bar():
foo = pyb.Timer(2, freq=4, callback=lambda t: print('.', end=''))
bar()
This continues to run until the timer is explicitly disabled or the board is
reset with ``ctrl D``.

View File

@@ -14,18 +14,18 @@ all divisions must be performed using '//' instead of '/'. Example::
Before applying power
---------------------
.. warning::
.. warning::
The GPIO pins of the WiPy are NOT 5V tolerant, connecting them to voltages higher
than 3.6V will cause irreparable damage to the board. ADC pins, when configured
than 3.6V will cause irreparable damage to the board. ADC pins, when configured
in analog mode cannot withstand voltages above 1.8V. Keep these considerations in
mind when wiring your electronics.
WLAN default behaviour
----------------------
When the WiPy boots with the default factory configuration starts in Access Point
mode with ``ssid`` that starts with: ``wipy-wlan`` and ``key: www.wipy.io``.
When the WiPy boots with the default factory configuration starts in Access Point
mode with ``ssid`` that starts with: ``wipy-wlan`` and ``key: www.wipy.io``.
Connect to this network and the WiPy will be reachable at ``192.168.1.1``. In order
to gain access to the interactive prompt, open a telnet session to that IP address on
the default port (23). You will be asked for credentials:
@@ -98,7 +98,7 @@ the WiPy by pressing the switch on the board, or by typing::
>>> import machine
>>> machine.reset()
Software updates can be found in: https://github.com/wipy/wipy/releases (**Binaries.zip**).
Software updates can be found in: https://github.com/wipy/wipy/releases (**Binaries.zip**).
It's always recommended to update to the latest software, but make sure to
read the **release notes** before.
@@ -122,7 +122,7 @@ Boot modes and safe boot
------------------------
If you power up normally, or press the reset button, the WiPy will boot
into standard mode; the ``boot.py`` file will be executed first, then
into standard mode; the ``boot.py`` file will be executed first, then
``main.py`` will run.
You can override this boot sequence by pulling ``GP28`` **up** (connect
@@ -178,4 +178,4 @@ Details on sleep modes
configuration required.
* ``machine.sleep()``: 950uA (in WLAN STA mode). Wake sources are ``Pin``, ``RTC``
and ``WLAN``
* ``machine.deepsleep()``: ~5uA. Wake sources are ``Pin`` and ``RTC``.
* ``machine.deepsleep()``: ~350uA. Wake sources are ``Pin`` and ``RTC``.

View File

@@ -51,11 +51,10 @@ See :ref:`machine.Timer <machine.Timer>` and :ref:`machine.Pin <machine.Pin>`. :
tim = Timer(0, mode=Timer.PERIODIC)
tim_a = tim.channel(Timer.A, freq=1000)
tim_a.time() # get the value in microseconds
tim_a.freq(5) # 5 Hz
p_out = Pin('GP2', mode=Pin.OUT)
tim_a.irq(handler=lambda t: p_out.toggle())
tim_a.irq(trigger=Timer.TIMEOUT, handler=lambda t: p_out.toggle())
PWM (pulse width modulation)
----------------------------
@@ -135,10 +134,9 @@ Real time clock (RTC)
See :ref:`machine.RTC <machine.RTC>` ::
import machine
from machine import RTC
rtc = machine.RTC() # init with default time and date
rtc = RTC() # init with default time and date
rtc = RTC(datetime=(2015, 8, 29, 9, 0, 0, 0, None)) # init with a specific time and date
print(rtc.now())

View File

@@ -84,6 +84,6 @@ STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) {
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_raise_OSError(MP_ETIMEDOUT);
}
MP_DEFINE_CONST_FUN_OBJ_2(dht_readinto_obj, dht_readinto);

View File

@@ -4,31 +4,41 @@ Micro Python driver for SD cards using SPI bus.
Requires an SPI bus and a CS pin. Provides readblocks and writeblocks
methods so the device can be mounted as a filesystem.
Example usage:
Example usage on pyboard:
import pyb, sdcard, os
sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
pyb.mount(sd, '/sd2')
os.listdir('/')
Example usage on ESP8266:
import machine, sdcard, os
sd = sdcard.SDCard(machine.SPI(0), machine.Pin(15))
os.umount()
os.VfsFat(sd, "")
os.listdir()
"""
import pyb
import time
_CMD_TIMEOUT = const(100)
_R1_IDLE_STATE = const(1 << 0)
#R1_ERASE_RESET = const(1 << 1)
_R1_ILLEGAL_COMMAND = const(1 << 2)
#R1_COM_CRC_ERROR = const(1 << 3)
#R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
#R1_ADDRESS_ERROR = const(1 << 5)
#R1_PARAMETER_ERROR = const(1 << 6)
_TOKEN_CMD25 = const(0xfc)
_TOKEN_STOP_TRAN = const(0xfd)
_TOKEN_DATA = const(0xfe)
class SDCard:
CMD_TIMEOUT = const(100)
R1_IDLE_STATE = const(1 << 0)
#R1_ERASE_RESET = const(1 << 1)
R1_ILLEGAL_COMMAND = const(1 << 2)
#R1_COM_CRC_ERROR = const(1 << 3)
#R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
#R1_ADDRESS_ERROR = const(1 << 5)
#R1_PARAMETER_ERROR = const(1 << 6)
TOKEN_CMD25 = const(0xfc)
TOKEN_STOP_TRAN = const(0xfd)
TOKEN_DATA = const(0xfe)
def __init__(self, spi, cs):
self.spi = spi
self.cs = cs
@@ -42,30 +52,39 @@ class SDCard:
# initialise the card
self.init_card()
def init_spi(self, baudrate):
try:
master = self.spi.MASTER
except AttributeError:
# on ESP8266
self.spi.init(baudrate=baudrate, phase=0, polarity=0)
else:
# on pyboard
self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)
def init_card(self):
# init CS pin
self.cs.high()
self.cs.init(self.cs.OUT_PP)
self.cs.init(self.cs.OUT, value=1)
# init SPI bus; use low data rate for initialisation
self.spi.init(self.spi.MASTER, baudrate=100000, phase=0, polarity=0)
self.init_spi(100000)
# clock card at least 100 cycles with cs high
for i in range(16):
self.spi.send(0xff)
self.spi.write(b'\xff')
# CMD0: init card; should return R1_IDLE_STATE (allow 5 attempts)
# CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
for _ in range(5):
if self.cmd(0, 0, 0x95) == R1_IDLE_STATE:
if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
break
else:
raise OSError("no SD card")
# CMD8: determine card version
r = self.cmd(8, 0x01aa, 0x87, 4)
if r == R1_IDLE_STATE:
if r == _R1_IDLE_STATE:
self.init_card_v2()
elif r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND):
elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
self.init_card_v1()
else:
raise OSError("couldn't determine SD card version")
@@ -86,10 +105,10 @@ class SDCard:
raise OSError("can't set 512 block size")
# set to high data rate now that it's initialised
self.spi.init(self.spi.MASTER, baudrate=1320000, phase=0, polarity=0)
self.init_spi(1320000)
def init_card_v1(self):
for i in range(CMD_TIMEOUT):
for i in range(_CMD_TIMEOUT):
self.cmd(55, 0, 0)
if self.cmd(41, 0, 0) == 0:
self.cdv = 512
@@ -98,8 +117,8 @@ class SDCard:
raise OSError("timeout waiting for v1 card")
def init_card_v2(self):
for i in range(CMD_TIMEOUT):
pyb.delay(50)
for i in range(_CMD_TIMEOUT):
time.sleep_ms(50)
self.cmd(58, 0, 0, 4)
self.cmd(55, 0, 0)
if self.cmd(41, 0x40000000, 0) == 0:
@@ -120,87 +139,87 @@ class SDCard:
buf[3] = arg >> 8
buf[4] = arg
buf[5] = crc
self.spi.send(buf)
self.spi.write(buf)
# wait for the repsonse (response[7] == 0)
for i in range(CMD_TIMEOUT):
response = self.spi.send_recv(0xff)[0]
for i in range(_CMD_TIMEOUT):
response = self.spi.read(1, 0xff)[0]
if not (response & 0x80):
# this could be a big-endian integer that we are getting here
for j in range(final):
self.spi.send(0xff)
self.spi.write(b'\xff')
if release:
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
return response
# timeout
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
return -1
def cmd_nodata(self, cmd):
self.spi.send(cmd)
self.spi.send_recv(0xff) # ignore stuff byte
for _ in range(CMD_TIMEOUT):
if self.spi.send_recv(0xff)[0] == 0xff:
self.spi.write(cmd)
self.spi.read(1, 0xff) # ignore stuff byte
for _ in range(_CMD_TIMEOUT):
if self.spi.read(1, 0xff)[0] == 0xff:
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
return 0 # OK
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
return 1 # timeout
def readinto(self, buf):
self.cs.low()
# read until start byte (0xff)
while self.spi.send_recv(0xff)[0] != 0xfe:
while self.spi.read(1, 0xff)[0] != 0xfe:
pass
# read data
mv = self.dummybuf_memoryview[:len(buf)]
self.spi.send_recv(mv, recv=buf)
self.spi.write_readinto(mv, buf)
# read checksum
self.spi.send(0xff)
self.spi.send(0xff)
self.spi.write(b'\xff')
self.spi.write(b'\xff')
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
def write(self, token, buf):
self.cs.low()
# send: start of block, data, checksum
self.spi.send(token)
self.spi.send(buf)
self.spi.send(0xff)
self.spi.send(0xff)
self.spi.read(1, token)
self.spi.write(buf)
self.spi.write(b'\xff')
self.spi.write(b'\xff')
# check the response
if (self.spi.send_recv(0xff)[0] & 0x1f) != 0x05:
if (self.spi.read(1, 0xff)[0] & 0x1f) != 0x05:
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
return
# wait for write to finish
while self.spi.send_recv(0xff)[0] == 0:
while self.spi.read(1, 0xff)[0] == 0:
pass
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
def write_token(self, token):
self.cs.low()
self.spi.send(token)
self.spi.send(0xff)
self.spi.read(1, token)
self.spi.write(b'\xff')
# wait for write to finish
while self.spi.send_recv(0xff)[0] == 0:
while self.spi.read(1, 0xff)[0] == 0x00:
pass
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
def count(self):
return self.sectors
@@ -224,7 +243,7 @@ class SDCard:
self.readinto(mv[offset : offset + 512])
offset += 512
nblocks -= 1
return self.cmd_nodata(12)
return self.cmd_nodata(b'\x0c') # cmd 12
return 0
def writeblocks(self, block_num, buf):
@@ -236,7 +255,7 @@ class SDCard:
return 1
# send the data
self.write(TOKEN_DATA, buf)
self.write(_TOKEN_DATA, buf)
else:
# CMD25: set write address for first block
if self.cmd(25, block_num * self.cdv, 0) != 0:
@@ -245,8 +264,8 @@ class SDCard:
offset = 0
mv = memoryview(buf)
while nblocks:
self.write(TOKEN_CMD25, mv[offset : offset + 512])
self.write(_TOKEN_CMD25, mv[offset : offset + 512])
offset += 512
nblocks -= 1
self.write_token(TOKEN_STOP_TRAN)
self.write_token(_TOKEN_STOP_TRAN)
return 0

View File

@@ -12,12 +12,13 @@ include ../py/py.mk
MPY_CROSS = ../mpy-cross/mpy-cross
MPY_TOOL = ../tools/mpy-tool.py
MAKE_FROZEN = ../tools/make-frozen.py
SCRIPTDIR = scripts
FROZEN_DIR = scripts
FROZEN_MPY_DIR = modules
PORT ?= /dev/ttyACM0
BAUD ?= 115200
FLASH_MODE ?= qio
FLASH_SIZE ?= 8m
CROSS_COMPILE = xtensa-lx106-elf-
ESP_SDK = $(shell $(CC) -print-sysroot)/usr
@@ -78,7 +79,9 @@ SRC_C = \
modpybrtc.c \
modpybadc.c \
modpybuart.c \
modmachinewdt.c \
modpybspi.c \
modpybhspi.c \
modesp.c \
modnetwork.c \
modutime.c \
@@ -89,6 +92,7 @@ SRC_C = \
$(BUILD)/frozen.c \
fatfs_port.c \
axtls_helpers.c \
hspi.c \
$(SRC_MOD)
STM_SRC_C = $(addprefix stmhal/,\
@@ -125,7 +129,7 @@ LIB_SRC_C = $(addprefix lib/,\
timeutils/timeutils.c \
utils/pyexec.c \
utils/pyhelp.c \
utils/printf.c \
utils/interrupt_char.c \
fatfs/ff.c \
fatfs/option/ccsbcs.c \
)
@@ -137,7 +141,7 @@ DRIVERS_SRC_C = $(addprefix drivers/,\
SRC_S = \
gchelper.s \
FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR)/ -type f -name '*.py')
FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py')
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
OBJ =
@@ -162,16 +166,14 @@ CONFVARS_FILE = $(BUILD)/confvars
ifeq ($(wildcard $(CONFVARS_FILE)),)
$(shell $(MKDIR) -p $(BUILD))
$(shell echo $(SCRIPTDIR) $(UART_OS) > $(CONFVARS_FILE))
else ifneq ($(shell cat $(CONFVARS_FILE)), $(SCRIPTDIR) $(UART_OS))
$(shell echo $(SCRIPTDIR) $(UART_OS) > $(CONFVARS_FILE))
$(shell echo $(FROZEN_DIR) $(UART_OS) > $(CONFVARS_FILE))
else ifneq ($(shell cat $(CONFVARS_FILE)), $(FROZEN_DIR) $(UART_OS))
$(shell echo $(FROZEN_DIR) $(UART_OS) > $(CONFVARS_FILE))
endif
$(BUILD)/uart.o: $(CONFVARS_FILE)
$(BUILD)/frozen.c: $(wildcard $(SCRIPTDIR)/*) $(CONFVARS_FILE)
$(ECHO) "Generating $@"
$(Q)$(MAKE_FROZEN) $(SCRIPTDIR) > $@
FROZEN_EXTRA_DEPS = $(CONFVARS_FILE)
# to build .mpy files from .py files
$(BUILD)/$(FROZEN_MPY_DIR)/%.mpy: $(FROZEN_MPY_DIR)/%.py
@@ -188,7 +190,7 @@ $(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generate
deploy: $(BUILD)/firmware-combined.bin
$(ECHO) "Writing $< to the board"
$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --verify --flash_size=8m 0 $<
$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --verify --flash_size=$(FLASH_SIZE) --flash_mode=$(FLASH_MODE) 0 $<
#$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --flash_size=8m 0 $(BUILD)/firmware.elf-0x00000.bin 0x9000 $(BUILD)/firmware.elf-0x0[1-f]000.bin
reset:

View File

@@ -70,9 +70,10 @@ $ make deploy
```
This will use the `esptool.py` script to download the images. You must have
your ESP module in the bootloader mode, and connected to a serial port on your PC.
The default serial port is `/dev/ttyACM0`. To specify another, use, eg:
The default serial port is `/dev/ttyACM0`, flash mode is `qio` and flash size is `8m`.
To specify other values, use, eg:
```bash
$ make PORT=/dev/ttyUSB0 deploy
$ make PORT=/dev/ttyUSB0 FLASH_MODE=qio FLASH_SIZE=8m deploy
```
The image produced is `firmware-combined.bin`, to be flashed at 0x00000.

View File

@@ -141,7 +141,10 @@ SECTIONS
*modpybadc.o(.literal*, .text*)
*modpybuart.o(.literal*, .text*)
*modpybi2c.o(.literal*, .text*)
*modmachinewdt.o(.literal*, .text*)
*modpybspi.o(.literal*, .text*)
*modpybhspi.o(.literal*, .text*)
*hspi.o(.literal*, .text*)
*modesp.o(.literal* .text*)
*modnetwork.o(.literal* .text*)
*moduos.o(.literal* .text*)

View File

@@ -36,17 +36,13 @@
#include "extmod/misc.h"
#include "lib/utils/pyexec.h"
extern void ets_wdt_disable(void);
extern void wdt_feed(void);
extern void ets_delay_us();
STATIC byte input_buf_array[256];
ringbuf_t input_buf = {input_buf_array, sizeof(input_buf_array)};
void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len);
const mp_print_t mp_debug_print = {NULL, mp_hal_debug_tx_strn_cooked};
void mp_hal_init(void) {
ets_wdt_disable(); // it's a pain while developing
//ets_wdt_disable(); // it's a pain while developing
mp_hal_rtc_init();
uart_init(UART_BIT_RATE_115200, UART_BIT_RATE_115200);
}
@@ -64,7 +60,14 @@ int mp_hal_stdin_rx_chr(void) {
if (c != -1) {
return c;
}
#if 0
// Idles CPU but need more testing before enabling
if (!ets_loop_iter()) {
asm("waiti 0");
}
#else
mp_hal_delay_us(1);
#endif
}
}
@@ -114,7 +117,7 @@ void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len) {
}
uint32_t mp_hal_ticks_ms(void) {
return system_get_time() / 1000;
return ((uint64_t)system_time_high_word << 32 | (uint64_t)system_get_time()) / 1000;
}
uint32_t mp_hal_ticks_us(void) {
@@ -125,14 +128,6 @@ void mp_hal_delay_ms(uint32_t delay) {
mp_hal_delay_us(delay * 1000);
}
void mp_hal_set_interrupt_char(int c) {
if (c != -1) {
mp_obj_exception_clear_traceback(MP_STATE_PORT(mp_kbd_exception));
}
extern int interrupt_char;
interrupt_char = c;
}
void ets_event_poll(void) {
ets_loop_iter();
if (MP_STATE_VM(mp_pending_exception) != NULL) {
@@ -177,7 +172,7 @@ static int call_dupterm_read(void) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(MP_STATE_PORT(dupterm_arr_obj), &bufinfo, MP_BUFFER_READ);
nlr_pop();
if (*(byte*)bufinfo.buf == interrupt_char) {
if (*(byte*)bufinfo.buf == mp_interrupt_char) {
mp_keyboard_interrupt();
return -2;
}

View File

@@ -28,10 +28,10 @@
#define _INCLUDED_MPHAL_H_
#include "py/ringbuf.h"
#include "lib/utils/interrupt_char.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()

View File

@@ -5,6 +5,9 @@
// ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus
// Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution.
#include "py/mpconfig.h"
#if MICROPY_ESP8266_NEOPIXEL
#include "c_types.h"
#include "eagle_soc.h"
#include "user_interface.h"
@@ -41,6 +44,7 @@ void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32
}
#endif
uint32_t irq_state = mp_hal_quiet_timing_enter();
for(t = time0;; t = time0) {
if(pix & mask) t = time1; // Bit high duration
while(((c = mp_hal_ticks_cpu()) - startTime) < period); // Wait for bit start
@@ -55,4 +59,7 @@ void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32
}
}
while((mp_hal_ticks_cpu() - startTime) < period); // Wait for last bit
mp_hal_quiet_timing_exit(irq_state);
}
#endif // MICROPY_ESP8266_NEOPIXEL

View File

@@ -87,7 +87,7 @@ bool ets_post(uint8 prio, os_signal_t sig, os_param_t param) {
if (emu_tasks[id].i_put == -1) {
// queue is full
printf("ets_post: task %d queue full\n", prio);
return false;
return 1;
}
q = &q[emu_tasks[id].i_put++];
q->sig = sig;
@@ -104,16 +104,28 @@ bool ets_post(uint8 prio, os_signal_t sig, os_param_t param) {
ets_intr_unlock();
return true;
return 0;
#endif
}
int ets_loop_iter_disable = 0;
// to implement a 64-bit wide microsecond counter
static uint32_t system_time_prev = 0;
uint32_t system_time_high_word = 0;
bool ets_loop_iter(void) {
if (ets_loop_iter_disable) {
return false;
}
// handle overflow of system microsecond counter
uint32_t system_time_cur = system_get_time();
if (system_time_cur < system_time_prev) {
system_time_high_word += 1; // record overflow of low 32-bits
}
system_time_prev = system_time_cur;
//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,2 +1,4 @@
extern int ets_loop_iter_disable;
extern uint32_t system_time_high_word;
bool ets_loop_iter(void);

View File

@@ -20,6 +20,9 @@ void ets_timer_arm_new(os_timer_t *tim, uint32_t millis, bool repeat, bool is_mi
void ets_timer_setfn(os_timer_t *tim, ETSTimerFunc callback, void *cb_data);
void ets_timer_disarm(os_timer_t *tim);
extern void ets_wdt_disable(void);
extern void wdt_feed(void);
// Opaque structure
typedef char MD5_CTX[64];

331
esp8266/hspi.c Normal file
View File

@@ -0,0 +1,331 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 David Ogilvy (MetalPhreak)
* Modified 2016 by Radomir Dopieralski
*
* 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 "hspi.h"
/*
Wrapper to setup HSPI/SPI GPIO pins and default SPI clock
spi_no - SPI (0) or HSPI (1)
Not used in Micropython.
*/
void spi_init(uint8_t spi_no) {
spi_init_gpio(spi_no, SPI_CLK_USE_DIV);
spi_clock(spi_no, SPI_CLK_PREDIV, SPI_CLK_CNTDIV);
spi_tx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW);
spi_rx_byte_order(spi_no, SPI_BYTE_ORDER_HIGH_TO_LOW);
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD);
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE);
}
/*
Configures SPI mode parameters for clock edge and clock polarity.
spi_no - SPI (0) or HSPI (1)
spi_cpha - (0) Data is valid on clock leading edge
(1) Data is valid on clock trailing edge
spi_cpol - (0) Clock is low when inactive
(1) Clock is high when inactive
For Micropython this version is different from original.
*/
void spi_mode(uint8_t spi_no, uint8_t spi_cpha, uint8_t spi_cpol) {
if (spi_cpol) {
SET_PERI_REG_MASK(SPI_PIN(HSPI), SPI_IDLE_EDGE);
} else {
CLEAR_PERI_REG_MASK(SPI_PIN(HSPI), SPI_IDLE_EDGE);
}
if (spi_cpha == spi_cpol) {
// Mode 3 - MOSI is set on falling edge of clock
// Mode 0 - MOSI is set on falling edge of clock
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE);
SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_I_EDGE);
} else {
// Mode 2 - MOSI is set on rising edge of clock
// Mode 1 - MOSI is set on rising edge of clock
SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE);
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_I_EDGE);
}
}
/*
Initialise the GPIO pins for use as SPI pins.
spi_no - SPI (0) or HSPI (1)
sysclk_as_spiclk -
SPI_CLK_80MHZ_NODIV (1) if using 80MHz for SPI clock.
SPI_CLK_USE_DIV (0) if using divider for lower speed.
*/
void spi_init_gpio(uint8_t spi_no, uint8_t sysclk_as_spiclk) {
uint32_t clock_div_flag = 0;
if (sysclk_as_spiclk) {
clock_div_flag = 0x0001;
}
if (spi_no == SPI) {
// Set bit 8 if 80MHz sysclock required
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005 | (clock_div_flag<<8));
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);
} else if (spi_no == HSPI) {
// Set bit 9 if 80MHz sysclock required
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105 | (clock_div_flag<<9));
// GPIO12 is HSPI MISO pin (Master Data In)
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);
// GPIO13 is HSPI MOSI pin (Master Data Out)
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);
// GPIO14 is HSPI CLK pin (Clock)
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);
// GPIO15 is HSPI CS pin (Chip Select / Slave Select)
// In Micropython, we are handling CS ourself in drivers.
// PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);
}
}
/*
Set up the control registers for the SPI clock
spi_no - SPI (0) or HSPI (1)
prediv - predivider value (actual division value)
cntdiv - postdivider value (actual division value)
Set either divider to 0 to disable all division (80MHz sysclock)
*/
void spi_clock(uint8_t spi_no, uint16_t prediv, uint8_t cntdiv) {
if (prediv == 0 || cntdiv == 0) {
WRITE_PERI_REG(SPI_CLOCK(spi_no), SPI_CLK_EQU_SYSCLK);
} else {
WRITE_PERI_REG(SPI_CLOCK(spi_no),
(((prediv - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) |
(((cntdiv - 1) & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) |
(((cntdiv >> 1) & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) |
((0 & SPI_CLKCNT_L) << SPI_CLKCNT_L_S)
);
}
}
/*
Setup the byte order for shifting data out of buffer
spi_no - SPI (0) or HSPI (1)
byte_order -
SPI_BYTE_ORDER_HIGH_TO_LOW (1)
Data is sent out starting with Bit31 and down to Bit0
SPI_BYTE_ORDER_LOW_TO_HIGH (0)
Data is sent out starting with the lowest BYTE, from MSB to LSB,
followed by the second lowest BYTE, from MSB to LSB, followed by
the second highest BYTE, from MSB to LSB, followed by the highest
BYTE, from MSB to LSB 0xABCDEFGH would be sent as 0xGHEFCDAB.
*/
void spi_tx_byte_order(uint8_t spi_no, uint8_t byte_order) {
if (byte_order) {
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER);
} else {
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_WR_BYTE_ORDER);
}
}
/*
Setup the byte order for shifting data into buffer
spi_no - SPI (0) or HSPI (1)
byte_order -
SPI_BYTE_ORDER_HIGH_TO_LOW (1)
Data is read in starting with Bit31 and down to Bit0
SPI_BYTE_ORDER_LOW_TO_HIGH (0)
Data is read in starting with the lowest BYTE, from MSB to LSB,
followed by the second lowest BYTE, from MSB to LSB, followed by
the second highest BYTE, from MSB to LSB, followed by the highest
BYTE, from MSB to LSB 0xABCDEFGH would be read as 0xGHEFCDAB
*/
void spi_rx_byte_order(uint8_t spi_no, uint8_t byte_order) {
if (byte_order) {
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER);
} else {
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_RD_BYTE_ORDER);
}
}
/*
SPI transaction function
spi_no - SPI (0) or HSPI (1)
cmd_bits - actual number of bits to transmit
cmd_data - command data
addr_bits - actual number of bits to transmit
addr_data - address data
dout_bits - actual number of bits to transmit
dout_data - output data
din_bits - actual number of bits to receive
Returns: read data - uint32_t containing read in data only if RX was set
0 - something went wrong (or actual read data was 0)
1 - data sent ok (or actual read data is 1)
Note: all data is assumed to be stored in the lower bits of the data variables
(for anything <32 bits).
*/
uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data,
uint32_t addr_bits, uint32_t addr_data,
uint32_t dout_bits, uint32_t dout_data,
uint32_t din_bits, uint32_t dummy_bits) {
while (spi_busy(spi_no)) {}; // Wait for SPI to be ready
// Enable SPI Functions
// Disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set.
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI | SPI_USR_MISO |
SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY);
// Enable functions based on number of bits. 0 bits = disabled.
// This is rather inefficient but allows for a very generic function.
// CMD ADDR and MOSI are set below to save on an extra if statement.
if (din_bits) {
if (dout_bits) {
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_DOUTDIN);
} else {
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO);
}
}
if (dummy_bits) {
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_DUMMY);
}
// Setup Bitlengths
WRITE_PERI_REG(SPI_USER1(spi_no),
// Number of bits in Address
((addr_bits - 1) & SPI_USR_ADDR_BITLEN) << SPI_USR_ADDR_BITLEN_S |
// Number of bits to Send
((dout_bits - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S |
// Number of bits to receive
((din_bits - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S |
// Number of Dummy bits to insert
((dummy_bits - 1) & SPI_USR_DUMMY_CYCLELEN) << SPI_USR_DUMMY_CYCLELEN_S);
// Setup Command Data
if (cmd_bits) {
// Enable COMMAND function in SPI module
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_COMMAND);
// Align command data to high bits
uint16_t command = cmd_data << (16-cmd_bits);
// Swap byte order
command = ((command>>8)&0xff) | ((command<<8)&0xff00);
WRITE_PERI_REG(SPI_USER2(spi_no), (
(((cmd_bits - 1) & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S) |
(command & SPI_USR_COMMAND_VALUE)
));
}
// Setup Address Data
if (addr_bits) {
// Enable ADDRess function in SPI module
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_ADDR);
// Align address data to high bits
WRITE_PERI_REG(SPI_ADDR(spi_no), addr_data << (32 - addr_bits));
}
// Setup DOUT data
if (dout_bits) {
// Enable MOSI function in SPI module
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI);
// Copy data to W0
if (READ_PERI_REG(SPI_USER(spi_no))&SPI_WR_BYTE_ORDER) {
WRITE_PERI_REG(SPI_W0(spi_no), dout_data << (32 - dout_bits));
} else {
uint8_t dout_extra_bits = dout_bits%8;
if (dout_extra_bits) {
// If your data isn't a byte multiple (8/16/24/32 bits) and you
// don't have SPI_WR_BYTE_ORDER set, you need this to move the
// non-8bit remainder to the MSBs. Not sure if there's even a use
// case for this, but it's here if you need it... For example,
// 0xDA4 12 bits without SPI_WR_BYTE_ORDER would usually be output
// as if it were 0x0DA4, of which 0xA4, and then 0x0 would be
// shifted out (first 8 bits of low byte, then 4 MSB bits of high
// byte - ie reverse byte order).
// The code below shifts it out as 0xA4 followed by 0xD as you
// might require.
WRITE_PERI_REG(SPI_W0(spi_no), (
(0xFFFFFFFF << (dout_bits - dout_extra_bits) & dout_data)
<< (8-dout_extra_bits) |
((0xFFFFFFFF >> (32 - (dout_bits - dout_extra_bits)))
& dout_data)
));
} else {
WRITE_PERI_REG(SPI_W0(spi_no), dout_data);
}
}
}
// Begin SPI Transaction
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
// Return DIN data
if (din_bits) {
while (spi_busy(spi_no)) {}; // Wait for SPI transaction to complete
if (READ_PERI_REG(SPI_USER(spi_no))&SPI_RD_BYTE_ORDER) {
// Assuming data in is written to MSB. TBC
return READ_PERI_REG(SPI_W0(spi_no)) >> (32 - din_bits);
} else {
// Read in the same way as DOUT is sent. Note existing contents of
// SPI_W0 remain unless overwritten!
return READ_PERI_REG(SPI_W0(spi_no));
}
return 0; // Something went wrong
}
// Transaction completed
return 1; // Success
}
/*
Just do minimal work needed to send 8 bits.
*/
inline void spi_tx8fast(uint8_t spi_no, uint8_t dout_data) {
while (spi_busy(spi_no)) {}; // Wait for SPI to be ready
// Enable SPI Functions
// Disable MOSI, MISO, ADDR, COMMAND, DUMMY in case previously set.
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI | SPI_USR_MISO |
SPI_USR_COMMAND | SPI_USR_ADDR | SPI_USR_DUMMY);
// Setup Bitlengths
WRITE_PERI_REG(SPI_USER1(spi_no),
// Number of bits to Send
((8 - 1) & SPI_USR_MOSI_BITLEN) << SPI_USR_MOSI_BITLEN_S |
// Number of bits to receive
((8 - 1) & SPI_USR_MISO_BITLEN) << SPI_USR_MISO_BITLEN_S);
// Setup DOUT data
// Enable MOSI function in SPI module
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI);
// Copy data to W0
if (READ_PERI_REG(SPI_USER(spi_no)) & SPI_WR_BYTE_ORDER) {
WRITE_PERI_REG(SPI_W0(spi_no), dout_data << (32 - 8));
} else {
WRITE_PERI_REG(SPI_W0(spi_no), dout_data);
}
// Begin SPI Transaction
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
}

79
esp8266/hspi.h Normal file
View File

@@ -0,0 +1,79 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 David Ogilvy (MetalPhreak)
* Modified 2016 by Radomir Dopieralski
*
* 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 SPI_APP_H
#define SPI_APP_H
#include "hspi_register.h"
#include "ets_sys.h"
#include "osapi.h"
#include "os_type.h"
// Define SPI hardware modules
#define SPI 0
#define HSPI 1
#define SPI_CLK_USE_DIV 0
#define SPI_CLK_80MHZ_NODIV 1
#define SPI_BYTE_ORDER_HIGH_TO_LOW 1
#define SPI_BYTE_ORDER_LOW_TO_HIGH 0
#ifndef CPU_CLK_FREQ //Should already be defined in eagle_soc.h
#define CPU_CLK_FREQ (80 * 1000000)
#endif
// Define some default SPI clock settings
#define SPI_CLK_PREDIV 10
#define SPI_CLK_CNTDIV 2
#define SPI_CLK_FREQ (CPU_CLK_FREQ / (SPI_CLK_PREDIV * SPI_CLK_CNTDIV))
// 80 / 20 = 4 MHz
void spi_init(uint8_t spi_no);
void spi_mode(uint8_t spi_no, uint8_t spi_cpha,uint8_t spi_cpol);
void spi_init_gpio(uint8_t spi_no, uint8_t sysclk_as_spiclk);
void spi_clock(uint8_t spi_no, uint16_t prediv, uint8_t cntdiv);
void spi_tx_byte_order(uint8_t spi_no, uint8_t byte_order);
void spi_rx_byte_order(uint8_t spi_no, uint8_t byte_order);
uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data,
uint32_t addr_bits, uint32_t addr_data,
uint32_t dout_bits, uint32_t dout_data,
uint32_t din_bits, uint32_t dummy_bits);
void spi_tx8fast(uint8_t spi_no, uint8_t dout_data);
// Expansion Macros
#define spi_busy(spi_no) READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR
#define spi_txd(spi_no, bits, data) spi_transaction(spi_no, 0, 0, 0, 0, bits, (uint32_t) data, 0, 0)
#define spi_tx8(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 8, (uint32_t) data, 0, 0)
#define spi_tx16(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 16, (uint32_t) data, 0, 0)
#define spi_tx32(spi_no, data) spi_transaction(spi_no, 0, 0, 0, 0, 32, (uint32_t) data, 0, 0)
#define spi_rxd(spi_no, bits) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, bits, 0)
#define spi_rx8(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 8, 0)
#define spi_rx16(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 16, 0)
#define spi_rx32(spi_no) spi_transaction(spi_no, 0, 0, 0, 0, 0, 0, 32, 0)
#endif

278
esp8266/hspi_register.h Normal file
View File

@@ -0,0 +1,278 @@
/*
* Copyright (c) 2010 - 2011 Espressif System
* Modified by David Ogilvy (MetalPhreak)
* Based on original file included in SDK 1.0.0
*
* Missing defines from previous SDK versions have
* been added and are noted with comments. The
* names of these defines are likely to change.
*/
#ifndef SPI_REGISTER_H_INCLUDED
#define SPI_REGISTER_H_INCLUDED
#define REG_SPI_BASE(i) (0x60000200-i*0x100)
#define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0)
#define SPI_FLASH_READ (BIT(31)) //From previous SDK
#define SPI_FLASH_WREN (BIT(30)) //From previous SDK
#define SPI_FLASH_WRDI (BIT(29)) //From previous SDK
#define SPI_FLASH_RDID (BIT(28)) //From previous SDK
#define SPI_FLASH_RDSR (BIT(27)) //From previous SDK
#define SPI_FLASH_WRSR (BIT(26)) //From previous SDK
#define SPI_FLASH_PP (BIT(25)) //From previous SDK
#define SPI_FLASH_SE (BIT(24)) //From previous SDK
#define SPI_FLASH_BE (BIT(23)) //From previous SDK
#define SPI_FLASH_CE (BIT(22)) //From previous SDK
#define SPI_FLASH_DP (BIT(21)) //From previous SDK
#define SPI_FLASH_RES (BIT(20)) //From previous SDK
#define SPI_FLASH_HPM (BIT(19)) //From previous SDK
#define SPI_USR (BIT(18))
#define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4)
#define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8)
#define SPI_WR_BIT_ORDER (BIT(26))
#define SPI_RD_BIT_ORDER (BIT(25))
#define SPI_QIO_MODE (BIT(24))
#define SPI_DIO_MODE (BIT(23))
#define SPI_TWO_BYTE_STATUS_EN (BIT(22)) //From previous SDK
#define SPI_WP_REG (BIT(21)) //From previous SDK
#define SPI_QOUT_MODE (BIT(20))
#define SPI_SHARE_BUS (BIT(19)) //From previous SDK
#define SPI_HOLD_MODE (BIT(18)) //From previous SDK
#define SPI_ENABLE_AHB (BIT(17)) //From previous SDK
#define SPI_SST_AAI (BIT(16)) //From previous SDK
#define SPI_RESANDRES (BIT(15)) //From previous SDK
#define SPI_DOUT_MODE (BIT(14))
#define SPI_FASTRD_MODE (BIT(13))
#define SPI_CTRL1(i) (REG_SPI_BASE (i) + 0xC) //From previous SDK. Removed _FLASH_ from name to match other registers.
#define SPI_CS_HOLD_DELAY 0x0000000F //Espressif BBS
#define SPI_CS_HOLD_DELAY_S 28 //Espressif BBS
#define SPI_CS_HOLD_DELAY_RES 0x00000FFF //Espressif BBS
#define SPI_CS_HOLD_DELAY_RES_S 16 //Espressif BBS
#define SPI_BUS_TIMER_LIMIT 0x0000FFFF //From previous SDK
#define SPI_BUS_TIMER_LIMIT_S 0 //From previous SDK
#define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10)
#define SPI_STATUS_EXT 0x000000FF //From previous SDK
#define SPI_STATUS_EXT_S 24 //From previous SDK
#define SPI_WB_MODE 0x000000FF //From previous SDK
#define SPI_WB_MODE_S 16 //From previous SDK
#define SPI_FLASH_STATUS_PRO_FLAG (BIT(7)) //From previous SDK
#define SPI_FLASH_TOP_BOT_PRO_FLAG (BIT(5)) //From previous SDK
#define SPI_FLASH_BP2 (BIT(4)) //From previous SDK
#define SPI_FLASH_BP1 (BIT(3)) //From previous SDK
#define SPI_FLASH_BP0 (BIT(2)) //From previous SDK
#define SPI_FLASH_WRENABLE_FLAG (BIT(1)) //From previous SDK
#define SPI_FLASH_BUSY_FLAG (BIT(0)) //From previous SDK
#define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14)
#define SPI_CS_DELAY_NUM 0x0000000F
#define SPI_CS_DELAY_NUM_S 28
#define SPI_CS_DELAY_MODE 0x00000003
#define SPI_CS_DELAY_MODE_S 26
#define SPI_MOSI_DELAY_NUM 0x00000007
#define SPI_MOSI_DELAY_NUM_S 23
#define SPI_MOSI_DELAY_MODE 0x00000003 //mode 0 : posedge; data set at positive edge of clk
//mode 1 : negedge + 1 cycle delay, only if freq<10MHz ; data set at negitive edge of clk
//mode 2 : Do not use this mode.
#define SPI_MOSI_DELAY_MODE_S 21
#define SPI_MISO_DELAY_NUM 0x00000007
#define SPI_MISO_DELAY_NUM_S 18
#define SPI_MISO_DELAY_MODE 0x00000003
#define SPI_MISO_DELAY_MODE_S 16
#define SPI_CK_OUT_HIGH_MODE 0x0000000F
#define SPI_CK_OUT_HIGH_MODE_S 12
#define SPI_CK_OUT_LOW_MODE 0x0000000F
#define SPI_CK_OUT_LOW_MODE_S 8
#define SPI_HOLD_TIME 0x0000000F
#define SPI_HOLD_TIME_S 4
#define SPI_SETUP_TIME 0x0000000F
#define SPI_SETUP_TIME_S 0
#define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18)
#define SPI_CLK_EQU_SYSCLK (BIT(31))
#define SPI_CLKDIV_PRE 0x00001FFF
#define SPI_CLKDIV_PRE_S 18
#define SPI_CLKCNT_N 0x0000003F
#define SPI_CLKCNT_N_S 12
#define SPI_CLKCNT_H 0x0000003F
#define SPI_CLKCNT_H_S 6
#define SPI_CLKCNT_L 0x0000003F
#define SPI_CLKCNT_L_S 0
#define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C)
#define SPI_USR_COMMAND (BIT(31))
#define SPI_USR_ADDR (BIT(30))
#define SPI_USR_DUMMY (BIT(29))
#define SPI_USR_MISO (BIT(28))
#define SPI_USR_MOSI (BIT(27))
#define SPI_USR_DUMMY_IDLE (BIT(26)) //From previous SDK
#define SPI_USR_MOSI_HIGHPART (BIT(25))
#define SPI_USR_MISO_HIGHPART (BIT(24))
#define SPI_USR_PREP_HOLD (BIT(23)) //From previous SDK
#define SPI_USR_CMD_HOLD (BIT(22)) //From previous SDK
#define SPI_USR_ADDR_HOLD (BIT(21)) //From previous SDK
#define SPI_USR_DUMMY_HOLD (BIT(20)) //From previous SDK
#define SPI_USR_DIN_HOLD (BIT(19)) //From previous SDK
#define SPI_USR_DOUT_HOLD (BIT(18)) //From previous SDK
#define SPI_USR_HOLD_POL (BIT(17)) //From previous SDK
#define SPI_SIO (BIT(16))
#define SPI_FWRITE_QIO (BIT(15))
#define SPI_FWRITE_DIO (BIT(14))
#define SPI_FWRITE_QUAD (BIT(13))
#define SPI_FWRITE_DUAL (BIT(12))
#define SPI_WR_BYTE_ORDER (BIT(11))
#define SPI_RD_BYTE_ORDER (BIT(10))
#define SPI_AHB_ENDIAN_MODE 0x00000003 //From previous SDK
#define SPI_AHB_ENDIAN_MODE_S 8 //From previous SDK
#define SPI_CK_OUT_EDGE (BIT(7))
#define SPI_CK_I_EDGE (BIT(6))
#define SPI_CS_SETUP (BIT(5))
#define SPI_CS_HOLD (BIT(4))
#define SPI_AHB_USR_COMMAND (BIT(3)) //From previous SDK
#define SPI_FLASH_MODE (BIT(2))
#define SPI_AHB_USR_COMMAND_4BYTE (BIT(1)) //From previous SDK
#define SPI_DOUTDIN (BIT(0)) //From previous SDK
//AHB = http://en.wikipedia.org/wiki/Advanced_Microcontroller_Bus_Architecture ?
#define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20)
#define SPI_USR_ADDR_BITLEN 0x0000003F
#define SPI_USR_ADDR_BITLEN_S 26
#define SPI_USR_MOSI_BITLEN 0x000001FF
#define SPI_USR_MOSI_BITLEN_S 17
#define SPI_USR_MISO_BITLEN 0x000001FF
#define SPI_USR_MISO_BITLEN_S 8
#define SPI_USR_DUMMY_CYCLELEN 0x000000FF
#define SPI_USR_DUMMY_CYCLELEN_S 0
#define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24)
#define SPI_USR_COMMAND_BITLEN 0x0000000F
#define SPI_USR_COMMAND_BITLEN_S 28
#define SPI_USR_COMMAND_VALUE 0x0000FFFF
#define SPI_USR_COMMAND_VALUE_S 0
#define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28)
//previously defined as SPI_FLASH_USER3. No further info available.
#define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C)
#define SPI_IDLE_EDGE (BIT(29))
#define SPI_CS2_DIS (BIT(2))
#define SPI_CS1_DIS (BIT(1))
#define SPI_CS0_DIS (BIT(0))
#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30)
#define SPI_SYNC_RESET (BIT(31))
#define SPI_SLAVE_MODE (BIT(30))
#define SPI_SLV_WR_RD_BUF_EN (BIT(29))
#define SPI_SLV_WR_RD_STA_EN (BIT(28))
#define SPI_SLV_CMD_DEFINE (BIT(27))
#define SPI_TRANS_CNT 0x0000000F
#define SPI_TRANS_CNT_S 23
#define SPI_SLV_LAST_STATE 0x00000007 //From previous SDK
#define SPI_SLV_LAST_STATE_S 20 //From previous SDK
#define SPI_SLV_LAST_COMMAND 0x00000007 //From previous SDK
#define SPI_SLV_LAST_COMMAND_S 17 //From previous SDK
#define SPI_CS_I_MODE 0x00000003 //From previous SDK
#define SPI_CS_I_MODE_S 10 //From previous SDK
#define SPI_TRANS_DONE_EN (BIT(9))
#define SPI_SLV_WR_STA_DONE_EN (BIT(8))
#define SPI_SLV_RD_STA_DONE_EN (BIT(7))
#define SPI_SLV_WR_BUF_DONE_EN (BIT(6))
#define SPI_SLV_RD_BUF_DONE_EN (BIT(5))
#define SLV_SPI_INT_EN 0x0000001f
#define SLV_SPI_INT_EN_S 5
#define SPI_TRANS_DONE (BIT(4))
#define SPI_SLV_WR_STA_DONE (BIT(3))
#define SPI_SLV_RD_STA_DONE (BIT(2))
#define SPI_SLV_WR_BUF_DONE (BIT(1))
#define SPI_SLV_RD_BUF_DONE (BIT(0))
#define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34)
#define SPI_SLV_STATUS_BITLEN 0x0000001F
#define SPI_SLV_STATUS_BITLEN_S 27
#define SPI_SLV_STATUS_FAST_EN (BIT(26)) //From previous SDK
#define SPI_SLV_STATUS_READBACK (BIT(25)) //From previous SDK
#define SPI_SLV_BUF_BITLEN 0x000001FF
#define SPI_SLV_BUF_BITLEN_S 16
#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F
#define SPI_SLV_RD_ADDR_BITLEN_S 10
#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F
#define SPI_SLV_WR_ADDR_BITLEN_S 4
#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3))
#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2))
#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1))
#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0))
#define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38)
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0
#define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C)
#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF
#define SPI_SLV_WRSTA_CMD_VALUE_S 24
#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF
#define SPI_SLV_RDSTA_CMD_VALUE_S 16
#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF
#define SPI_SLV_WRBUF_CMD_VALUE_S 8
#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF
#define SPI_SLV_RDBUF_CMD_VALUE_S 0
//Previous SDKs referred to these following registers as SPI_C0 etc.
#define SPI_W0(i) (REG_SPI_BASE(i) +0x40)
#define SPI_W1(i) (REG_SPI_BASE(i) +0x44)
#define SPI_W2(i) (REG_SPI_BASE(i) +0x48)
#define SPI_W3(i) (REG_SPI_BASE(i) +0x4C)
#define SPI_W4(i) (REG_SPI_BASE(i) +0x50)
#define SPI_W5(i) (REG_SPI_BASE(i) +0x54)
#define SPI_W6(i) (REG_SPI_BASE(i) +0x58)
#define SPI_W7(i) (REG_SPI_BASE(i) +0x5C)
#define SPI_W8(i) (REG_SPI_BASE(i) +0x60)
#define SPI_W9(i) (REG_SPI_BASE(i) +0x64)
#define SPI_W10(i) (REG_SPI_BASE(i) +0x68)
#define SPI_W11(i) (REG_SPI_BASE(i) +0x6C)
#define SPI_W12(i) (REG_SPI_BASE(i) +0x70)
#define SPI_W13(i) (REG_SPI_BASE(i) +0x74)
#define SPI_W14(i) (REG_SPI_BASE(i) +0x78)
#define SPI_W15(i) (REG_SPI_BASE(i) +0x7C)
// +0x80 to +0xBC could be SPI_W16 through SPI_W31?
// +0xC0 to +0xEC not currently defined.
#define SPI_EXT0(i) (REG_SPI_BASE(i) + 0xF0) //From previous SDK. Removed _FLASH_ from name to match other registers.
#define SPI_T_PP_ENA (BIT(31)) //From previous SDK
#define SPI_T_PP_SHIFT 0x0000000F //From previous SDK
#define SPI_T_PP_SHIFT_S 16 //From previous SDK
#define SPI_T_PP_TIME 0x00000FFF //From previous SDK
#define SPI_T_PP_TIME_S 0 //From previous SDK
#define SPI_EXT1(i) (REG_SPI_BASE(i) + 0xF4) //From previous SDK. Removed _FLASH_ from name to match other registers.
#define SPI_T_ERASE_ENA (BIT(31)) //From previous SDK
#define SPI_T_ERASE_SHIFT 0x0000000F //From previous SDK
#define SPI_T_ERASE_SHIFT_S 16 //From previous SDK
#define SPI_T_ERASE_TIME 0x00000FFF //From previous SDK
#define SPI_T_ERASE_TIME_S 0 //From previous SDK
#define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8) //From previous SDK. Removed _FLASH_ from name to match other registers.
#define SPI_ST 0x00000007 //From previous SDK
#define SPI_ST_S 0 //From previous SDK
#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC)
#define SPI_INT_HOLD_ENA 0x00000003
#define SPI_INT_HOLD_ENA_S 0
#endif // SPI_REGISTER_H_INCLUDED

View File

@@ -49,8 +49,8 @@ STATIC void mp_reset(void) {
mp_init();
mp_obj_list_init(mp_sys_path, 0);
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script)
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_));
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib));
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_));
mp_obj_list_init(mp_sys_argv, 0);
#if MICROPY_VFS_FAT
memset(MP_STATE_PORT(fs_user_mount), 0, sizeof(MP_STATE_PORT(fs_user_mount)));
@@ -141,10 +141,6 @@ mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) {
}
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
void mp_keyboard_interrupt(void) {
MP_STATE_VM(mp_pending_exception) = MP_STATE_PORT(mp_kbd_exception);
}
void nlr_jump_fail(void *val) {
printf("NLR jump failed\n");
for (;;) {

View File

@@ -583,7 +583,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 ? MP_ETIMEDOUT : MP_EIO)));
mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_read_obj, esp_flash_read);
@@ -598,9 +598,7 @@ STATIC mp_obj_t esp_flash_write(mp_obj_t offset_in, const mp_obj_t buf_in) {
if (res == SPI_FLASH_RESULT_OK) {
return mp_const_none;
}
nlr_raise(mp_obj_new_exception_arg1(
&mp_type_OSError,
MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO)));
mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_write_obj, esp_flash_write);
@@ -610,9 +608,7 @@ STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) {
if (res == SPI_FLASH_RESULT_OK) {
return mp_const_none;
}
nlr_raise(mp_obj_new_exception_arg1(
&mp_type_OSError,
MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO)));
mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_flash_erase_obj, esp_flash_erase);
@@ -714,7 +710,9 @@ STATIC const mp_map_elem_t esp_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&esp_socket_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_getaddrinfo_obj },
#endif
#if MICROPY_ESP8266_NEOPIXEL
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&esp_neopixel_write_obj },
#endif
#if MICROPY_ESP8266_APA102
{ MP_OBJ_NEW_QSTR(MP_QSTR_apa102_write), (mp_obj_t)&esp_apa102_write_obj },
#endif
@@ -748,6 +746,5 @@ STATIC MP_DEFINE_CONST_DICT(esp_module_globals, esp_module_globals_table);
const mp_obj_module_t esp_module = {
.base = { &mp_type_module },
.name = MP_QSTR_esp,
.globals = (mp_obj_dict_t*)&esp_module_globals,
};

View File

@@ -49,6 +49,8 @@
//#define MACHINE_WAKE_SLEEP (0x02)
#define MACHINE_WAKE_DEEPSLEEP (0x04)
extern const mp_obj_type_t esp_wdt_type;
STATIC mp_obj_t machine_freq(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
// get
@@ -84,8 +86,10 @@ STATIC mp_obj_t machine_unique_id(void) {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id);
STATIC mp_obj_t machine_idle(void) {
uint32_t t = mp_hal_ticks_cpu();
asm("waiti 0");
return mp_const_none;
t = mp_hal_ticks_cpu() - t;
return MP_OBJ_NEW_SMALL_INT(t);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
@@ -246,27 +250,29 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ 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_WDT), MP_ROM_PTR(&esp_wdt_type) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pyb_pin_type) },
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&pyb_pwm_type) },
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_spi_type) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_hspi_type) },
// wake abilities
{ MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(MACHINE_WAKE_DEEPSLEEP) },
// reset causes
{ MP_ROM_QSTR(MP_QSTR_PWR_ON_RESET), MP_ROM_INT(REASON_EXT_SYS_RST) },
{ MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(REASON_DEFAULT_RST) },
{ MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(REASON_EXT_SYS_RST) },
{ MP_ROM_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_ROM_INT(REASON_DEEP_SLEEP_AWAKE) },
{ MP_ROM_QSTR(MP_QSTR_WDT_RESET), MP_ROM_INT(REASON_WDT_RST) },
{ MP_ROM_QSTR(MP_QSTR_SOFT_RESET), MP_ROM_INT(REASON_SOFT_RESTART) },
};
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
const mp_obj_module_t mp_module_machine = {
.base = { &mp_type_module },
.name = MP_QSTR_umachine,
.globals = (mp_obj_dict_t*)&machine_module_globals,
};

85
esp8266/modmachinewdt.c Normal file
View File

@@ -0,0 +1,85 @@
/*
* 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 <stdio.h>
#include <string.h>
#include "py/nlr.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "user_interface.h"
#include "etshal.h"
const mp_obj_type_t esp_wdt_type;
typedef struct _machine_wdt_obj_t {
mp_obj_base_t base;
} machine_wdt_obj_t;
STATIC machine_wdt_obj_t wdt_default = {{&esp_wdt_type}};
STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_int_t id = 0;
if (n_args > 0) {
id = mp_obj_get_int(args[0]);
}
switch (id) {
case 0:
return &wdt_default;
default:
mp_raise_ValueError("");
}
}
STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) {
(void)self_in;
system_soft_wdt_feed();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed);
STATIC mp_obj_t machine_wdt_deinit(mp_obj_t self_in) {
(void)self_in;
ets_wdt_disable();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_deinit_obj, machine_wdt_deinit);
STATIC const mp_map_elem_t machine_wdt_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_feed), (mp_obj_t)&machine_wdt_feed_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&machine_wdt_deinit_obj },
};
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
const mp_obj_type_t esp_wdt_type = {
{ &mp_type_type },
.name = MP_QSTR_WDT,
.make_new = machine_wdt_make_new,
.locals_dict = (mp_obj_t)&machine_wdt_locals_dict,
};

View File

@@ -130,17 +130,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_status_obj, esp_status);
STATIC mp_obj_t *esp_scan_list = NULL;
STATIC void esp_scan_cb(scaninfo *si, STATUS status) {
STATIC void esp_scan_cb(void *result, STATUS status) {
if (esp_scan_list == NULL) {
// called unexpectedly
return;
}
if (si->pbss && status == 0) {
if (result && status == 0) {
// 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) {
for (struct bss_info *bs = result; bs; bs = STAILQ_NEXT(bs, next)) {
mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL);
#if 1
// struct bss_info::ssid_len is not documented in SDK API Guide,
@@ -485,6 +484,5 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals
const mp_obj_module_t network_module = {
.base = { &mp_type_module },
.name = MP_QSTR_network,
.globals = (mp_obj_dict_t*)&mp_module_network_globals,
};

View File

@@ -117,6 +117,5 @@ STATIC MP_DEFINE_CONST_DICT(onewire_module_globals, onewire_module_globals_table
const mp_obj_module_t onewire_module = {
.base = { &mp_type_module },
.name = MP_QSTR_onewire,
.globals = (mp_obj_dict_t*)&onewire_module_globals,
};

View File

@@ -10,6 +10,8 @@ extern const mp_obj_type_t pyb_rtc_type;
extern const mp_obj_type_t pyb_uart_type;
extern const mp_obj_type_t pyb_i2c_type;
extern const mp_obj_type_t pyb_spi_type;
extern const mp_obj_type_t pyb_hspi_type;
extern const mp_obj_type_t machine_spi_type;
MP_DECLARE_CONST_FUN_OBJ(pyb_info_obj);

212
esp8266/modpybhspi.c Normal file
View File

@@ -0,0 +1,212 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "ets_sys.h"
#include "etshal.h"
#include "ets_alt_task.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mphal.h"
#include "extmod/machine_spi.h"
#include "hspi.h"
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);
typedef struct _pyb_hspi_obj_t {
mp_obj_base_t base;
uint32_t baudrate;
uint8_t polarity;
uint8_t phase;
} pyb_hspi_obj_t;
STATIC void hspi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
(void)self_in;
if (dest == NULL) {
// fast case when we only need to write data
size_t chunk_size = 1024;
size_t count = len / chunk_size;
size_t i = 0;
for (size_t j = 0; j < count; ++j) {
for (size_t k = 0; k < chunk_size; ++k) {
spi_tx8fast(HSPI, src[i]);
++i;
}
ets_loop_iter();
}
while (i < len) {
spi_tx8fast(HSPI, src[i]);
++i;
}
} else {
// we need to read and write data
// Process data in chunks, let the pending tasks run in between
size_t chunk_size = 1024; // TODO this should depend on baudrate
size_t count = len / chunk_size;
size_t i = 0;
for (size_t j = 0; j < count; ++j) {
for (size_t k = 0; k < chunk_size; ++k) {
dest[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, src[i], 8, 0);
++i;
}
ets_loop_iter();
}
while (i < len) {
dest[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, src[i], 8, 0);
++i;
}
}
}
/******************************************************************************/
// MicroPython bindings for HSPI
STATIC void pyb_hspi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_hspi_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "HSPI(id=1, baudrate=%u, polarity=%u, phase=%u)",
self->baudrate, self->polarity, self->phase);
}
STATIC void pyb_hspi_init_helper(pyb_hspi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args),
allowed_args, args);
if (args[ARG_baudrate].u_int != -1) {
self->baudrate = args[ARG_baudrate].u_int;
}
if (args[ARG_polarity].u_int != -1) {
self->polarity = args[ARG_polarity].u_int;
}
if (args[ARG_phase].u_int != -1) {
self->phase = args[ARG_phase].u_int;
}
if (self->baudrate == 80000000L) {
// Special case for full speed.
spi_init_gpio(HSPI, SPI_CLK_80MHZ_NODIV);
spi_clock(HSPI, 0, 0);
} else if (self->baudrate > 40000000L) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"impossible baudrate"));
} else {
uint32_t divider = 40000000L / self->baudrate;
uint16_t prediv = MIN(divider, SPI_CLKDIV_PRE + 1);
uint16_t cntdiv = (divider / prediv) * 2; // cntdiv has to be even
if (cntdiv > SPI_CLKCNT_N + 1 || cntdiv == 0 || prediv == 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"impossible baudrate"));
}
self->baudrate = 80000000L / (prediv * cntdiv);
spi_init_gpio(HSPI, SPI_CLK_USE_DIV);
spi_clock(HSPI, prediv, cntdiv);
}
// TODO: Make the byte order configurable too (discuss param names)
spi_tx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW);
spi_rx_byte_order(HSPI, SPI_BYTE_ORDER_HIGH_TO_LOW);
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_FLASH_MODE | SPI_USR_MISO |
SPI_USR_ADDR | SPI_USR_COMMAND | SPI_USR_DUMMY);
// Clear Dual or Quad lines transmission mode
CLEAR_PERI_REG_MASK(SPI_CTRL(HSPI), SPI_QIO_MODE | SPI_DIO_MODE |
SPI_DOUT_MODE | SPI_QOUT_MODE);
spi_mode(HSPI, self->phase, self->polarity);
}
mp_obj_t pyb_hspi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, true);
mp_int_t id = -1;
if (n_args > 0) {
id = mp_obj_get_int(args[0]);
}
if (id == -1) {
// Multiplex to bitbanging SPI
if (n_args > 0) {
args++;
}
return pyb_spi_make_new(type, 0, n_kw, args);
}
if (id != 1) {
// FlashROM is on SPI0, so far we don't support its usage
mp_raise_ValueError("");
}
pyb_hspi_obj_t *self = m_new_obj(pyb_hspi_obj_t);
self->base.type = &pyb_hspi_type;
// set defaults
self->baudrate = 80000000L;
self->polarity = 0;
self->phase = 0;
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
pyb_hspi_init_helper(self, n_args, args, &kw_args);
return MP_OBJ_FROM_PTR(self);
}
STATIC mp_obj_t pyb_hspi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_hspi_init_helper(args[0], n_args - 1, args + 1, kw_args);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_hspi_init_obj, 1, pyb_hspi_init);
STATIC const mp_rom_map_elem_t pyb_hspi_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_hspi_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_hspi_locals_dict, pyb_hspi_locals_dict_table);
STATIC const mp_machine_spi_p_t pyb_hspi_p = {
.transfer = hspi_transfer,
};
const mp_obj_type_t pyb_hspi_type = {
{ &mp_type_type },
.name = MP_QSTR_HSPI,
.print = pyb_hspi_print,
.make_new = pyb_hspi_make_new,
.protocol = &pyb_hspi_p,
.locals_dict = (mp_obj_dict_t*)&pyb_hspi_locals_dict,
};

View File

@@ -244,7 +244,11 @@ STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, mp_uint_t n_args, c
// configure the GPIO as requested
if (self->phys_port == 16) {
// TODO: Set pull up/pull down
// only pull-down seems to be supported by the hardware, and
// we only expose pull-up behaviour in software
if (pull != GPIO_PULL_NONE) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin(16) doesn't support pull"));
}
} else {
PIN_FUNC_SELECT(self->periph, self->func);
#if 0
@@ -301,7 +305,7 @@ STATIC mp_obj_t pyb_pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
pyb_pin_obj_t *self = self_in;
if (n_args == 0) {
// get pin
return MP_OBJ_NEW_SMALL_INT(GPIO_INPUT_GET(self->phys_port));
return MP_OBJ_NEW_SMALL_INT(pin_get(self->phys_port));
} else {
// set pin
pin_set(self->phys_port, mp_obj_is_true(args[0]));

View File

@@ -212,13 +212,28 @@ STATIC mp_obj_t pyb_rtc_alarm(mp_obj_t self_in, mp_obj_t alarm_id, mp_obj_t time
}
// set expiry time (in microseconds)
pyb_rtc_alarm0_expiry = pyb_rtc_get_us_since_2000() + mp_obj_get_int(time_in) * 1000;
pyb_rtc_alarm0_expiry = pyb_rtc_get_us_since_2000() + (uint64_t)mp_obj_get_int(time_in) * 1000;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_rtc_alarm_obj, pyb_rtc_alarm);
STATIC mp_obj_t pyb_rtc_alarm_left(size_t n_args, const mp_obj_t *args) {
// check we want alarm0
if (n_args > 1 && mp_obj_get_int(args[1]) != 0) {
mp_raise_ValueError("invalid alarm");
}
uint64_t now = pyb_rtc_get_us_since_2000();
if (pyb_rtc_alarm0_expiry <= now) {
return MP_OBJ_NEW_SMALL_INT(0);
} else {
return mp_obj_new_int((pyb_rtc_alarm0_expiry - now) / 1000);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_alarm_left_obj, 1, 2, pyb_rtc_alarm_left);
STATIC mp_obj_t pyb_rtc_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_trigger, ARG_wake };
static const mp_arg_t allowed_args[] = {
@@ -244,6 +259,7 @@ STATIC const mp_map_elem_t pyb_rtc_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_datetime), (mp_obj_t)&pyb_rtc_datetime_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_memory), (mp_obj_t)&pyb_rtc_memory_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_alarm), (mp_obj_t)&pyb_rtc_alarm_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_alarm_left), (mp_obj_t)&pyb_rtc_alarm_left_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_rtc_irq_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ALARM0), MP_OBJ_NEW_SMALL_INT(0) },
};

View File

@@ -28,71 +28,35 @@
#include <stdint.h>
#include <string.h>
#include "ets_sys.h"
#include "etshal.h"
#include "ets_alt_task.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mphal.h"
typedef struct _pyb_spi_obj_t {
mp_obj_base_t base;
uint32_t baudrate;
uint8_t polarity;
uint8_t phase;
mp_hal_pin_obj_t sck;
mp_hal_pin_obj_t mosi;
mp_hal_pin_obj_t miso;
} pyb_spi_obj_t;
STATIC void mp_hal_spi_transfer(pyb_spi_obj_t *self, size_t src_len, const uint8_t *src_buf, size_t dest_len, uint8_t *dest_buf) {
// only MSB transfer is implemented
uint32_t delay_half = 500000 / self->baudrate + 1;
for (size_t i = 0; i < src_len || i < dest_len; ++i) {
uint8_t data_out;
if (src_len == 1) {
data_out = src_buf[0];
} else {
data_out = src_buf[i];
}
uint8_t data_in = 0;
for (int j = 0; j < 8; ++j, data_out <<= 1) {
mp_hal_pin_write(self->mosi, (data_out >> 7) & 1);
if (self->phase == 0) {
ets_delay_us(delay_half);
mp_hal_pin_write(self->sck, 1 - self->polarity);
} else {
mp_hal_pin_write(self->sck, 1 - self->polarity);
ets_delay_us(delay_half);
}
data_in = (data_in << 1) | mp_hal_pin_read(self->miso);
if (self->phase == 0) {
ets_delay_us(delay_half);
mp_hal_pin_write(self->sck, self->polarity);
} else {
mp_hal_pin_write(self->sck, self->polarity);
ets_delay_us(delay_half);
}
}
if (dest_len != 0) {
dest_buf[i] = data_in;
}
// make sure pending tasks have a chance to run
ets_loop_iter();
}
}
#include "extmod/machine_spi.h"
/******************************************************************************/
// MicroPython bindings for SPI
STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "SPI(baudrate=%u, polarity=%u, phase=%u, sck=%u, mosi=%u, miso=%u)",
self->baudrate, self->polarity, self->phase, self->sck, self->mosi, self->miso);
STATIC uint32_t baudrate_from_delay_half(uint32_t delay_half) {
return 500000 / delay_half;
}
STATIC void pyb_spi_init_helper(pyb_spi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC uint32_t baudrate_to_delay_half(uint32_t baudrate) {
uint32_t delay_half = 500000 / baudrate;
// round delay_half up so that: actual_baudrate <= requested_baudrate
if (500000 % baudrate != 0) {
delay_half += 1;
}
return delay_half;
}
STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "SPI(baudrate=%u, polarity=%u, phase=%u, sck=%u, mosi=%u, miso=%u)",
baudrate_from_delay_half(self->delay_half),
self->polarity, self->phase, self->sck, self->mosi, self->miso);
}
STATIC void pyb_spi_init_helper(mp_machine_soft_spi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_sck, ARG_mosi, ARG_miso };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
@@ -106,7 +70,7 @@ STATIC void pyb_spi_init_helper(pyb_spi_obj_t *self, size_t n_args, const mp_obj
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
if (args[ARG_baudrate].u_int != -1) {
self->baudrate = args[ARG_baudrate].u_int;
self->delay_half = baudrate_to_delay_half(args[ARG_baudrate].u_int);
}
if (args[ARG_polarity].u_int != -1) {
self->polarity = args[ARG_polarity].u_int;
@@ -131,12 +95,12 @@ STATIC void pyb_spi_init_helper(pyb_spi_obj_t *self, size_t n_args, const mp_obj
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) {
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) {
mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true);
pyb_spi_obj_t *self = m_new_obj(pyb_spi_obj_t);
mp_machine_soft_spi_obj_t *self = m_new_obj(mp_machine_soft_spi_obj_t);
self->base.type = &pyb_spi_type;
// set defaults
self->baudrate = 500000;
self->delay_half = baudrate_to_delay_half(500000);
self->polarity = 0;
self->phase = 0;
self->sck = 14;
@@ -154,69 +118,25 @@ STATIC mp_obj_t pyb_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_a
}
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_init_obj, 1, pyb_spi_init);
STATIC mp_obj_t pyb_spi_read(size_t n_args, const mp_obj_t *args) {
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(args[0]);
uint8_t write_byte = 0;
if (n_args == 3) {
write_byte = mp_obj_get_int(args[2]);
}
vstr_t vstr;
vstr_init_len(&vstr, mp_obj_get_int(args[1]));
mp_hal_spi_transfer(self, 1, &write_byte, vstr.len, (uint8_t*)vstr.buf);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_spi_read_obj, 2, 3, pyb_spi_read);
STATIC mp_obj_t pyb_spi_readinto(size_t n_args, const mp_obj_t *args) {
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(args[0]);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
uint8_t write_byte = 0;
if (n_args == 3) {
write_byte = mp_obj_get_int(args[2]);
}
mp_hal_spi_transfer(self, 1, &write_byte, bufinfo.len, (uint8_t*)bufinfo.buf);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_spi_readinto_obj, 2, 3, pyb_spi_readinto);
STATIC mp_obj_t pyb_spi_write(mp_obj_t self_in, mp_obj_t wr_buf_in) {
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t src_buf;
mp_get_buffer_raise(wr_buf_in, &src_buf, MP_BUFFER_READ);
mp_hal_spi_transfer(self, src_buf.len, (const uint8_t*)src_buf.buf, 0, NULL);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(pyb_spi_write_obj, pyb_spi_write);
STATIC mp_obj_t pyb_spi_write_readinto(mp_obj_t self_in, mp_obj_t wr_buf_in, mp_obj_t rd_buf_in) {
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t src_buf;
mp_get_buffer_raise(wr_buf_in, &src_buf, MP_BUFFER_READ);
mp_buffer_info_t dest_buf;
mp_get_buffer_raise(rd_buf_in, &dest_buf, MP_BUFFER_WRITE);
if (src_buf.len != dest_buf.len) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "buffers must be the same length"));
}
mp_hal_spi_transfer(self, src_buf.len, (const uint8_t*)src_buf.buf, dest_buf.len, (uint8_t*)dest_buf.buf);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(pyb_spi_write_readinto_obj, pyb_spi_write_readinto);
STATIC const mp_rom_map_elem_t pyb_spi_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_spi_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&pyb_spi_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&pyb_spi_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&pyb_spi_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&pyb_spi_write_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table);
STATIC const mp_machine_spi_p_t pyb_spi_p = {
.transfer = mp_machine_soft_spi_transfer,
};
const mp_obj_type_t pyb_spi_type = {
{ &mp_type_type },
.name = MP_QSTR_SPI,
.name = MP_QSTR_SoftSPI,
.print = pyb_spi_print,
.make_new = pyb_spi_make_new,
.protocol = &pyb_spi_p,
.locals_dict = (mp_obj_dict_t*)&pyb_spi_locals_dict,
};

View File

@@ -0,0 +1,46 @@
# DS18x20 temperature sensor driver for MicroPython.
# MIT license; Copyright (c) 2016 Damien P. George
_CONVERT = const(0x44)
_RD_SCRATCH = const(0xbe)
_WR_SCRATCH = const(0x4e)
class DS18X20:
def __init__(self, onewire):
self.ow = onewire
self.buf = bytearray(9)
def scan(self):
return [rom for rom in self.ow.scan() if rom[0] == 0x10 or rom[0] == 0x28]
def convert_temp(self):
self.ow.reset(True)
self.ow.writebyte(self.ow.SKIP_ROM)
self.ow.writebyte(_CONVERT)
def read_scratch(self, rom):
self.ow.reset(True)
self.ow.select_rom(rom)
self.ow.writebyte(_RD_SCRATCH)
self.ow.readinto(self.buf)
if self.ow.crc8(self.buf):
raise Exception('CRC error')
return self.buf
def write_scratch(self, rom, buf):
self.ow.reset(True)
self.ow.select_rom(rom)
self.ow.writebyte(_WR_SCRATCH)
self.ow.write(buf)
def read_temp(self, rom):
buf = self.read_scratch(rom)
if rom[0] == 0x10:
if buf[1]:
t = buf[0] >> 1 | 0x80
t = -((~t + 1) & 0xff)
else:
t = buf[0] >> 1
return t - 0.25 + (buf[7] - buf[6]) / buf[7]
else:
return (buf[1] << 8 | buf[0]) / 16

View File

@@ -15,8 +15,11 @@ class OneWire:
self.pin = pin
self.pin.init(pin.OPEN_DRAIN)
def reset(self):
return _ow.reset(self.pin)
def reset(self, required=False):
reset = _ow.reset(self.pin)
if required and not reset:
raise OneWireError
return reset
def readbit(self):
return _ow.readbit(self.pin)
@@ -24,11 +27,9 @@ class OneWire:
def readbyte(self):
return _ow.readbyte(self.pin)
def read(self, count):
buf = bytearray(count)
for i in range(count):
def readinto(self, buf):
for i in range(len(buf)):
buf[i] = _ow.readbyte(self.pin)
return buf
def writebit(self, value):
return _ow.writebit(self.pin, value)
@@ -87,41 +88,3 @@ class OneWire:
def crc8(self, data):
return _ow.crc8(data)
class DS18B20:
CONVERT = const(0x44)
RD_SCRATCH = const(0xbe)
WR_SCRATCH = const(0x4e)
def __init__(self, onewire):
self.ow = onewire
def scan(self):
return [rom for rom in self.ow.scan() if rom[0] == 0x28]
def convert_temp(self):
if not self.ow.reset():
raise OneWireError
self.ow.writebyte(SKIP_ROM)
self.ow.writebyte(CONVERT)
def read_scratch(self, rom):
if not self.ow.reset():
raise OneWireError
self.ow.select_rom(rom)
self.ow.writebyte(RD_SCRATCH)
buf = self.ow.read(9)
if self.ow.crc8(buf):
raise OneWireError
return buf
def write_scratch(self, rom, buf):
if not self.ow.reset():
raise OneWireError
self.ow.select_rom(rom)
self.ow.writebyte(WR_SCRATCH)
self.ow.write(buf)
def read_temp(self, rom):
buf = self.read_scratch(rom)
return (buf[1] << 8 | buf[0]) / 16

View File

@@ -74,7 +74,7 @@ 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(MP_ENODEV)));
mp_raise_OSError(MP_ENODEV);
}
mp_obj_t meth[n_args + 2];
@@ -123,6 +123,20 @@ STATIC mp_obj_t os_rename(mp_obj_t path_old, mp_obj_t path_new) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename);
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 mp_obj_t os_statvfs(mp_obj_t path_in) {
return vfs_proxy_call(MP_QSTR_statvfs, 1, &path_in);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_statvfs_obj, os_statvfs);
STATIC mp_obj_t os_umount(void) {
return vfs_proxy_call(MP_QSTR_umount, 0, NULL);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_umount_obj, os_umount);
#endif
STATIC mp_obj_t os_urandom(mp_obj_t num) {
@@ -143,11 +157,6 @@ 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) },
@@ -166,6 +175,8 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
{ 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) },
{ MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&os_statvfs_obj) },
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&os_umount_obj) },
#endif
};
@@ -173,6 +184,5 @@ STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
const mp_obj_module_t uos_module = {
.base = { &mp_type_module },
.name = MP_QSTR_uos,
.globals = (mp_obj_dict_t*)&os_module_globals,
};

View File

@@ -38,6 +38,7 @@
#include "modpybrtc.h"
#include "timeutils.h"
#include "user_interface.h"
#include "extmod/utime_mphal.h"
/// \module time - time related functions
///
@@ -99,53 +100,6 @@ STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
}
MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime);
/// \function sleep(seconds)
/// Sleep for the given number of seconds.
STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
#if MICROPY_PY_BUILTINS_FLOAT
mp_hal_delay_ms(1000 * mp_obj_get_float(seconds_o));
#else
mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o));
#endif
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep);
STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) {
mp_hal_delay_ms(mp_obj_get_int(arg));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_ms_obj, time_sleep_ms);
STATIC mp_obj_t time_sleep_us(mp_obj_t arg) {
mp_hal_delay_us(mp_obj_get_int(arg));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_us_obj, time_sleep_us);
STATIC mp_obj_t time_ticks_ms(void) {
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & MP_SMALL_INT_POSITIVE_MASK);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_ms_obj, time_ticks_ms);
STATIC mp_obj_t time_ticks_us(void) {
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_us() & MP_SMALL_INT_POSITIVE_MASK);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_us_obj, time_ticks_us);
STATIC mp_obj_t time_ticks_cpu(void) {
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_cpu() & MP_SMALL_INT_POSITIVE_MASK);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_cpu_obj, time_ticks_cpu);
STATIC mp_obj_t time_ticks_diff(mp_obj_t start_in, mp_obj_t end_in) {
// we assume that the arguments come from ticks_xx so are small ints
uint32_t start = MP_OBJ_SMALL_INT_VALUE(start_in);
uint32_t end = MP_OBJ_SMALL_INT_VALUE(end_in);
return MP_OBJ_NEW_SMALL_INT((end - start) & MP_SMALL_INT_POSITIVE_MASK);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(time_ticks_diff_obj, time_ticks_diff);
/// \function time()
/// Returns the number of seconds, as an integer, since 1/1/2000.
STATIC mp_obj_t time_time(void) {
@@ -159,13 +113,13 @@ STATIC const mp_map_elem_t time_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_localtime), (mp_obj_t)&time_localtime_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mktime), (mp_obj_t)&time_mktime_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&time_sleep_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_ms), (mp_obj_t)&time_sleep_ms_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_us), (mp_obj_t)&time_sleep_us_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_ms), (mp_obj_t)&time_ticks_ms_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_us), (mp_obj_t)&time_ticks_us_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_cpu), (mp_obj_t)&time_ticks_cpu_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_diff), (mp_obj_t)&time_ticks_diff_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&mp_utime_sleep_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_ms), (mp_obj_t)&mp_utime_sleep_ms_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_us), (mp_obj_t)&mp_utime_sleep_us_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_ms), (mp_obj_t)&mp_utime_ticks_ms_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_us), (mp_obj_t)&mp_utime_ticks_us_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_cpu), (mp_obj_t)&mp_utime_ticks_cpu_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_diff), (mp_obj_t)&mp_utime_ticks_diff_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_time_obj },
};
@@ -173,6 +127,5 @@ STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);
const mp_obj_module_t utime_module = {
.base = { &mp_type_module },
.name = MP_QSTR_utime,
.globals = (mp_obj_dict_t*)&time_module_globals,
};

View File

@@ -9,6 +9,7 @@
#define MICROPY_ALLOC_PARSE_RULE_INC (8)
#define MICROPY_ALLOC_PARSE_RESULT_INC (8)
#define MICROPY_ALLOC_PARSE_CHUNK_INIT (64)
#define MICROPY_PERSISTENT_CODE_LOAD (1)
#define MICROPY_EMIT_X64 (0)
#define MICROPY_EMIT_THUMB (0)
#define MICROPY_EMIT_INLINE_THUMB (0)
@@ -17,6 +18,7 @@
#define MICROPY_DEBUG_PRINTER_DEST mp_debug_print
#define MICROPY_ENABLE_GC (1)
#define MICROPY_STACK_CHECK (1)
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
#define MICROPY_REPL_EVENT_DRIVEN (0)
#define MICROPY_REPL_AUTO_INDENT (1)
#define MICROPY_HELPER_REPL (1)
@@ -25,6 +27,7 @@
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
#define MICROPY_USE_INTERNAL_ERRNO (1)
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
#define MICROPY_PY_BUILTINS_COMPLEX (0)
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
@@ -32,6 +35,7 @@
#define MICROPY_PY_BUILTINS_FROZENSET (1)
#define MICROPY_PY_BUILTINS_SET (1)
#define MICROPY_PY_BUILTINS_SLICE (1)
#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1)
#define MICROPY_PY_BUILTINS_PROPERTY (1)
#define MICROPY_PY___FILE__ (0)
#define MICROPY_PY_GC (1)
@@ -48,20 +52,23 @@
#define MICROPY_PY_SYS_MAXSIZE (1)
#define MICROPY_PY_SYS_EXIT (1)
#define MICROPY_PY_SYS_STDFILES (1)
#define MICROPY_PY_SYS_STDIO_BUFFER (1)
#define MICROPY_PY_UERRNO (1)
#define MICROPY_PY_UBINASCII (1)
#define MICROPY_PY_UCTYPES (1)
#define MICROPY_PY_UHASHLIB (1)
#define MICROPY_PY_UHASHLIB_SHA1 (1)
#define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL && MICROPY_SSL_AXTLS)
#define MICROPY_PY_UHEAPQ (1)
#define MICROPY_PY_UJSON (1)
#define MICROPY_PY_URANDOM (1)
#define MICROPY_PY_URE (1)
#define MICROPY_PY_UTIME_MP_HAL (1)
#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_MACHINE_SPI (1)
#define MICROPY_PY_WEBSOCKET (1)
#define MICROPY_PY_WEBREPL (1)
#define MICROPY_PY_WEBREPL_DELAY (20)
@@ -89,6 +96,7 @@
#define MICROPY_FSUSERMOUNT (1)
#define MICROPY_VFS_FAT (1)
#define MICROPY_ESP8266_APA102 (1)
#define MICROPY_ESP8266_NEOPIXEL (1)
#define MICROPY_EVENT_POLL_HOOK {ets_event_poll();}
#define MICROPY_VM_HOOK_COUNT (10)
@@ -114,8 +122,6 @@
typedef int32_t mp_int_t; // must be pointer size
typedef uint32_t mp_uint_t; // must be pointer size
typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
typedef long mp_off_t;
typedef uint32_t sys_prot_t; // for modlwip
// ssize_t, off_t as required by POSIX-signatured functions in stream.h

View File

@@ -39,8 +39,6 @@ static void uart0_rx_intr_handler(void *para);
void soft_reset(void);
void mp_keyboard_interrupt(void);
int interrupt_char;
/******************************************************************************
* FunctionName : uart_config
* Description : Internal used function
@@ -172,7 +170,7 @@ static void uart0_rx_intr_handler(void *para) {
while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
uint8 RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xff;
if (RcvChar == interrupt_char) {
if (RcvChar == mp_interrupt_char) {
mp_keyboard_interrupt();
} else {
ringbuf_put(&input_buf, RcvChar);

View File

@@ -16,10 +16,10 @@ pyb.LED(3).off() # indicate that we finished waiting for the swit
pyb.LED(4).on() # indicate that we are selecting the mode
if switch_value:
pyb.usb_mode('CDC+MSC')
pyb.usb_mode('VCP+MSC')
pyb.main('cardreader.py') # if switch was pressed, run this
else:
pyb.usb_mode('CDC+HID')
pyb.usb_mode('VCP+HID')
pyb.main('datalogger.py') # if switch wasn't pressed, run this
pyb.LED(4).off() # indicate that we finished selecting the mode

View File

@@ -127,9 +127,6 @@ typedef long long mp_off_t;
typedef long mp_off_t;
#endif
typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
// We need to provide a declaration/definition of alloca()
#ifdef __FreeBSD__
#include <stdlib.h>

View File

@@ -18,10 +18,10 @@ def main(use_stream=False):
# MicroPython socket objects support stream (aka file) interface
# directly, but the line below is needed for CPython.
s = s.makefile("rwb", 0)
s.write(b"GET / HTTP/1.0\n\n")
s.write(b"GET / HTTP/1.0\r\n\r\n")
print(s.readall())
else:
s.send(b"GET / HTTP/1.0\n\n")
s.send(b"GET / HTTP/1.0\r\n\r\n")
print(s.recv(4096))
s.close()

View File

@@ -24,12 +24,12 @@ def main(use_stream=True):
if use_stream:
# Both CPython and MicroPython SSLSocket objects support read() and
# write() methods.
s.write(b"GET / HTTP/1.0\n\n")
s.write(b"GET / HTTP/1.0\r\n\r\n")
print(s.read(4096))
else:
# MicroPython SSLSocket objects implement only stream interface, not
# socket interface
s.send(b"GET / HTTP/1.0\n\n")
s.send(b"GET / HTTP/1.0\r\n\r\n")
print(s.recv(4096))
s.close()

View File

@@ -31,6 +31,7 @@
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/mperrno.h"
#include "lib/fatfs/ff.h"
#include "extmod/fsusermount.h"
@@ -162,7 +163,7 @@ STATIC mp_obj_t fatfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
}
MP_DEFINE_CONST_FUN_OBJ_KW(fsuser_mount_obj, 2, fatfs_mount);
STATIC mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in) {
mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in) {
size_t i = 0;
if (MP_OBJ_IS_STR(bdev_or_path_in)) {
mp_uint_t mnt_len;
@@ -183,7 +184,7 @@ STATIC mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in) {
}
if (i == MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount))) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL)));
mp_raise_OSError(MP_EINVAL);
}
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i];

View File

@@ -55,6 +55,7 @@ typedef struct _fs_user_mount_t {
} fs_user_mount_t;
fs_user_mount_t *fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, bool mkfs);
mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in);
MP_DECLARE_CONST_FUN_OBJ(fsuser_mount_obj);
MP_DECLARE_CONST_FUN_OBJ(fsuser_umount_obj);

View File

@@ -34,6 +34,9 @@
#if MICROPY_PY_MACHINE_I2C
// Clock stretching limit, so that we don't get stuck.
#define I2C_STRETCH_LIMIT 255
typedef struct _machine_i2c_obj_t {
mp_obj_base_t base;
uint32_t us_delay;
@@ -53,6 +56,11 @@ STATIC void mp_hal_i2c_scl_low(machine_i2c_obj_t *self) {
STATIC void mp_hal_i2c_scl_release(machine_i2c_obj_t *self) {
mp_hal_pin_od_high(self->scl);
mp_hal_i2c_delay(self);
// For clock stretching, wait for the SCL pin to be released, with timeout.
for (int count = I2C_STRETCH_LIMIT; mp_hal_pin_read(self->scl) == 0 && count; --count) {
mp_hal_delay_us_fast(1);
}
}
STATIC void mp_hal_i2c_sda_low(machine_i2c_obj_t *self) {
@@ -71,7 +79,6 @@ STATIC void mp_hal_i2c_start(machine_i2c_obj_t *self) {
mp_hal_i2c_sda_release(self);
mp_hal_i2c_delay(self);
mp_hal_i2c_scl_release(self);
mp_hal_i2c_delay(self);
mp_hal_i2c_sda_low(self);
mp_hal_i2c_delay(self);
}
@@ -81,7 +88,6 @@ STATIC void mp_hal_i2c_stop(machine_i2c_obj_t *self) {
mp_hal_i2c_sda_low(self);
mp_hal_i2c_delay(self);
mp_hal_i2c_scl_release(self);
mp_hal_i2c_delay(self);
mp_hal_i2c_sda_release(self);
mp_hal_i2c_delay(self);
}
@@ -108,14 +114,12 @@ STATIC int mp_hal_i2c_write_byte(machine_i2c_obj_t *self, uint8_t val) {
}
mp_hal_i2c_delay(self);
mp_hal_i2c_scl_release(self);
mp_hal_i2c_delay(self);
mp_hal_i2c_scl_low(self);
}
mp_hal_i2c_sda_release(self);
mp_hal_i2c_delay(self);
mp_hal_i2c_scl_release(self);
mp_hal_i2c_delay(self);
int ret = mp_hal_i2c_sda_read(self);
mp_hal_i2c_delay(self);
@@ -124,24 +128,6 @@ STATIC int mp_hal_i2c_write_byte(machine_i2c_obj_t *self, uint8_t val) {
return !ret;
}
STATIC void mp_hal_i2c_write(machine_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len) {
mp_hal_i2c_start(self);
if (!mp_hal_i2c_write_byte(self, addr << 1)) {
goto er;
}
while (len--) {
if (!mp_hal_i2c_write_byte(self, *data++)) {
goto er;
}
}
mp_hal_i2c_stop(self);
return;
er:
mp_hal_i2c_stop(self);
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
}
STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack) {
mp_hal_i2c_delay(self);
mp_hal_i2c_scl_low(self);
@@ -150,7 +136,6 @@ STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack)
uint8_t data = 0;
for (int i = 7; i >= 0; i--) {
mp_hal_i2c_scl_release(self);
mp_hal_i2c_delay(self);
data = (data << 1) | mp_hal_i2c_sda_read(self);
mp_hal_i2c_scl_low(self);
mp_hal_i2c_delay(self);
@@ -163,40 +148,33 @@ STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack)
}
mp_hal_i2c_delay(self);
mp_hal_i2c_scl_release(self);
mp_hal_i2c_delay(self);
mp_hal_i2c_scl_low(self);
mp_hal_i2c_sda_release(self);
return 1; // success
}
STATIC void mp_hal_i2c_read(machine_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len) {
mp_hal_i2c_start(self);
if (!mp_hal_i2c_write_byte(self, (addr << 1) | 1)) {
goto er;
// addr is the device address, memaddr is a memory address sent big-endian
STATIC int mp_hal_i2c_write_addresses(machine_i2c_obj_t *self, uint8_t addr,
uint32_t memaddr, uint8_t addrsize) {
if (!mp_hal_i2c_write_byte(self, addr << 1)) {
return 0; // error
}
while (len--) {
if (!mp_hal_i2c_read_byte(self, data++, len == 0)) {
goto er;
for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
if (!mp_hal_i2c_write_byte(self, memaddr >> i)) {
return 0; // error
}
}
mp_hal_i2c_stop(self);
return;
er:
mp_hal_i2c_stop(self);
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
return 1; // success
}
STATIC void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr, uint16_t memaddr, const uint8_t *src, size_t len) {
STATIC void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr,
uint32_t memaddr, uint8_t addrsize, const uint8_t *src, size_t len) {
// start the I2C transaction
mp_hal_i2c_start(self);
// write the slave address and the memory address within the slave
if (!mp_hal_i2c_write_byte(self, addr << 1)) {
goto er;
}
if (!mp_hal_i2c_write_byte(self, memaddr)) {
if (!mp_hal_i2c_write_addresses(self, addr, memaddr, addrsize)) {
goto er;
}
@@ -216,20 +194,30 @@ er:
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
}
STATIC void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr, uint16_t memaddr, uint8_t *dest, size_t len) {
STATIC void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr,
uint32_t memaddr, uint8_t addrsize, uint8_t *dest, size_t len) {
// start the I2C transaction
mp_hal_i2c_start(self);
// write the slave address and the memory address within the slave
if (!mp_hal_i2c_write_byte(self, addr << 1)) {
goto er;
}
if (!mp_hal_i2c_write_byte(self, memaddr)) {
goto er;
if (addrsize) {
// write the slave address and the memory address within the slave
if (!mp_hal_i2c_write_addresses(self, addr, memaddr, addrsize)) {
goto er;
}
// i2c_read will do a repeated start, and then read the I2C memory
mp_hal_i2c_start(self);
}
// i2c_read will do a repeated start, and then read the I2C memory
mp_hal_i2c_read(self, addr, dest, len);
if (!mp_hal_i2c_write_byte(self, (addr << 1) | 1)) {
goto er;
}
while (len--) {
if (!mp_hal_i2c_read_byte(self, dest++, len == 0)) {
goto er;
}
}
mp_hal_i2c_stop(self);
return;
er:
@@ -237,6 +225,14 @@ er:
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
}
STATIC void mp_hal_i2c_write(machine_i2c_obj_t *self, uint8_t addr, const uint8_t *src, size_t len) {
mp_hal_i2c_write_mem(self, addr, 0, 0, src, len);
}
STATIC void mp_hal_i2c_read(machine_i2c_obj_t *self, uint8_t addr, uint8_t *dest, size_t len) {
mp_hal_i2c_read_mem(self, addr, 0, 0, dest, len);
}
/******************************************************************************/
// MicroPython bindings for I2C
@@ -276,7 +272,7 @@ STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
// 7-bit addresses 0b0000xxx and 0b1111xxx are reserved
for (int addr = 0x08; addr < 0x78; ++addr) {
mp_hal_i2c_start(self);
int ack = mp_hal_i2c_write_byte(self, (addr << 1) | 1);
int ack = mp_hal_i2c_write_byte(self, (addr << 1));
if (ack) {
mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));
}
@@ -365,68 +361,64 @@ STATIC mp_obj_t machine_i2c_writeto(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_writeto_obj, machine_i2c_writeto);
STATIC const mp_arg_t machine_i2c_mem_allowed_args[] = {
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_arg, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
};
STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_n, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
//{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO
};
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
// create the buffer to store data into
vstr_t vstr;
vstr_init_len(&vstr, args[ARG_n].u_int);
vstr_init_len(&vstr, mp_obj_get_int(args[ARG_n].u_obj));
// do the transfer
mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, (uint8_t*)vstr.buf, vstr.len);
mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int,
args[ARG_addrsize].u_int, (uint8_t*)vstr.buf, vstr.len);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem);
STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
//{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO
};
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
// get the buffer to store data into
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE);
// do the transfer
mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len);
mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int,
args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into);
STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
//{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO
};
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
// get the buffer to write the data from
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ);
// do the transfer
mp_hal_i2c_write_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len);
mp_hal_i2c_write_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int,
args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem);

View File

@@ -58,7 +58,7 @@ STATIC mp_obj_t machine_time_pulse_us_(size_t n_args, const mp_obj_t *args) {
}
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)));
mp_raise_OSError(MP_ETIMEDOUT);
}
return mp_obj_new_int(us);
}

141
extmod/machine_spi.c Normal file
View File

@@ -0,0 +1,141 @@
/*
* 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 <string.h>
#include "py/runtime.h"
#include "extmod/machine_spi.h"
#if MICROPY_PY_MACHINE_SPI
void mp_machine_soft_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
mp_machine_soft_spi_obj_t *self = (mp_machine_soft_spi_obj_t*)self_in;
uint32_t delay_half = self->delay_half;
// only MSB transfer is implemented
// If a port defines MICROPY_PY_MACHINE_SPI_MIN_DELAY, and the configured
// delay_half is equal to this value, then the software SPI implementation
// will run as fast as possible, limited only by CPU speed and GPIO time.
#ifdef MICROPY_PY_MACHINE_SPI_MIN_DELAY
if (delay_half == MICROPY_PY_MACHINE_SPI_MIN_DELAY) {
for (size_t i = 0; i < len; ++i) {
uint8_t data_out = src[i];
uint8_t data_in = 0;
for (int j = 0; j < 8; ++j, data_out <<= 1) {
mp_hal_pin_write(self->mosi, (data_out >> 7) & 1);
mp_hal_pin_write(self->sck, 1 - self->polarity);
data_in = (data_in << 1) | mp_hal_pin_read(self->miso);
mp_hal_pin_write(self->sck, self->polarity);
}
if (dest != NULL) {
dest[i] = data_in;
}
}
return;
}
#endif
for (size_t i = 0; i < len; ++i) {
uint8_t data_out = src[i];
uint8_t data_in = 0;
for (int j = 0; j < 8; ++j, data_out <<= 1) {
mp_hal_pin_write(self->mosi, (data_out >> 7) & 1);
if (self->phase == 0) {
mp_hal_delay_us_fast(delay_half);
mp_hal_pin_write(self->sck, 1 - self->polarity);
} else {
mp_hal_pin_write(self->sck, 1 - self->polarity);
mp_hal_delay_us_fast(delay_half);
}
data_in = (data_in << 1) | mp_hal_pin_read(self->miso);
if (self->phase == 0) {
mp_hal_delay_us_fast(delay_half);
mp_hal_pin_write(self->sck, self->polarity);
} else {
mp_hal_pin_write(self->sck, self->polarity);
mp_hal_delay_us_fast(delay_half);
}
}
if (dest != NULL) {
dest[i] = data_in;
}
// Some ports need a regular callback, but probably we don't need
// to do this every byte, or even at all.
#ifdef MICROPY_EVENT_POLL_HOOK
MICROPY_EVENT_POLL_HOOK;
#endif
}
}
STATIC void mp_machine_spi_transfer(mp_obj_t self, size_t len, const void *src, void *dest) {
mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(self);
mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol;
spi_p->transfer(s, len, src, dest);
}
STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) {
vstr_t vstr;
vstr_init_len(&vstr, mp_obj_get_int(args[1]));
memset(vstr.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, vstr.len);
mp_machine_spi_transfer(args[0], vstr.len, vstr.buf, vstr.buf);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read);
STATIC mp_obj_t mp_machine_spi_readinto(size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
memset(bufinfo.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, bufinfo.len);
mp_machine_spi_transfer(args[0], bufinfo.len, bufinfo.buf, bufinfo.buf);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj, 2, 3, mp_machine_spi_readinto);
STATIC mp_obj_t mp_machine_spi_write(mp_obj_t self, mp_obj_t wr_buf) {
mp_buffer_info_t src;
mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ);
mp_machine_spi_transfer(self, src.len, (const uint8_t*)src.buf, NULL);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj, mp_machine_spi_write);
STATIC mp_obj_t mp_machine_spi_write_readinto(mp_obj_t self, mp_obj_t wr_buf, mp_obj_t rd_buf) {
mp_buffer_info_t src;
mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ);
mp_buffer_info_t dest;
mp_get_buffer_raise(rd_buf, &dest, MP_BUFFER_WRITE);
if (src.len != dest.len) {
mp_raise_ValueError("buffers must be the same length");
}
mp_machine_spi_transfer(self, src.len, src.buf, dest.buf);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj, mp_machine_spi_write_readinto);
#endif // MICROPY_PY_MACHINE_SPI

55
extmod/machine_spi.h Normal file
View File

@@ -0,0 +1,55 @@
/*
* 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_SPI_H
#define MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
#include "py/obj.h"
#include "py/mphal.h"
// SPI protocol
typedef struct _mp_machine_spi_p_t {
void (*transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest);
} mp_machine_spi_p_t;
typedef struct _mp_machine_soft_spi_obj_t {
mp_obj_base_t base;
uint32_t delay_half; // microsecond delay for half SCK period
uint8_t polarity;
uint8_t phase;
mp_hal_pin_obj_t sck;
mp_hal_pin_obj_t mosi;
mp_hal_pin_obj_t miso;
} mp_machine_soft_spi_obj_t;
void mp_machine_soft_spi_transfer(mp_obj_base_t *self, size_t len, const uint8_t *src, uint8_t *dest);
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_read_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_readinto_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_write_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_write_readinto_obj);
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H

View File

@@ -58,7 +58,7 @@ STATIC const mp_obj_type_t btree_type;
#define CHECK_ERROR(res) \
if (res == RET_ERROR) { \
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno))); \
mp_raise_OSError(errno); \
}
void __dbpanic(DB *db) {
@@ -133,6 +133,7 @@ STATIC mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) {
}
int res = __bt_seq(self->db, &key, &val, flags);
CHECK_ERROR(res);
if (res == RET_SPECIAL) {
return mp_const_none;
}
@@ -369,7 +370,7 @@ STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t
DB *db = __bt_open(pos_args[0], &btree_stream_fvtable, &openinfo, /*dflags*/0);
if (db == NULL) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno)));
mp_raise_OSError(errno);
}
return MP_OBJ_FROM_PTR(btree_new(db));
}
@@ -386,7 +387,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_btree_globals, mp_module_btree_globals_tab
const mp_obj_module_t mp_module_btree = {
.base = { &mp_type_module },
.name = MP_QSTR_btree,
.globals = (mp_obj_dict_t*)&mp_module_btree_globals,
};

View File

@@ -33,7 +33,7 @@
#if MICROPY_PY_FRAMEBUF
#include "font_petme128_8x8.h"
#include "stmhal/font_petme128_8x8.h"
// 1-bit frame buffer, each byte is a column of 8 pixels
typedef struct _mp_obj_framebuf1_t {
@@ -68,7 +68,8 @@ STATIC mp_obj_t framebuf1_fill(mp_obj_t self_in, mp_obj_t col_in) {
if (col) {
col = 0xff;
}
for (int y = 0; y < self->height / 8; ++y) {
int end = (self->height + 7) >> 3;
for (int y = 0; y < end; ++y) {
memset(self->buf + y * self->stride, col, self->width);
}
return mp_const_none;
@@ -83,7 +84,7 @@ STATIC mp_obj_t framebuf1_pixel(size_t n_args, const mp_obj_t *args) {
int index = (y / 8) * self->stride + x;
if (n_args == 3) {
// get
return MP_OBJ_NEW_SMALL_INT(self->buf[index] >> (y & 7));
return MP_OBJ_NEW_SMALL_INT((self->buf[index] >> (y & 7)) & 1);
} else {
// set
if (mp_obj_get_int(args[3])) {
@@ -101,8 +102,9 @@ STATIC mp_obj_t framebuf1_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t y
mp_obj_framebuf1_t *self = MP_OBJ_TO_PTR(self_in);
mp_int_t xstep = mp_obj_get_int(xstep_in);
mp_int_t ystep = mp_obj_get_int(ystep_in);
if (xstep == 0 && ystep > 0) {
for (int y = self->height / 8; y > 0;) {
int end = (self->height + 7) >> 3;
if (ystep > 0) {
for (int y = end; y > 0;) {
--y;
for (int x = 0; x < self->width; ++x) {
int prev = 0;
@@ -112,18 +114,31 @@ STATIC mp_obj_t framebuf1_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t y
self->buf[y * self->stride + x] = (self->buf[y * self->stride + x] << ystep) | prev;
}
}
} else if (xstep == 0 && ystep < 0) {
for (int y = 0; y < self->height / 8; ++y) {
} else if (ystep < 0) {
for (int y = 0; y < end; ++y) {
for (int x = 0; x < self->width; ++x) {
int prev = 0;
if (y + 1 < self->height / 8) {
if (y + 1 < end) {
prev = self->buf[(y + 1) * self->stride + x] << (8 + ystep);
}
self->buf[y * self->stride + x] = (self->buf[y * self->stride + x] >> -ystep) | prev;
}
}
}
// TODO xstep!=0
if (xstep < 0) {
for (int y = 0; y < end; ++y) {
for (int x = 0; x < self->width + xstep; ++x) {
self->buf[y * self->stride + x] = self->buf[y * self->stride + x - xstep];
}
}
} else if (xstep > 0) {
for (int y = 0; y < end; ++y) {
for (int x = self->width - 1; x >= xstep; --x) {
self->buf[y * self->stride + x] = self->buf[y * self->stride + x - xstep];
}
}
}
// TODO: Should we clear the margin created by scrolling?
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf1_scroll_obj, framebuf1_scroll);
@@ -198,7 +213,6 @@ STATIC MP_DEFINE_CONST_DICT(framebuf_module_globals, framebuf_module_globals_tab
const mp_obj_module_t mp_module_framebuf = {
.base = { &mp_type_module },
.name = MP_QSTR_framebuf,
.globals = (mp_obj_dict_t*)&framebuf_module_globals,
};

View File

@@ -598,11 +598,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(MP_EINVAL)));
default: mp_raise_OSError(MP_EINVAL);
}
if (socket->pcb.tcp == NULL) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENOMEM)));
mp_raise_OSError(MP_ENOMEM);
}
switch (socket->type) {
@@ -686,7 +686,7 @@ STATIC mp_obj_t lwip_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
}
if (err != ERR_OK) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error_lookup_table[-err])));
mp_raise_OSError(error_lookup_table[-err]);
}
return mp_const_none;
@@ -698,15 +698,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(MP_EBADF)));
mp_raise_OSError(MP_EBADF);
}
if (socket->type != MOD_NETWORK_SOCK_STREAM) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EOPNOTSUPP)));
mp_raise_OSError(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(MP_ENOMEM)));
mp_raise_OSError(MP_ENOMEM);
}
socket->pcb.tcp = new_pcb;
tcp_accept(new_pcb, _lwip_tcp_accept);
@@ -719,15 +719,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(MP_EBADF)));
mp_raise_OSError(MP_EBADF);
}
if (socket->type != MOD_NETWORK_SOCK_STREAM) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EOPNOTSUPP)));
mp_raise_OSError(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(MP_EINVAL)));
mp_raise_OSError(MP_EINVAL);
}
// accept incoming connection
@@ -738,7 +738,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(MP_ETIMEDOUT)));
mp_raise_OSError(MP_ETIMEDOUT);
}
} else {
while (socket->incoming.connection == NULL) {
@@ -785,7 +785,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(MP_EBADF)));
mp_raise_OSError(MP_EBADF);
}
// get address
@@ -800,9 +800,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(MP_EALREADY)));
mp_raise_OSError(MP_EALREADY);
} else {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EINPROGRESS)));
mp_raise_OSError(MP_EINPROGRESS);
}
}
// Register our recieve callback.
@@ -811,7 +811,7 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
err = tcp_connect(socket->pcb.tcp, &dest, port, _lwip_tcp_connected);
if (err != ERR_OK) {
socket->state = STATE_NEW;
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error_lookup_table[-err])));
mp_raise_OSError(error_lookup_table[-err]);
}
socket->peer_port = (mp_uint_t)port;
memcpy(socket->peer, &dest, sizeof(socket->peer));
@@ -822,7 +822,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(MP_ETIMEDOUT)));
mp_raise_OSError(MP_ETIMEDOUT);
}
} else {
while (socket->state == STATE_CONNECTING) {
@@ -843,7 +843,7 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
}
if (err != ERR_OK) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error_lookup_table[-err])));
mp_raise_OSError(error_lookup_table[-err]);
}
return mp_const_none;
@@ -855,7 +855,7 @@ STATIC void lwip_socket_check_connected(lwip_socket_obj_t *socket) {
// not connected
int _errno = error_lookup_table[-socket->state];
socket->state = _ERR_BADF;
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
mp_raise_OSError(_errno);
}
}
@@ -880,7 +880,7 @@ STATIC mp_obj_t lwip_socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
}
}
if (ret == -1) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
mp_raise_OSError(_errno);
}
return mp_obj_new_int_from_uint(ret);
@@ -909,7 +909,7 @@ STATIC mp_obj_t lwip_socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
}
}
if (ret == -1) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
mp_raise_OSError(_errno);
}
if (ret == 0) {
@@ -944,7 +944,7 @@ STATIC mp_obj_t lwip_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t
}
}
if (ret == -1) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
mp_raise_OSError(_errno);
}
return mp_obj_new_int_from_uint(ret);
@@ -977,7 +977,7 @@ STATIC mp_obj_t lwip_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
}
}
if (ret == -1) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
mp_raise_OSError(_errno);
}
mp_obj_t tuple[2];
@@ -1010,7 +1010,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(MP_EAGAIN)));
mp_raise_OSError(MP_EAGAIN);
}
}
// TODO: In CPython3.5, socket timeout should apply to the
@@ -1018,7 +1018,7 @@ STATIC mp_obj_t lwip_socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) {
while (bufinfo.len != 0) {
ret = lwip_tcp_send(socket, bufinfo.buf, bufinfo.len, &_errno);
if (ret == -1) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
mp_raise_OSError(_errno);
}
bufinfo.len -= ret;
bufinfo.buf = (char*)bufinfo.buf + ret;
@@ -1259,7 +1259,7 @@ STATIC mp_obj_t lwip_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
if (state.status < 0) {
// TODO: CPython raises gaierror, we raise with native lwIP negative error
// values, to differentiate from normal errno's at least in such way.
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(state.status)));
mp_raise_OSError(state.status);
}
mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
@@ -1309,7 +1309,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_lwip_globals, mp_module_lwip_globals_table
const mp_obj_module_t mp_module_lwip = {
.base = { &mp_type_module },
.name = MP_QSTR_lwip,
.globals = (mp_obj_dict_t*)&mp_module_lwip_globals,
};

View File

@@ -33,6 +33,7 @@
#include "py/binary.h"
#include "extmod/modubinascii.h"
#include "uzlib/tinf.h"
mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {
// Second argument is for an extension to allow a separator to be used
@@ -203,6 +204,17 @@ mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
}
MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj, mod_binascii_b2a_base64);
#if MICROPY_PY_UBINASCII_CRC32
mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
uint32_t crc = (n_args > 1) ? mp_obj_get_int_truncated(args[1]) : 0;
crc = uzlib_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff);
return mp_obj_new_int_from_uint(crc ^ 0xffffffff);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_binascii_crc32);
#endif
#if MICROPY_PY_UBINASCII
STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = {
@@ -211,13 +223,15 @@ STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&mod_binascii_unhexlify_obj) },
{ MP_ROM_QSTR(MP_QSTR_a2b_base64), MP_ROM_PTR(&mod_binascii_a2b_base64_obj) },
{ MP_ROM_QSTR(MP_QSTR_b2a_base64), MP_ROM_PTR(&mod_binascii_b2a_base64_obj) },
#if MICROPY_PY_UBINASCII_CRC32
{ MP_ROM_QSTR(MP_QSTR_crc32), MP_ROM_PTR(&mod_binascii_crc32_obj) },
#endif
};
STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table);
const mp_obj_module_t mp_module_ubinascii = {
.base = { &mp_type_module },
.name = MP_QSTR_ubinascii,
.globals = (mp_obj_dict_t*)&mp_module_binascii_globals,
};

View File

@@ -31,10 +31,12 @@ extern mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args);
extern mp_obj_t mod_binascii_unhexlify(mp_obj_t data);
extern mp_obj_t mod_binascii_a2b_base64(mp_obj_t data);
extern mp_obj_t mod_binascii_b2a_base64(mp_obj_t data);
extern mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args);
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_hexlify_obj);
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_unhexlify_obj);
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_a2b_base64_obj);
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_b2a_base64_obj);
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_crc32_obj);
#endif /* MICROPY_EXTMOD_MODUBINASCII */

View File

@@ -125,7 +125,7 @@ STATIC mp_obj_t uctypes_struct_make_new(const mp_obj_type_t *type, size_t n_args
mp_arg_check_num(n_args, n_kw, 2, 3, false);
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
o->base.type = type;
o->addr = (void*)(uintptr_t)mp_obj_get_int(args[0]);
o->addr = (void*)(uintptr_t)mp_obj_int_get_truncated(args[0]);
o->desc = args[1];
o->flags = LAYOUT_NATIVE;
if (n_args == 3) {
@@ -710,7 +710,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_uctypes_globals, mp_module_uctypes_globals
const mp_obj_module_t mp_module_uctypes = {
.base = { &mp_type_module },
.name = MP_QSTR_uctypes,
.globals = (mp_obj_dict_t*)&mp_module_uctypes_globals,
};

View File

@@ -151,7 +151,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_hashlib_globals, mp_module_hashlib_globals
const mp_obj_module_t mp_module_uhashlib = {
.base = { &mp_type_module },
.name = MP_QSTR_uhashlib,
.globals = (mp_obj_dict_t*)&mp_module_hashlib_globals,
};

View File

@@ -116,7 +116,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_uheapq_globals, mp_module_uheapq_globals_t
const mp_obj_module_t mp_module_uheapq = {
.base = { &mp_type_module },
.name = MP_QSTR_uheapq,
.globals = (mp_obj_dict_t*)&mp_module_uheapq_globals,
};

View File

@@ -1,9 +1,9 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Damien P. George
* Copyright (c) 2014-2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,8 +28,10 @@
#include "py/nlr.h"
#include "py/objlist.h"
#include "py/objstringio.h"
#include "py/parsenum.h"
#include "py/runtime.h"
#include "py/stream.h"
#if MICROPY_PY_UJSON
@@ -42,7 +44,7 @@ STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps);
// This function implements a simple non-recursive JSON parser.
// The function below implements a simple non-recursive JSON parser.
//
// The JSON specification is at http://www.ietf.org/rfc/rfc4627.txt
// The parser here will parse any valid JSON and return the correct
@@ -52,13 +54,35 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps);
// input is outside it's specs.
//
// Most of the work is parsing the primitives (null, false, true, numbers,
// strings). It does 1 pass over the input string and so is easily extended to
// being able to parse from a non-seekable stream. It tries to be fast and
// strings). It does 1 pass over the input stream. It tries to be fast and
// small in code size, while not using more RAM than necessary.
STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
mp_uint_t len;
const char *s = mp_obj_str_get_data(obj, &len);
const char *top = s + len;
typedef struct _ujson_stream_t {
mp_obj_t stream_obj;
mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
int errcode;
byte cur;
} ujson_stream_t;
#define S_EOF (0) // null is not allowed in json stream so is ok as EOF marker
#define S_END(s) ((s).cur == S_EOF)
#define S_CUR(s) ((s).cur)
#define S_NEXT(s) (ujson_stream_next(&(s)))
STATIC byte ujson_stream_next(ujson_stream_t *s) {
mp_uint_t ret = s->read(s->stream_obj, &s->cur, 1, &s->errcode);
if (s->errcode != 0) {
mp_raise_OSError(s->errcode);
}
if (ret == 0) {
s->cur = S_EOF;
}
return s->cur;
}
STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
const mp_stream_p_t *stream_p = mp_get_stream_raise(stream_obj, MP_STREAM_OP_READ);
ujson_stream_t s = {stream_obj, stream_p->read, 0, 0};
vstr_t vstr;
vstr_init(&vstr, 8);
mp_obj_list_t stack; // we use a list as a simple stack for nested JSON
@@ -67,41 +91,43 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
mp_obj_t stack_top = MP_OBJ_NULL;
mp_obj_type_t *stack_top_type = NULL;
mp_obj_t stack_key = MP_OBJ_NULL;
S_NEXT(s);
for (;;) {
cont:
if (s == top) {
if (S_END(s)) {
break;
}
mp_obj_t next = MP_OBJ_NULL;
bool enter = false;
switch (*s) {
byte cur = S_CUR(s);
S_NEXT(s);
switch (cur) {
case ',':
case ':':
case ' ':
case '\t':
case '\n':
case '\r':
s += 1;
goto cont;
case 'n':
if (s + 3 < top && s[1] == 'u' && s[2] == 'l' && s[3] == 'l') {
s += 4;
if (S_CUR(s) == 'u' && S_NEXT(s) == 'l' && S_NEXT(s) == 'l') {
S_NEXT(s);
next = mp_const_none;
} else {
goto fail;
}
break;
case 'f':
if (s + 4 < top && s[1] == 'a' && s[2] == 'l' && s[3] == 's' && s[4] == 'e') {
s += 5;
if (S_CUR(s) == 'a' && S_NEXT(s) == 'l' && S_NEXT(s) == 's' && S_NEXT(s) == 'e') {
S_NEXT(s);
next = mp_const_false;
} else {
goto fail;
}
break;
case 't':
if (s + 3 < top && s[1] == 'r' && s[2] == 'u' && s[3] == 'e') {
s += 4;
if (S_CUR(s) == 'r' && S_NEXT(s) == 'u' && S_NEXT(s) == 'e') {
S_NEXT(s);
next = mp_const_true;
} else {
goto fail;
@@ -109,11 +135,10 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
break;
case '"':
vstr_reset(&vstr);
for (s++; s < top && *s != '"';) {
byte c = *s;
for (; !S_END(s) && S_CUR(s) != '"';) {
byte c = S_CUR(s);
if (c == '\\') {
s++;
c = *s;
c = S_NEXT(s);
switch (c) {
case 'b': c = 0x08; break;
case 'f': c = 0x0c; break;
@@ -121,10 +146,9 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
case 'r': c = 0x0d; break;
case 't': c = 0x09; break;
case 'u': {
if (s + 4 >= top) { goto fail; }
mp_uint_t num = 0;
for (int i = 0; i < 4; i++) {
c = (*++s | 0x20) - '0';
c = (S_NEXT(s) | 0x20) - '0';
if (c > 9) {
c -= ('a' - ('9' + 1));
}
@@ -137,27 +161,29 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
}
vstr_add_byte(&vstr, c);
str_cont:
s++;
S_NEXT(s);
}
if (s == top) {
if (S_END(s)) {
goto fail;
}
s++;
S_NEXT(s);
next = mp_obj_new_str(vstr.buf, vstr.len, false);
break;
case '-':
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': {
bool flt = false;
vstr_reset(&vstr);
for (; s < top; s++) {
if (*s == '.' || *s == 'E' || *s == 'e') {
for (;;) {
vstr_add_byte(&vstr, cur);
cur = S_CUR(s);
if (cur == '.' || cur == 'E' || cur == 'e') {
flt = true;
} else if (*s == '-' || unichar_isdigit(*s)) {
} else if (cur == '-' || unichar_isdigit(cur)) {
// pass
} else {
break;
}
vstr_add_byte(&vstr, *s);
S_NEXT(s);
}
if (flt) {
next = mp_parse_num_decimal(vstr.buf, vstr.len, false, false, NULL);
@@ -169,16 +195,13 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
case '[':
next = mp_obj_new_list(0, NULL);
enter = true;
s += 1;
break;
case '{':
next = mp_obj_new_dict(0);
enter = true;
s += 1;
break;
case '}':
case ']': {
s += 1;
if (stack_top == MP_OBJ_NULL) {
// no object at all
goto fail;
@@ -231,10 +254,10 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
}
success:
// eat trailing whitespace
while (s < top && unichar_isspace(*s)) {
s++;
while (unichar_isspace(S_CUR(s))) {
S_NEXT(s);
}
if (s < top) {
if (!S_END(s)) {
// unexpected chars
goto fail;
}
@@ -248,11 +271,21 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
fail:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "syntax error in JSON"));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load);
STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
mp_uint_t len;
const char *buf = mp_obj_str_get_data(obj, &len);
vstr_t vstr = {len, len, (char*)buf, true};
mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0};
return mod_ujson_load(MP_OBJ_FROM_PTR(&sio));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_loads_obj, mod_ujson_loads);
STATIC const mp_rom_map_elem_t mp_module_ujson_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ujson) },
{ MP_ROM_QSTR(MP_QSTR_dumps), MP_ROM_PTR(&mod_ujson_dumps_obj) },
{ MP_ROM_QSTR(MP_QSTR_load), MP_ROM_PTR(&mod_ujson_load_obj) },
{ MP_ROM_QSTR(MP_QSTR_loads), MP_ROM_PTR(&mod_ujson_loads_obj) },
};
@@ -260,7 +293,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_ujson_globals, mp_module_ujson_globals_tab
const mp_obj_module_t mp_module_ujson = {
.base = { &mp_type_module },
.name = MP_QSTR_ujson,
.globals = (mp_obj_dict_t*)&mp_module_ujson_globals,
};

View File

@@ -215,7 +215,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_urandom_globals, mp_module_urandom_globals
const mp_obj_module_t mp_module_urandom = {
.base = { &mp_type_module },
.name = MP_QSTR_urandom,
.globals = (mp_obj_dict_t*)&mp_module_urandom_globals,
};

View File

@@ -237,7 +237,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_re_globals, mp_module_re_globals_table);
const mp_obj_module_t mp_module_ure = {
.base = { &mp_type_module },
.name = MP_QSTR_ure,
.globals = (mp_obj_dict_t*)&mp_module_re_globals,
};

View File

@@ -56,7 +56,7 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, bool server_side) {
uint32_t options = SSL_SERVER_VERIFY_LATER;
if ((o->ssl_ctx = ssl_ctx_new(options, SSL_DEFAULT_CLNT_SESS)) == NULL) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL)));
mp_raise_OSError(MP_EINVAL);
}
if (server_side) {
@@ -69,7 +69,7 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, bool server_side) {
if ((res = ssl_handshake_status(o->ssl_sock)) != SSL_OK) {
printf("ssl_handshake_status: %d\n", res);
ssl_display_error(res);
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EIO)));
mp_raise_OSError(MP_EIO);
}
}
@@ -196,7 +196,6 @@ STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
const mp_obj_module_t mp_module_ussl = {
.base = { &mp_type_module },
.name = MP_QSTR_ussl,
.globals = (mp_obj_dict_t*)&mp_module_ssl_globals,
};

303
extmod/modussl_mbedtls.c Normal file
View File

@@ -0,0 +1,303 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Linaro Ltd.
*
* 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/mpconfig.h"
#if MICROPY_PY_USSL && MICROPY_SSL_MBEDTLS
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/stream.h"
// mbedtls_time_t
#include "mbedtls/platform.h"
#include "mbedtls/net.h"
#include "mbedtls/ssl.h"
#include "mbedtls/x509_crt.h"
#include "mbedtls/pk.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/debug.h"
typedef struct _mp_obj_ssl_socket_t {
mp_obj_base_t base;
mp_obj_t sock;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt cacert;
mbedtls_x509_crt cert;
mbedtls_pk_context pkey;
} mp_obj_ssl_socket_t;
struct ssl_args {
mp_arg_val_t key;
mp_arg_val_t cert;
mp_arg_val_t server_side;
mp_arg_val_t server_hostname;
};
STATIC const mp_obj_type_t ussl_socket_type;
static void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) {
printf("DBG:%s:%04d: %s\n", file, line, str);
}
// TODO: FIXME!
int null_entropy_func(void *data, unsigned char *output, size_t len) {
// enjoy random bytes
return 0;
}
int _mbedtls_ssl_send(void *ctx, const byte *buf, size_t len) {
mp_obj_t sock = *(mp_obj_t*)ctx;
const mp_stream_p_t *sock_stream = mp_get_stream_raise(sock, MP_STREAM_OP_WRITE);
int err;
int out_sz = sock_stream->write(sock, buf, len, &err);
if (out_sz == MP_STREAM_ERROR) {
return -err;
} else {
return out_sz;
}
}
int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) {
mp_obj_t sock = *(mp_obj_t*)ctx;
const mp_stream_p_t *sock_stream = mp_get_stream_raise(sock, MP_STREAM_OP_READ);
int err;
int out_sz = sock_stream->read(sock, buf, len, &err);
if (out_sz == MP_STREAM_ERROR) {
return -err;
} else {
return out_sz;
}
}
STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t);
o->base.type = &ussl_socket_type;
int ret;
mbedtls_ssl_init(&o->ssl);
mbedtls_ssl_config_init(&o->conf);
mbedtls_x509_crt_init(&o->cacert);
mbedtls_x509_crt_init(&o->cert);
mbedtls_pk_init(&o->pkey);
mbedtls_ctr_drbg_init(&o->ctr_drbg);
// Debug level (0-4)
mbedtls_debug_set_threshold(0);
mbedtls_entropy_init(&o->entropy);
const byte seed[] = "upy";
ret = mbedtls_ctr_drbg_seed(&o->ctr_drbg, null_entropy_func/*mbedtls_entropy_func*/, &o->entropy, seed, sizeof(seed));
if (ret != 0) {
printf("ret=%d\n", ret);
assert(0);
}
ret = mbedtls_ssl_config_defaults(&o->conf,
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT);
if (ret != 0) {
assert(0);
}
mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_NONE);
mbedtls_ssl_conf_rng(&o->conf, mbedtls_ctr_drbg_random, &o->ctr_drbg);
mbedtls_ssl_conf_dbg(&o->conf, mbedtls_debug, NULL);
ret = mbedtls_ssl_setup(&o->ssl, &o->conf);
if (ret != 0) {
assert(0);
}
if (args->server_hostname.u_obj != mp_const_none) {
const char *sni = mp_obj_str_get_str(args->server_hostname.u_obj);
ret = mbedtls_ssl_set_hostname(&o->ssl, sni);
if (ret != 0) {
assert(0);
}
}
o->sock = sock;
mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL);
if (args->key.u_obj != MP_OBJ_NULL) {
mp_uint_t key_len;
const byte *key = (const byte*)mp_obj_str_get_data(args->key.u_obj, &key_len);
// len should include terminating null
ret = mbedtls_pk_parse_key(&o->pkey, key, key_len + 1, NULL, 0);
assert(ret == 0);
mp_uint_t cert_len;
const byte *cert = (const byte*)mp_obj_str_get_data(args->cert.u_obj, &cert_len);
// len should include terminating null
ret = mbedtls_x509_crt_parse(&o->cert, cert, cert_len + 1);
assert(ret == 0);
ret = mbedtls_ssl_conf_own_cert(&o->conf, &o->cert, &o->pkey);
assert(ret == 0);
}
if (args->server_side.u_bool) {
assert(0);
} else {
while ((ret = mbedtls_ssl_handshake(&o->ssl)) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
//assert(0);
printf("mbedtls_ssl_handshake error: -%x\n", -ret);
mp_raise_OSError(MP_EIO);
}
}
}
return o;
}
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 = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "<_SSLSocket %p>", self);
}
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 = MP_OBJ_TO_PTR(o_in);
int ret = mbedtls_ssl_read(&o->ssl, buf, size);
if (ret >= 0) {
return ret;
}
*errcode = ret;
return MP_STREAM_ERROR;
}
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 = MP_OBJ_TO_PTR(o_in);
int ret = mbedtls_ssl_write(&o->ssl, buf, size);
if (ret >= 0) {
return ret;
}
*errcode = ret;
return MP_STREAM_ERROR;
}
STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
// Currently supports only blocking mode
(void)self_in;
if (!mp_obj_is_true(flag_in)) {
mp_not_implemented("");
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
STATIC mp_obj_t socket_close(mp_obj_t self_in) {
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
mbedtls_x509_crt_free(&self->cacert);
mbedtls_ssl_free(&self->ssl);
mbedtls_ssl_config_free(&self->conf);
mbedtls_ctr_drbg_free(&self->ctr_drbg);
mbedtls_entropy_free(&self->entropy);
mp_obj_t dest[2];
mp_load_method(self->sock, MP_QSTR_close, dest);
return mp_call_method_n_kw(0, 0, dest);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close);
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_setblocking), MP_ROM_PTR(&socket_setblocking_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);
STATIC const mp_stream_p_t ussl_socket_stream_p = {
.read = socket_read,
.write = socket_write,
};
STATIC const mp_obj_type_t ussl_socket_type = {
{ &mp_type_type },
// Save on qstr's, reuse same as for module
.name = MP_QSTR_ussl,
.print = socket_print,
.getiter = NULL,
.iternext = NULL,
.protocol = &ussl_socket_stream_p,
.locals_dict = (void*)&ussl_socket_locals_dict,
};
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_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
// TODO: Check that sock implements stream protocol
mp_obj_t sock = pos_args[0];
struct ssl_args 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 MP_OBJ_FROM_PTR(socket_new(sock, &args));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
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);
const mp_obj_module_t mp_module_ussl = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&mp_module_ssl_globals,
};
#endif // MICROPY_PY_USSL

View File

@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Paul Sokolovsky
* Copyright (c) 2014-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
@@ -25,9 +25,12 @@
*/
#include <stdio.h>
#include <string.h>
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mperrno.h"
#if MICROPY_PY_UZLIB
@@ -39,16 +42,107 @@
#define DEBUG_printf(...) (void)0
#endif
STATIC int mod_uzlib_grow_buf(TINF_DATA *d, unsigned alloc_req) {
if (alloc_req < 256) {
alloc_req = 256;
typedef struct _mp_obj_decompio_t {
mp_obj_base_t base;
mp_obj_t src_stream;
TINF_DATA decomp;
bool eof;
} mp_obj_decompio_t;
STATIC unsigned char read_src_stream(TINF_DATA *data) {
byte *p = (void*)data;
p -= offsetof(mp_obj_decompio_t, decomp);
mp_obj_decompio_t *self = (mp_obj_decompio_t*)p;
const mp_stream_p_t *stream = mp_get_stream_raise(self->src_stream, MP_STREAM_OP_READ);
int err;
byte c;
mp_uint_t out_sz = stream->read(self->src_stream, &c, 1, &err);
if (out_sz == MP_STREAM_ERROR) {
mp_raise_OSError(err);
}
DEBUG_printf("uzlib: Resizing buffer to " UINT_FMT " bytes\n", d->destSize + alloc_req);
d->destStart = m_renew(byte, d->destStart, d->destSize, d->destSize + alloc_req);
d->destSize += alloc_req;
return 0;
if (out_sz == 0) {
nlr_raise(mp_obj_new_exception(&mp_type_EOFError));
}
return c;
}
STATIC mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, 2, false);
mp_obj_decompio_t *o = m_new_obj(mp_obj_decompio_t);
o->base.type = type;
memset(&o->decomp, 0, sizeof(o->decomp));
o->decomp.readSource = read_src_stream;
o->src_stream = args[0];
o->eof = false;
mp_int_t dict_opt = 0;
int dict_sz;
if (n_args > 1) {
dict_opt = mp_obj_get_int(args[1]);
}
if (dict_opt >= 16) {
int st = uzlib_gzip_parse_header(&o->decomp);
if (st != TINF_OK) {
goto header_error;
}
dict_sz = 1 << (dict_opt - 16);
} else if (dict_opt >= 0) {
dict_opt = uzlib_zlib_parse_header(&o->decomp);
if (dict_opt < 0) {
header_error:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "compression header"));
}
dict_sz = 1 << dict_opt;
} else {
dict_sz = 1 << -dict_opt;
}
uzlib_uncompress_init(&o->decomp, m_new(byte, dict_sz), dict_sz);
return MP_OBJ_FROM_PTR(o);
}
STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
mp_obj_decompio_t *o = MP_OBJ_TO_PTR(o_in);
if (o->eof) {
return 0;
}
o->decomp.dest = buf;
o->decomp.destSize = size;
int st = uzlib_uncompress_chksum(&o->decomp);
if (st == TINF_DONE) {
o->eof = true;
}
if (st < 0) {
*errcode = MP_EINVAL;
return MP_STREAM_ERROR;
}
return o->decomp.dest - (byte*)buf;
}
STATIC const mp_rom_map_elem_t decompio_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) },
};
STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
STATIC const mp_stream_p_t decompio_stream_p = {
.read = decompio_read,
};
STATIC const mp_obj_type_t decompio_type = {
{ &mp_type_type },
.name = MP_QSTR_DecompIO,
.make_new = decompio_make_new,
.protocol = &decompio_stream_p,
.locals_dict = (void*)&decompio_locals_dict,
};
STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
(void)n_args;
mp_obj_t data = args[0];
@@ -56,43 +150,68 @@ STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
TINF_DATA *decomp = m_new_obj(TINF_DATA);
memset(decomp, 0, sizeof(*decomp));
DEBUG_printf("sizeof(TINF_DATA)=" UINT_FMT "\n", sizeof(*decomp));
uzlib_uncompress_init(decomp, NULL, 0);
mp_uint_t dest_buf_size = (bufinfo.len + 15) & ~15;
byte *dest_buf = m_new(byte, dest_buf_size);
decomp->destSize = (bufinfo.len + 15) & ~15;
decomp->destStart = m_new(byte, decomp->destSize);
decomp->dest = dest_buf;
decomp->destSize = dest_buf_size;
DEBUG_printf("uzlib: Initial out buffer: " UINT_FMT " bytes\n", decomp->destSize);
decomp->destGrow = mod_uzlib_grow_buf;
decomp->source = bufinfo.buf;
int st;
bool is_zlib = true;
if (n_args > 1 && MP_OBJ_SMALL_INT_VALUE(args[1]) < 0) {
st = tinf_uncompress_dyn(decomp);
} else {
st = tinf_zlib_uncompress_dyn(decomp, bufinfo.len);
}
if (st != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st)));
is_zlib = false;
}
mp_uint_t final_sz = decomp->dest - decomp->destStart;
DEBUG_printf("uzlib: Resizing from " UINT_FMT " to final size: " UINT_FMT " bytes\n", decomp->destSize, final_sz);
decomp->destStart = (byte*)m_renew(byte, decomp->destStart, decomp->destSize, final_sz);
mp_obj_t res = mp_obj_new_bytearray_by_ref(final_sz, decomp->destStart);
if (is_zlib) {
st = uzlib_zlib_parse_header(decomp);
if (st < 0) {
goto error;
}
}
while (1) {
st = uzlib_uncompress_chksum(decomp);
if (st < 0) {
goto error;
}
if (st == TINF_DONE) {
break;
}
size_t offset = decomp->dest - dest_buf;
dest_buf = m_renew(byte, dest_buf, dest_buf_size, dest_buf_size + 256);
dest_buf_size += 256;
decomp->dest = dest_buf + offset;
decomp->destSize = 256;
}
mp_uint_t final_sz = decomp->dest - dest_buf;
DEBUG_printf("uzlib: Resizing from " UINT_FMT " to final size: " UINT_FMT " bytes\n", dest_buf_size, final_sz);
dest_buf = (byte*)m_renew(byte, dest_buf, dest_buf_size, final_sz);
mp_obj_t res = mp_obj_new_bytearray_by_ref(final_sz, dest_buf);
m_del_obj(TINF_DATA, decomp);
return res;
error:
nlr_raise(mp_obj_new_exception_arg1(&mp_type_ValueError, MP_OBJ_NEW_SMALL_INT(st)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_uzlib_decompress_obj, 1, 3, mod_uzlib_decompress);
STATIC const mp_rom_map_elem_t mp_module_uzlib_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uzlib) },
{ MP_ROM_QSTR(MP_QSTR_decompress), MP_ROM_PTR(&mod_uzlib_decompress_obj) },
{ MP_ROM_QSTR(MP_QSTR_DecompIO), MP_ROM_PTR(&decompio_type) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_uzlib_globals, mp_module_uzlib_globals_table);
const mp_obj_module_t mp_module_uzlib = {
.base = { &mp_type_module },
.name = MP_QSTR_uzlib,
.globals = (mp_obj_dict_t*)&mp_module_uzlib_globals,
};
@@ -101,6 +220,8 @@ const mp_obj_module_t mp_module_uzlib = {
#include "uzlib/tinflate.c"
#include "uzlib/tinfzlib.c"
#include "uzlib/tinfgzip.c"
#include "uzlib/adler32.c"
#include "uzlib/crc32.c"
#endif // MICROPY_PY_UZLIB

View File

@@ -310,9 +310,10 @@ 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);
len = MIN(len, sizeof(webrepl_passwd) - 1);
memcpy(webrepl_passwd, passwd, len);
webrepl_passwd[len] = 0;
if (len > sizeof(webrepl_passwd) - 1) {
mp_raise_ValueError("");
}
strcpy(webrepl_passwd, passwd);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(webrepl_set_password_obj, webrepl_set_password);
@@ -339,7 +340,7 @@ STATIC const mp_obj_type_t webrepl_type = {
};
STATIC const mp_map_elem_t webrepl_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_websocket) },
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR__webrepl) },
{ MP_OBJ_NEW_QSTR(MP_QSTR__webrepl), (mp_obj_t)&webrepl_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_password), (mp_obj_t)&webrepl_set_password_obj },
};
@@ -348,7 +349,6 @@ STATIC MP_DEFINE_CONST_DICT(webrepl_module_globals, webrepl_module_globals_table
const mp_obj_module_t mp_module_webrepl = {
.base = { &mp_type_module },
.name = MP_QSTR__webrepl,
.globals = (mp_obj_dict_t*)&webrepl_module_globals,
};

View File

@@ -313,7 +313,6 @@ STATIC MP_DEFINE_CONST_DICT(websocket_module_globals, websocket_module_globals_t
const mp_obj_module_t mp_module_websocket = {
.base = { &mp_type_module },
.name = MP_QSTR_websocket,
.globals = (mp_obj_dict_t*)&websocket_module_globals,
};

89
extmod/utime_mphal.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) 2013-2016 Damien P. George
* Copyright (c) 2016 Paul Sokolovsky
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/mpconfig.h"
#if MICROPY_PY_UTIME_MP_HAL
#include <string.h>
#include "py/obj.h"
#include "py/mphal.h"
#include "py/smallint.h"
#include "extmod/utime_mphal.h"
STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
#if MICROPY_PY_BUILTINS_FLOAT
mp_hal_delay_ms(1000 * mp_obj_get_float(seconds_o));
#else
mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o));
#endif
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_obj, time_sleep);
STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) {
mp_int_t ms = mp_obj_get_int(arg);
if (ms > 0) {
mp_hal_delay_ms(ms);
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_ms_obj, time_sleep_ms);
STATIC mp_obj_t time_sleep_us(mp_obj_t arg) {
mp_int_t us = mp_obj_get_int(arg);
if (us > 0) {
mp_hal_delay_us(us);
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_us_obj, time_sleep_us);
STATIC mp_obj_t time_ticks_ms(void) {
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & MP_SMALL_INT_POSITIVE_MASK);
}
MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_ms_obj, time_ticks_ms);
STATIC mp_obj_t time_ticks_us(void) {
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_us() & MP_SMALL_INT_POSITIVE_MASK);
}
MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_us_obj, time_ticks_us);
STATIC mp_obj_t time_ticks_cpu(void) {
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_cpu() & MP_SMALL_INT_POSITIVE_MASK);
}
MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_cpu_obj, time_ticks_cpu);
STATIC mp_obj_t time_ticks_diff(mp_obj_t start_in, mp_obj_t end_in) {
// we assume that the arguments come from ticks_xx so are small ints
uint32_t start = MP_OBJ_SMALL_INT_VALUE(start_in);
uint32_t end = MP_OBJ_SMALL_INT_VALUE(end_in);
return MP_OBJ_NEW_SMALL_INT((end - start) & MP_SMALL_INT_POSITIVE_MASK);
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj, time_ticks_diff);
#endif // MICROPY_PY_UTIME_MP_HAL

36
extmod/utime_mphal.h Normal file
View File

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

View File

@@ -41,12 +41,12 @@
#define A32_BASE 65521
#define A32_NMAX 5552
unsigned int tinf_adler32(const void *data, unsigned int length)
uint32_t uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum /* 1 */)
{
const unsigned char *buf = (const unsigned char *)data;
unsigned int s1 = 1;
unsigned int s2 = 0;
unsigned int s1 = prev_sum & 0xffff;
unsigned int s2 = prev_sum >> 16;
while (length > 0)
{

63
extmod/uzlib/crc32.c Normal file
View File

@@ -0,0 +1,63 @@
/*
* CRC32 checksum
*
* Copyright (c) 1998-2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* This software is provided 'as-is', without any express
* or implied warranty. In no event will the authors be
* held liable for any damages arising from the use of
* this software.
*
* Permission is granted to anyone to use this software
* for any purpose, including commercial applications,
* and to alter it and redistribute it freely, subject to
* the following restrictions:
*
* 1. The origin of this software must not be
* misrepresented; you must not claim that you
* wrote the original software. If you use this
* software in a product, an acknowledgment in
* the product documentation would be appreciated
* but is not required.
*
* 2. Altered source versions must be plainly marked
* as such, and must not be misrepresented as
* being the original software.
*
* 3. This notice may not be removed or altered from
* any source distribution.
*/
/*
* CRC32 algorithm taken from the zlib source, which is
* Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
*/
#include "tinf.h"
static const unsigned int tinf_crc32tab[16] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190,
0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344,
0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278,
0xbdbdf21c
};
/* crc is previous value for incremental computation, 0xffffffff initially */
uint32_t uzlib_crc32(const void *data, unsigned int length, uint32_t crc)
{
const unsigned char *buf = (const unsigned char *)data;
unsigned int i;
for (i = 0; i < length; ++i)
{
crc ^= buf[i];
crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4);
crc = tinf_crc32tab[crc & 0x0f] ^ (crc >> 4);
}
// return value suitable for passing in next time, for final value invert it
return crc/* ^ 0xffffffff*/;
}

View File

@@ -5,7 +5,7 @@
* All Rights Reserved
* http://www.ibsensoftware.com/
*
* Copyright (c) 2014 by Paul Sokolovsky
* Copyright (c) 2014-2016 by Paul Sokolovsky
*/
#ifndef TINF_H_INCLUDED
@@ -26,9 +26,18 @@
extern "C" {
#endif
/* ok status, more data produced */
#define TINF_OK 0
/* end of compressed stream reached */
#define TINF_DONE 1
#define TINF_DATA_ERROR (-3)
#define TINF_DEST_OVERFLOW (-4)
#define TINF_CHKSUM_ERROR (-4)
#define TINF_DICT_ERROR (-5)
/* checksum types */
#define TINF_CHKSUM_NONE 0
#define TINF_CHKSUM_ADLER 1
#define TINF_CHKSUM_CRC 2
/* data structures */
@@ -40,6 +49,10 @@ typedef struct {
struct TINF_DATA;
typedef struct TINF_DATA {
const unsigned char *source;
/* If source above is NULL, this function will be used to read
next byte from source stream */
unsigned char (*readSource)(struct TINF_DATA *data);
unsigned int tag;
unsigned int bitcount;
@@ -51,49 +64,51 @@ typedef struct TINF_DATA {
unsigned char *dest;
/* Remaining bytes in buffer */
unsigned int destRemaining;
/* Argument is the allocation size which didn't fit into buffer. Note that
exact mimumum size to grow buffer by is lastAlloc - destRemaining. But
growing by this exact size is ineficient, as the next allocation will
fail again. */
int (*destGrow)(struct TINF_DATA *data, unsigned int lastAlloc);
/* Accumulating checksum */
unsigned int checksum;
char checksum_type;
int btype;
int bfinal;
unsigned int curlen;
int lzOff;
unsigned char *dict_ring;
unsigned int dict_size;
unsigned int dict_idx;
TINF_TREE ltree; /* dynamic length/symbol tree */
TINF_TREE dtree; /* dynamic distance tree */
} TINF_DATA;
#define TINF_PUT(d, c) \
{ \
*d->dest++ = c; \
if (d->dict_ring) { d->dict_ring[d->dict_idx++] = c; if (d->dict_idx == d->dict_size) d->dict_idx = 0; } \
}
/* low-level API */
unsigned char TINFCC uzlib_get_byte(TINF_DATA *d);
/* Step 1: Allocate TINF_DATA structure */
/* Step 2: Set destStart, destSize, and destGrow fields */
/* Step 3: Set source field */
/* Step 4: Call tinf_uncompress_dyn() */
/* Step 5: In response to destGrow callback, update destStart and destSize fields */
/* Step 6: When tinf_uncompress_dyn() returns, buf.dest points to a byte past last uncompressed byte */
/* Decompression API */
int TINFCC tinf_uncompress_dyn(TINF_DATA *d);
int TINFCC tinf_zlib_uncompress_dyn(TINF_DATA *d, unsigned int sourceLen);
void TINFCC uzlib_init(void);
void TINFCC uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen);
int TINFCC uzlib_uncompress(TINF_DATA *d);
int TINFCC uzlib_uncompress_chksum(TINF_DATA *d);
/* high-level API */
int TINFCC uzlib_zlib_parse_header(TINF_DATA *d);
int TINFCC uzlib_gzip_parse_header(TINF_DATA *d);
void TINFCC tinf_init(void);
/* Compression API */
int TINFCC tinf_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);
void TINFCC uzlib_compress(void *data, const uint8_t *src, unsigned slen);
int TINFCC tinf_gzip_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);
/* Checksum API */
int TINFCC tinf_zlib_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen);
unsigned int TINFCC tinf_adler32(const void *data, unsigned int length);
unsigned int TINFCC tinf_crc32(const void *data, unsigned int length);
/* compression API */
void TINFCC tinf_compress(void *data, const uint8_t *src, unsigned slen);
/* prev_sum is previous value for incremental computation, 1 initially */
uint32_t TINFCC uzlib_adler32(const void *data, unsigned int length, uint32_t prev_sum);
/* crc is previous value for incremental computation, 0xffffffff initially */
uint32_t TINFCC uzlib_crc32(const void *data, unsigned int length, uint32_t crc);
#ifdef __cplusplus
} /* extern "C" */

110
extmod/uzlib/tinfgzip.c Normal file
View File

@@ -0,0 +1,110 @@
/*
* tinfgzip - tiny gzip decompressor
*
* Copyright (c) 2003 by Joergen Ibsen / Jibz
* All Rights Reserved
*
* http://www.ibsensoftware.com/
*
* Copyright (c) 2014-2016 by Paul Sokolovsky
*
* This software is provided 'as-is', without any express
* or implied warranty. In no event will the authors be
* held liable for any damages arising from the use of
* this software.
*
* Permission is granted to anyone to use this software
* for any purpose, including commercial applications,
* and to alter it and redistribute it freely, subject to
* the following restrictions:
*
* 1. The origin of this software must not be
* misrepresented; you must not claim that you
* wrote the original software. If you use this
* software in a product, an acknowledgment in
* the product documentation would be appreciated
* but is not required.
*
* 2. Altered source versions must be plainly marked
* as such, and must not be misrepresented as
* being the original software.
*
* 3. This notice may not be removed or altered from
* any source distribution.
*/
#include "tinf.h"
#define FTEXT 1
#define FHCRC 2
#define FEXTRA 4
#define FNAME 8
#define FCOMMENT 16
void tinf_skip_bytes(TINF_DATA *d, int num);
uint16_t tinf_get_uint16(TINF_DATA *d);
void tinf_skip_bytes(TINF_DATA *d, int num)
{
while (num--) uzlib_get_byte(d);
}
uint16_t tinf_get_uint16(TINF_DATA *d)
{
unsigned int v = uzlib_get_byte(d);
v = (uzlib_get_byte(d) << 8) | v;
return v;
}
int uzlib_gzip_parse_header(TINF_DATA *d)
{
unsigned char flg;
/* -- check format -- */
/* check id bytes */
if (uzlib_get_byte(d) != 0x1f || uzlib_get_byte(d) != 0x8b) return TINF_DATA_ERROR;
/* check method is deflate */
if (uzlib_get_byte(d) != 8) return TINF_DATA_ERROR;
/* get flag byte */
flg = uzlib_get_byte(d);
/* check that reserved bits are zero */
if (flg & 0xe0) return TINF_DATA_ERROR;
/* -- find start of compressed data -- */
/* skip rest of base header of 10 bytes */
tinf_skip_bytes(d, 6);
/* skip extra data if present */
if (flg & FEXTRA)
{
unsigned int xlen = tinf_get_uint16(d);
tinf_skip_bytes(d, xlen);
}
/* skip file name if present */
if (flg & FNAME) { while (uzlib_get_byte(d)); }
/* skip file comment if present */
if (flg & FCOMMENT) { while (uzlib_get_byte(d)); }
/* check header crc if present */
if (flg & FHCRC)
{
/*unsigned int hcrc =*/ tinf_get_uint16(d);
// TODO: Check!
// if (hcrc != (tinf_crc32(src, start - src) & 0x0000ffff))
// return TINF_DATA_ERROR;
}
/* initialize for crc32 checksum */
d->checksum_type = TINF_CHKSUM_CRC;
d->checksum = ~0;
return TINF_OK;
}

View File

@@ -5,7 +5,7 @@
* All Rights Reserved
* http://www.ibsensoftware.com/
*
* Copyright (c) 2014 by Paul Sokolovsky
* Copyright (c) 2014-2016 by Paul Sokolovsky
*
* This software is provided 'as-is', without any express
* or implied warranty. In no event will the authors be
@@ -32,8 +32,12 @@
* any source distribution.
*/
#include <assert.h>
#include "tinf.h"
uint32_t tinf_get_le_uint32(TINF_DATA *d);
uint32_t tinf_get_be_uint32(TINF_DATA *d);
/* --------------------------------------------------- *
* -- uninitialized global data (static structures) -- *
* --------------------------------------------------- */
@@ -89,21 +93,6 @@ const unsigned char clcidx[] = {
* -- utility functions -- *
* ----------------------- */
/* Execute callback to grow destination buffer */
static int tinf_grow_dest_buf(TINF_DATA *d, unsigned int lastAlloc)
{
unsigned int oldsize = d->dest - d->destStart;
/* This will update only destStart and destSize */
if (!d->destGrow)
{
return TINF_DEST_OVERFLOW;
}
d->destGrow(d, lastAlloc);
d->dest = d->destStart + oldsize;
d->destRemaining = d->destSize - oldsize;
return 0;
}
#ifdef RUNTIME_BITS_TABLES
/* build extra bits and base tables */
static void tinf_build_bits_base(unsigned char *bits, unsigned short *base, int delta, int first)
@@ -180,6 +169,34 @@ static void tinf_build_tree(TINF_TREE *t, const unsigned char *lengths, unsigned
* -- decode functions -- *
* ---------------------- */
unsigned char uzlib_get_byte(TINF_DATA *d)
{
if (d->source) {
return *d->source++;
}
return d->readSource(d);
}
uint32_t tinf_get_le_uint32(TINF_DATA *d)
{
uint32_t val = 0;
int i;
for (i = 4; i--;) {
val = val >> 8 | uzlib_get_byte(d) << 24;
}
return val;
}
uint32_t tinf_get_be_uint32(TINF_DATA *d)
{
uint32_t val = 0;
int i;
for (i = 4; i--;) {
val = val << 8 | uzlib_get_byte(d);
}
return val;
}
/* get one bit from source stream */
static int tinf_getbit(TINF_DATA *d)
{
@@ -189,7 +206,7 @@ static int tinf_getbit(TINF_DATA *d)
if (!d->bitcount--)
{
/* load next tag */
d->tag = *d->source++;
d->tag = uzlib_get_byte(d);
d->bitcount = 7;
}
@@ -318,113 +335,86 @@ static void tinf_decode_trees(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
/* given a stream and two trees, inflate a block of data */
static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt)
{
while (1)
{
int sym = tinf_decode_symbol(d, lt);
if (d->curlen == 0) {
unsigned int offs;
int dist;
int sym = tinf_decode_symbol(d, lt);
//printf("huff sym: %02x\n", sym);
/* check for end of block */
if (sym == 256)
{
return TINF_OK;
}
/* literal byte */
if (sym < 256) {
TINF_PUT(d, sym);
return TINF_OK;
}
if (sym < 256)
{
if (d->destRemaining == 0)
{
int res = tinf_grow_dest_buf(d, 1);
if (res) return res;
}
/* end of block */
if (sym == 256) {
return TINF_DONE;
}
*d->dest++ = sym;
d->destRemaining--;
/* substring from sliding dictionary */
sym -= 257;
/* possibly get more bits from length code */
d->curlen = tinf_read_bits(d, length_bits[sym], length_base[sym]);
} else {
dist = tinf_decode_symbol(d, dt);
/* possibly get more bits from distance code */
offs = tinf_read_bits(d, dist_bits[dist], dist_base[dist]);
if (d->dict_ring) {
if (offs > d->dict_size) {
return TINF_DICT_ERROR;
}
d->lzOff = d->dict_idx - offs;
if (d->lzOff < 0) {
d->lzOff += d->dict_size;
}
} else {
d->lzOff = -offs;
}
}
unsigned int length, offs, i;
int dist;
sym -= 257;
/* possibly get more bits from length code */
length = tinf_read_bits(d, length_bits[sym], length_base[sym]);
dist = tinf_decode_symbol(d, dt);
/* possibly get more bits from distance code */
offs = tinf_read_bits(d, dist_bits[dist], dist_base[dist]);
if (d->destRemaining < length)
{
int res = tinf_grow_dest_buf(d, length);
if (res) return res;
}
/* copy match */
for (i = 0; i < length; ++i)
{
d->dest[i] = d->dest[(int)(i - offs)];
}
d->dest += length;
d->destRemaining -= length;
}
}
/* copy next byte from dict substring */
if (d->dict_ring) {
TINF_PUT(d, d->dict_ring[d->lzOff]);
if ((unsigned)++d->lzOff == d->dict_size) {
d->lzOff = 0;
}
} else {
d->dest[0] = d->dest[d->lzOff];
d->dest++;
}
d->curlen--;
return TINF_OK;
}
/* inflate an uncompressed block of data */
static int tinf_inflate_uncompressed_block(TINF_DATA *d)
{
unsigned int length, invlength;
unsigned int i;
if (d->curlen == 0) {
unsigned int length, invlength;
/* get length */
length = d->source[1];
length = 256*length + d->source[0];
/* get length */
length = uzlib_get_byte(d) + 256 * uzlib_get_byte(d);
/* get one's complement of length */
invlength = uzlib_get_byte(d) + 256 * uzlib_get_byte(d);
/* check length */
if (length != (~invlength & 0x0000ffff)) return TINF_DATA_ERROR;
/* get one's complement of length */
invlength = d->source[3];
invlength = 256*invlength + d->source[2];
/* increment length to properly return TINF_DONE below, without
producing data at the same time */
d->curlen = length + 1;
/* check length */
if (length != (~invlength & 0x0000ffff)) return TINF_DATA_ERROR;
/* make sure we start next block on a byte boundary */
d->bitcount = 0;
}
if (d->destRemaining < length)
{
int res = tinf_grow_dest_buf(d, length);
if (res) return res;
}
if (--d->curlen == 0) {
return TINF_DONE;
}
d->source += 4;
/* copy block */
for (i = length; i; --i) *d->dest++ = *d->source++;
d->destRemaining -= length;
/* make sure we start next block on a byte boundary */
d->bitcount = 0;
return TINF_OK;
}
/* inflate a block of data compressed with fixed huffman trees */
static int tinf_inflate_fixed_block(TINF_DATA *d)
{
/* build fixed huffman trees */
tinf_build_fixed_trees(&d->ltree, &d->dtree);
/* decode block using fixed trees */
return tinf_inflate_block_data(d, &d->ltree, &d->dtree);
}
/* inflate a block of data compressed with dynamic huffman trees */
static int tinf_inflate_dynamic_block(TINF_DATA *d)
{
/* decode trees from stream */
tinf_decode_trees(d, &d->ltree, &d->dtree);
/* decode block using decoded trees */
return tinf_inflate_block_data(d, &d->ltree, &d->dtree);
unsigned char c = uzlib_get_byte(d);
TINF_PUT(d, c);
return TINF_OK;
}
/* ---------------------- *
@@ -432,7 +422,7 @@ static int tinf_inflate_dynamic_block(TINF_DATA *d)
* ---------------------- */
/* initialize global (static) data */
void tinf_init(void)
void uzlib_init(void)
{
#ifdef RUNTIME_BITS_TABLES
/* build extra bits and base tables */
@@ -445,72 +435,117 @@ void tinf_init(void)
#endif
}
/* inflate stream from source to dest */
int tinf_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen)
/* initialize decompression structure */
void uzlib_uncompress_init(TINF_DATA *d, void *dict, unsigned int dictLen)
{
(void)sourceLen;
TINF_DATA d;
int res;
/* initialise data */
d.source = (const unsigned char *)source;
d.destStart = (unsigned char *)dest;
d.destRemaining = *destLen;
d.destSize = *destLen;
res = tinf_uncompress_dyn(&d);
*destLen = d.dest - d.destStart;
return res;
}
/* inflate stream from source to dest */
int tinf_uncompress_dyn(TINF_DATA *d)
{
int bfinal;
/* initialise data */
d->bitcount = 0;
d->dest = d->destStart;
d->destRemaining = d->destSize;
do {
unsigned int btype;
int res;
/* read final block flag */
bfinal = tinf_getbit(d);
/* read block type (2 bits) */
btype = tinf_read_bits(d, 2, 0);
/* decompress block */
switch (btype)
{
case 0:
/* decompress uncompressed block */
res = tinf_inflate_uncompressed_block(d);
break;
case 1:
/* decompress block with fixed huffman trees */
res = tinf_inflate_fixed_block(d);
break;
case 2:
/* decompress block with dynamic huffman trees */
res = tinf_inflate_dynamic_block(d);
break;
default:
return TINF_DATA_ERROR;
}
if (res != TINF_OK) return TINF_DATA_ERROR;
} while (!bfinal);
return TINF_OK;
d->bfinal = 0;
d->btype = -1;
d->dict_size = dictLen;
d->dict_ring = dict;
d->dict_idx = 0;
d->curlen = 0;
}
/* inflate next byte of compressed stream */
int uzlib_uncompress(TINF_DATA *d)
{
do {
int res;
/* start a new block */
if (d->btype == -1) {
next_blk:
/* read final block flag */
d->bfinal = tinf_getbit(d);
/* read block type (2 bits) */
d->btype = tinf_read_bits(d, 2, 0);
//printf("Started new block: type=%d final=%d\n", d->btype, d->bfinal);
if (d->btype == 1) {
/* build fixed huffman trees */
tinf_build_fixed_trees(&d->ltree, &d->dtree);
} else if (d->btype == 2) {
/* decode trees from stream */
tinf_decode_trees(d, &d->ltree, &d->dtree);
}
}
/* process current block */
switch (d->btype)
{
case 0:
/* decompress uncompressed block */
res = tinf_inflate_uncompressed_block(d);
break;
case 1:
case 2:
/* decompress block with fixed/dyanamic huffman trees */
/* trees were decoded previously, so it's the same routine for both */
res = tinf_inflate_block_data(d, &d->ltree, &d->dtree);
break;
default:
return TINF_DATA_ERROR;
}
if (res == TINF_DONE && !d->bfinal) {
/* the block has ended (without producing more data), but we
can't return without data, so start procesing next block */
goto next_blk;
}
if (res != TINF_OK) {
return res;
}
} while (--d->destSize);
return TINF_OK;
}
int uzlib_uncompress_chksum(TINF_DATA *d)
{
int res;
unsigned char *data = d->dest;
res = uzlib_uncompress(d);
if (res < 0) return res;
switch (d->checksum_type) {
case TINF_CHKSUM_ADLER:
d->checksum = uzlib_adler32(data, d->dest - data, d->checksum);
break;
case TINF_CHKSUM_CRC:
d->checksum = uzlib_crc32(data, d->dest - data, d->checksum);
break;
}
if (res == TINF_DONE) {
unsigned int val;
switch (d->checksum_type) {
case TINF_CHKSUM_ADLER:
val = tinf_get_be_uint32(d);
if (d->checksum != val) {
return TINF_CHKSUM_ERROR;
}
break;
case TINF_CHKSUM_CRC:
val = tinf_get_le_uint32(d);
if (~d->checksum != val) {
return TINF_CHKSUM_ERROR;
}
// Uncompressed size. TODO: Check
val = tinf_get_le_uint32(d);
break;
}
}
return res;
}

View File

@@ -6,6 +6,8 @@
*
* http://www.ibsensoftware.com/
*
* Copyright (c) 2014-2016 by Paul Sokolovsky
*
* This software is provided 'as-is', without any express
* or implied warranty. In no event will the authors be
* held liable for any damages arising from the use of
@@ -33,35 +35,14 @@
#include "tinf.h"
int tinf_zlib_uncompress(void *dest, unsigned int *destLen,
const void *source, unsigned int sourceLen)
int uzlib_zlib_parse_header(TINF_DATA *d)
{
TINF_DATA d;
int res;
/* initialise data */
d.source = (const unsigned char *)source;
d.destStart = (unsigned char *)dest;
d.destRemaining = *destLen;
res = tinf_zlib_uncompress_dyn(&d, sourceLen);
*destLen = d.dest - d.destStart;
return res;
}
int tinf_zlib_uncompress_dyn(TINF_DATA *d, unsigned int sourceLen)
{
unsigned int a32;
int res;
unsigned char cmf, flg;
/* -- get header bytes -- */
cmf = d->source[0];
flg = d->source[1];
cmf = uzlib_get_byte(d);
flg = uzlib_get_byte(d);
/* -- check format -- */
@@ -77,25 +58,9 @@ int tinf_zlib_uncompress_dyn(TINF_DATA *d, unsigned int sourceLen)
/* check there is no preset dictionary */
if (flg & 0x20) return TINF_DATA_ERROR;
/* -- get adler32 checksum -- */
/* initialize for adler32 checksum */
d->checksum_type = TINF_CHKSUM_ADLER;
d->checksum = 1;
a32 = d->source[sourceLen - 4];
a32 = 256*a32 + d->source[sourceLen - 3];
a32 = 256*a32 + d->source[sourceLen - 2];
a32 = 256*a32 + d->source[sourceLen - 1];
d->source += 2;
/* -- inflate -- */
res = tinf_uncompress_dyn(d);
if (res != TINF_OK) return res;
/* -- check adler32 checksum -- */
if (a32 != tinf_adler32(d->destStart, d->dest - d->destStart)) return TINF_DATA_ERROR;
return TINF_OK;
return cmf >> 4;
}

View File

@@ -31,6 +31,7 @@
#include <string.h>
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/mperrno.h"
#include "lib/fatfs/ff.h"
#include "lib/fatfs/diskio.h"
#include "extmod/vfs_fat_file.h"
@@ -76,25 +77,42 @@ STATIC mp_obj_t fat_vfs_listdir_func(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fat_vfs_listdir_obj, 1, 2, fat_vfs_listdir_func);
STATIC mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) {
(void)vfs_in;
STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t path_in, mp_int_t attr) {
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);
if (res == FR_OK) {
FILINFO fno;
#if _USE_LFN
fno.lfname = NULL;
fno.lfsize = 0;
#endif
FRESULT res = f_stat(path, &fno);
if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
}
// check if path is a file or directory
if ((fno.fattrib & AM_DIR) == attr) {
res = f_unlink(path);
if (res != FR_OK) {
mp_raise_OSError(fresult_to_errno_table[res]);
}
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])));
mp_raise_OSError(attr ? MP_ENOTDIR : MP_EISDIR);
}
}
STATIC mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) {
(void)vfs_in;
return fat_vfs_remove_internal(path_in, 0); // 0 == file attribute
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_remove_obj, fat_vfs_remove);
STATIC mp_obj_t fat_vfs_rmdir(mp_obj_t vfs_in, mp_obj_t path_in) {
// TODO: Currently just redirects to fat_vfs_remove(), which are
// backed by the same underlying FatFs function. Should at least
// check that path is actually a dir.
return fat_vfs_remove(vfs_in, path_in);
(void) vfs_in;
return fat_vfs_remove_internal(path_in, AM_DIR);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_rmdir_obj, fat_vfs_rmdir);
@@ -106,8 +124,7 @@ STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t 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])));
mp_raise_OSError(fresult_to_errno_table[res]);
}
}
@@ -120,8 +137,7 @@ STATIC mp_obj_t fat_vfs_mkdir(mp_obj_t vfs_in, mp_obj_t path_o) {
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])));
mp_raise_OSError(fresult_to_errno_table[res]);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_mkdir_obj, fat_vfs_mkdir);
@@ -139,8 +155,7 @@ STATIC mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) {
}
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_raise_OSError(fresult_to_errno_table[res]);
}
return mp_const_none;
@@ -154,7 +169,7 @@ STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) {
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])));
mp_raise_OSError(fresult_to_errno_table[res]);
}
return mp_obj_new_str(buf, strlen(buf), false);
@@ -215,8 +230,7 @@ STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
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_raise_OSError(fresult_to_errno_table[res]);
}
}
@@ -250,6 +264,42 @@ STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_stat_obj, fat_vfs_stat);
// Get the status of a VFS.
STATIC mp_obj_t fat_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) {
(void)vfs_in;
const char *path = mp_obj_str_get_str(path_in);
FATFS *fatfs;
DWORD nclst;
FRESULT res = f_getfree(path, &nclst, &fatfs);
if (FR_OK != res) {
mp_raise_OSError(fresult_to_errno_table[res]);
}
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
t->items[0] = MP_OBJ_NEW_SMALL_INT(fatfs->csize * fatfs->ssize); // f_bsize
t->items[1] = t->items[0]; // f_frsize
t->items[2] = MP_OBJ_NEW_SMALL_INT((fatfs->n_fatent - 2) * fatfs->csize); // f_blocks
t->items[3] = MP_OBJ_NEW_SMALL_INT(nclst); // f_bfree
t->items[4] = t->items[3]; // f_bavail
t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // f_files
t->items[6] = MP_OBJ_NEW_SMALL_INT(0); // f_ffree
t->items[7] = MP_OBJ_NEW_SMALL_INT(0); // f_favail
t->items[8] = MP_OBJ_NEW_SMALL_INT(0); // f_flags
t->items[9] = MP_OBJ_NEW_SMALL_INT(_MAX_LFN); // f_namemax
return MP_OBJ_FROM_PTR(t);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_statvfs_obj, fat_vfs_statvfs);
// Unmount the filesystem
STATIC mp_obj_t fat_vfs_umount(mp_obj_t vfs_in) {
fatfs_umount(((fs_user_mount_t *)vfs_in)->readblocks[1]);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, fat_vfs_umount);
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) },
@@ -261,6 +311,8 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
{ 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) },
{ MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&fat_vfs_statvfs_obj) },
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&fat_vfs_umount_obj) },
};
STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table);

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