Compare commits

...

696 Commits
v1.5.1 ... v1.7

Author SHA1 Message Date
Damien George
9b0a150bd6 docs: Bump version to 1.7. 2016-04-11 12:18:10 +01:00
Paul Sokolovsky
f8fb4470a0 extmod/modwebsocket: write(): Support write size beyond 125 bytes. 2016-04-11 14:07:57 +03:00
Paul Sokolovsky
7063210014 extmod/modlwip: Fix for loss of data in unaccepted incoming sockets.
When lwIP creates a incoming connection socket of a listen socket, it
sets its recv callback to one which discards incoming data. We set
proper callback only in accept() call, when we allocate Python-level
socket where we can queue incoming data. So, in lwIP accept callback
be sure to set recv callback to one which tells lwIP to not discard
incoming data.
2016-04-11 01:21:34 +03:00
Paul Sokolovsky
1cc81ed449 esp8266/modesp: Add freemem() and meminfo() functions.
They call into vendor SDK functions system_get_free_heap_size() and
system_print_meminfo() respectively.
2016-04-11 01:16:38 +03:00
Paul Sokolovsky
c734de490a esp8266/main: mp_builtin_open(): Implement, using vfs_proxy_call(). 2016-04-10 16:59:19 +03:00
Damien George
358e5d8bad py/stream: Move uPy func obj wrappers to below their respective funcs. 2016-04-10 12:41:28 +01:00
Damien George
657aef66ff py/stream: Simplify arg extraction logic for stream_ioctl.
Saves 16 bytes of code.

Also, use mp_obj_get_int_truncated to allow integers as big as a machine
word to be passed as the value.
2016-04-10 12:37:59 +01:00
Damien George
6e87aeb841 esp8266: Implement multistage bootstrap sequence.
Upon start-up, _boot module is executed from frozen files to do early
initialization, e.g. create and mount the flash filesystem. Then
"boot.py" is executed if it exists in the filesystem. Finally, "main.py"
is executed if exists to allow start-on-boot user applications.

This allows a user to make a custom boot file or startup application
without recompiling the firmware, while letting to do early initialization
in Python code.

Based on RFC https://github.com/micropython/micropython/issues/1955.
2016-04-10 14:24:41 +03:00
Paul Sokolovsky
b69f798c92 extmod/modwebsocket.h: Split websocket-related defines for reuse. 2016-04-10 13:42:51 +03:00
Paul Sokolovsky
558fd5d228 py/stream: ioctl(): Properly support 2-arg form. 2016-04-10 13:36:44 +03:00
Paul Sokolovsky
6c3db26ab7 py/stream: Fix signed comparison issue. 2016-04-10 13:31:52 +03:00
Paul Sokolovsky
d6236e85c2 extmod/modwebsocket: Implement MP_STREAM_SET_DATA_OPTS ioctl.
Allows to set fragment type (txt/bin/etc.) for output records.
2016-04-10 13:19:26 +03:00
Paul Sokolovsky
6837dba6b8 extmod/modwebsocket: Allow to get type of last read data using ioctl(). 2016-04-10 12:50:46 +03:00
Paul Sokolovsky
0c97e4c414 py/stream: Add Python-level ioctl() method.
Will call underlying C virtual methods of stream interface. This isn't
intended to be added to every stream object (it's not in CPython), but
is convenient way to expose extra operation on Python side without
adding bunch of Python-level methods.
2016-04-10 12:45:46 +03:00
Paul Sokolovsky
a45e280c58 py/stream.h: Add bigger inventory of stream ioctl's. 2016-04-10 12:42:41 +03:00
Paul Sokolovsky
f38e8f5217 extmod/modwebsocket: Record current fragment type (binary/text/etc.)
Also, handle continuation frames (untested).
2016-04-09 16:14:47 +03:00
Paul Sokolovsky
5b1c221785 extmod/modwebsocket: Add option for blocking writes to non-blk sockets.
This is strange asymmetry which is sometimes needed, e.g. for WebREPL: we
want to process only available input and no more; but for output, we want
to get rid of all of it, because there's no other place to buffer/store
it. This asymmetry is akin to CPython's asyncio asymmetry, where reads are
asynchronous, but writes are synchronous (asyncio doesn't expect them to
block, instead expects there to be (unlimited) buffering for any sync write
to completely immediately).
2016-04-09 16:03:38 +03:00
Paul Sokolovsky
397b705647 extmod/modwebsocket: Reset mask between packets. 2016-04-09 12:29:18 +03:00
Paul Sokolovsky
7e9182f3aa extmod/modwebsocket: Make sure to propagate EOF. 2016-04-08 20:26:54 +03:00
pohmelie
b32b0d38fe unix: freedos strip and size names for binaries
After this you need only one path for build (path/to/djgpp/bin). Original patch made by @dhylands
2016-04-08 20:15:37 +03:00
Tom Sparks
20d9bc2d76 extmod/modure: re_exec() renamed to ure_exec() due to collison in 4.3BSD.
Addresses issue #1972.
2016-04-08 20:12:03 +03:00
Paul Sokolovsky
05ba2433f6 extmod/modwebsocket: Properly check number of args to constructor. 2016-04-08 16:05:48 +03:00
Paul Sokolovsky
5e919b7ef8 lib/axtls: Update to the latest upstream master. 2016-04-08 15:19:57 +03:00
Paul Sokolovsky
9c04299da1 docs: esp8266: Enable "machine" module docs.
The docs are still heavily biased towards WiPy, so will need a lot of
exclusions.
2016-04-07 16:44:10 +03:00
Paul Sokolovsky
5e7fa7c80c docs/ubinascii: Document non-standard "sep" argument to hexlify(). 2016-04-07 12:39:00 +03:00
Martin Fischer
8a8e775035 stmhal: Consistently enable USB SOF Irqs for all USB modes (FS and HS).
SOF irqs are now standard for rx/tx USB transfers, so enable them for both
FS and HS modes.  Fixes #1944.
2016-04-07 09:23:33 +01:00
Damien George
04d5e644fc py/objarray: Fix array.append so it doesn't extend if append fails.
Addresses issue #1965.
2016-04-07 09:03:33 +01:00
Damien George
2c915e1ae6 py: Implement basic with support in native emitter. 2016-04-07 08:53:24 +01:00
Damien George
ce8b4e8749 py: Combine continuous block of emit steps into with_cleanup emit call.
Because different emitters need to handle with-cleanup in different ways.
2016-04-07 08:50:38 +01:00
Damien George
2c407bcf20 esp8266: Switch from terse error messages to normal ones.
Adds 2k to the code size.
2016-04-07 00:38:08 +03:00
Paul Sokolovsky
d85439fd19 esp8266/README: Add short troubleshooting section. 2016-04-07 00:21:04 +03:00
Damien George
1a0a323ca8 esp8266: Add initial implementation of machine.UART.
Currently UART(0) and UART(1) are exposed and only uart.write works.
2016-04-06 19:45:52 +03:00
Paul Sokolovsky
4e51a3038c cc3200/mods/modwlan: Include stream.h after recent refactor. 2016-04-06 01:18:39 +03:00
Damien George
96eca22322 esp8266: Make destination for vendor OS debug output soft-configurable.
Use esp.osdebug(None) to disable, or esp.osdebug(uart_id) to send output
to a UART.
2016-04-06 00:12:58 +03:00
Paul Sokolovsky
e6a4d4e23c py: Move stream-related declarations from obj.h to stream.h. 2016-04-05 22:06:52 +03:00
Paul Sokolovsky
e4cb7c6158 docs/esp8266/quickref: Add note about physical vs logical pin numbers. 2016-04-05 16:30:51 +03:00
Paul Sokolovsky
2c8356c482 esp8266/modnetwork: require_if(): Report the actual interface required. 2016-04-05 16:09:03 +03:00
Paul Sokolovsky
f81ea6307c docs/ubinascii: Document a2b_base64(), b2a_base64(). 2016-04-05 14:00:12 +03:00
Paul Sokolovsky
de12502d89 esp8266: Move pyb.unique_id() to machine.unique_id(). 2016-04-05 00:57:49 +03:00
Paul Sokolovsky
81fd5685fc esp8266: Move pyb.hard_reset() to machine.reset(). 2016-04-05 00:20:25 +03:00
Paul Sokolovsky
1b811b946e unix/modsocket: Use mp_const_empty_map instead of creating empty map. 2016-04-04 23:43:16 +03:00
Paul Sokolovsky
069654f2be py/obj.h: Add comment why mp_fun_kw_t takes non-const mp_map_t*.
mp_fun_kw_t takes mp_map_t* (and not const mp_map_t*) to ease passing
this arg to mp_map_lookup(), which may modify its arg, depending on
flags.
2016-04-04 15:37:19 +03:00
pohmelie
cee888255b unix: djgpp errno.h have no ENOTSUP, so define it to Linux value. 2016-04-03 23:23:01 +03:00
Paul Sokolovsky
28d4b94dce docs/machine: Change wording to be a bit more port-neutral. 2016-04-03 20:49:29 +03:00
Paul Sokolovsky
69b702276b docs/os: Change wording to be a bit more port-neutral. 2016-04-03 20:49:25 +03:00
Paul Sokolovsky
e24674d44e docs: esp8266: esp.socket is deprecated, remove from docs. 2016-04-03 20:19:39 +03:00
Paul Sokolovsky
69256ac0b1 esp8266: Bump heap size to 24k. 2016-04-03 19:55:45 +03:00
Paul Sokolovsky
debbaac1bd esp8266: Update flashing instructions in README. 2016-04-03 16:04:18 +03:00
Paul Sokolovsky
919b70b7ec esp8266: Switch back to flashing combined firmware (single file).
With gap between segments minimized, there's not much padding to flash,
so no big speed overhead.
2016-04-03 15:48:46 +03:00
Paul Sokolovsky
8d2bcaf3cd esp8266: Minimize gap between Inst/DataRAM segments and FlashROM segment.
With .rodata being in FlashROM now, gap can be much smaller now. InstRAM
can be max 32K, and with segment headers, that already makes it more than
32K. Then there's some .data still, and the next Flash page boundary is
0x9000. That figure should be more or less future-proof.

TODO: Refactor makeimg to take FlashROM segment offset from file name.
2016-04-03 15:45:14 +03:00
Paul Sokolovsky
9698a60591 esp8266/ets_alt_task: Comment out debug output. 2016-04-03 01:04:01 +03:00
Paul Sokolovsky
fcd6862597 esp8266: Bump iROM size to 512k.
Needed for frozen scripts, and for future growth of binary.
2016-04-03 00:57:27 +03:00
Paul Sokolovsky
ef0c5db2ed esp8266: Move .rodata where it belongs with -mforce-l32 help. 2016-04-03 00:51:51 +03:00
Paul Sokolovsky
254a5646c1 docs: Update copyright notice. 2016-04-03 00:05:23 +03:00
Paul Sokolovsky
333a63efaa esp8266/README: Add link to docs. 2016-04-03 00:01:31 +03:00
Paul Sokolovsky
4f2d59e82f examples/http_client_ssl.py: HTTPS client example. 2016-04-02 23:19:03 +03:00
Paul Sokolovsky
ec5f8db49d examples/http_server.py: Bind to 0.0.0.0, to be accessible from other hosts.
This is helpful when running on deeply embedded targets, but may be
"security risk". Caveat emptor.
2016-04-02 23:14:19 +03:00
Paul Sokolovsky
c07a03a36d examples/http_server.py: Introduce main() function.
Allows to re-run code if it was imported as a module (e.g., on bare-metal
ports).
2016-04-02 20:57:58 +03:00
Paul Sokolovsky
aa3fb7b387 examples/http_server.py: Refactor/simplify for Python 3.5. 2016-04-02 20:53:29 +03:00
Paul Sokolovsky
fd2b71f972 examples/http_client.py: Introduce main() function.
Allows to re-run code if it was imported as a module (e.g., on bare-metal
ports).
2016-04-02 19:13:39 +03:00
Paul Sokolovsky
a5d07c3aba examples/http_client.py: Improve CPython compatibility in stream mode. 2016-04-02 17:28:42 +03:00
Paul Sokolovsky
a5d2af7949 unix/file: "encoding" arg to open() isn't kw-only.
And with "buffering" arg introduced, it's non possible to make it
non-kwonly.
2016-04-02 17:23:51 +03:00
Paul Sokolovsky
e5fa163a4c unix/file: Parse "buffering" argument of open() builtin.
It's ignored (unbuffered, raw I/O is used), but least makes it compatible
with CPython.
2016-04-02 17:23:46 +03:00
Damien George
a0cb4eda9a esp8266: Use VM_HOOK to call ets_loop_iter within the VM.
Starting with a divisor of 10, pystone_lowmem gives a score of 256.
2016-04-02 01:34:32 +03:00
Paul Sokolovsky
cef073877b example/http_client.py: Remove unused code. 2016-04-01 21:10:06 +03:00
Paul Sokolovsky
cf4b72bf13 examples: http_client.py, http_server.py aren't just unix, move to network/. 2016-04-01 20:53:23 +03:00
Stephen Kyle
b475327ffa py/map: Prevent map resize failure from destroying map. 2016-04-01 16:36:00 +03:00
Damien George
6a051a8e0b esp8266/uart: Get ctrl-C working now that event-based REPL is disabled. 2016-04-01 14:53:01 +03:00
Damien George
fb6cc96951 esp8266/uart: Comment out old, unused rx buffering code.
This was originally used for non-event based REPL processing.  Then it
was unused when event-based processing was activated.  But now that event
based is disabled, and non-event based is back, there has been new ring
buffer code to process the chars.
2016-04-01 14:30:47 +03:00
Paul Sokolovsky
fc4c43a72e esp8266: Switch to non event-driven REPL to support paste mode. 2016-04-01 14:22:28 +03:00
Paul Sokolovsky
785cf9a61f esp8266: Support dedicated REPL loop (aka pull-style).
Event-driven loop (push-style) is still supported and default (controlled
by MICROPY_REPL_EVENT_DRIVEN setting, as expected).

Dedicated loop worked even without adding ets_loop_iter(), though that
needs to be revisited later.
2016-04-01 14:02:36 +03:00
Paul Sokolovsky
777232c9a5 esp8266: Disallow recursive calls to REPL.
Before this change, if REPL blocked executing some code, it was possible
to still input new statememts and excuting them, all leading to weird,
and portentially dangerous interaction.

TODO: Current implementation may have issues processing input accumulated
while REPL was blocked.
2016-04-01 12:53:50 +03:00
Pavol Rusnak
3d4a535208 unix: implement -i option (inspect - start REPL after script is finished) 2016-04-01 12:35:45 +03:00
Paul Sokolovsky
5531437941 esp8266: Move PHY mode constants from modesp to modnetwork. 2016-04-01 12:10:11 +03:00
Damien George
4b597a1c1a esp8266: Reset term_obj on reboot.
Also, term_obj can be NULL if socket enables REPL duplication signalling
before os.dupterm is called, so it should be checked.
2016-03-31 19:56:52 +03:00
Paul Sokolovsky
98af891610 esp8266: Implement input part of dupterm handling.
The idea is following: underlying interrupt-driven or push-style data source
signals that more data is available for dupterm processing via call to
mp_hal_signal_dupterm_input(). This triggers a task which pumps data between
actual dupterm object (which may perform additional processing on data from
low-level data source) and input ring buffer.
2016-03-31 19:49:55 +03:00
Paul Sokolovsky
61fa7c8152 esp8266: Switch back to accumulating input data via ring buffer.
But now it's generic ring buffer implemented via ringbuf.h, and is intended
for any type of input, including dupterm's, not just UART. The general
process work like this: an interrupt-driven input source puts data into
input_buf, and then signals new data available via call to
mp_hal_signal_input().
2016-03-30 18:50:38 +03:00
Paul Sokolovsky
2e75a17bab esp8266: Fix issue when current repl line was garbage-collected.
Reference it from root pointers section.
2016-03-30 18:13:03 +03:00
Paul Sokolovsky
b1dfdaf6cb py/ringbuf.h: Add reusable ring buffer class.
Features inline get/put operations for the highest performance. Locking
is not part of implementation, operation should be wrapped with locking
externally as needed.
2016-03-30 14:48:31 +03:00
Paul Sokolovsky
f50d9477c1 docs: network: esp8266: .scan() is now synchronous and returns result list. 2016-03-30 11:56:20 +03:00
Paul Sokolovsky
d7019d0628 docs: network: esp8266: status is WLAN object method. 2016-03-30 11:53:45 +03:00
Damien George
9475cc59e6 esp8266: Support synchronous wifi scanning.
That is: aps = if0.scan()

TODO: make sure that returned list has tuple with values in "standard"
order (whatever that standard is).
2016-03-30 11:35:03 +03:00
Damien George
2599672384 py/parsenum: Use pow function to apply exponent to decimal number.
Pow is already a dependency when compiling with floats, so may as well
use it here to reduce code size and speed up the conversion for most
cases.
2016-03-29 22:12:07 +01:00
Damien George
e1e7657277 py/formatfloat: Fix further cases of buffer overflow in formatting.
Includes extensive test cases to catch hopefully all cases where
buffer might overflow.
2016-03-29 22:07:15 +01:00
Damien George
03b8bb7ec9 py/formatfloat: Fix case of float format where leading digit was "10".
When taking the logarithm of the float to determine the exponent, there
are some edge cases that finish the log loop too large.  Eg for an
input value of 1e32-epsilon, this is actually less than 1e32 from the
log-loop table and finishes as 10.0e31 when it should be 1.0e32.  It
is thus rendered as :e32 (: comes after 9 in ascii).

There was the same problem with numbers less than 1.
2016-03-29 22:03:13 +01:00
Paul Sokolovsky
d88250c06e esp8266: Reduce heap size for now to avoid random segfaults on WiFi connect. 2016-03-29 21:14:41 +03:00
Paul Sokolovsky
c4506ed869 esp8266: Let esp8266 "os" messages go to standard (REPL) UART.
That's definitely helpful for debugging.
2016-03-29 21:10:10 +03:00
Paul Sokolovsky
402a743821 esp8266/esp_mphal: Add support for debug UART-only output.
Helpful when debugging dupterm support (because otherwise all output is
spooled to dupterm too).

To use:

mp_printf(&mp_debug_print, "...");
2016-03-29 11:48:43 +03:00
Paul Sokolovsky
8fc5e56a6a esp8266: Enable uos.dupterm() method. 2016-03-29 11:41:23 +03:00
Paul Sokolovsky
c961889e34 esp8266: Add basic support for duplicating REPL output. 2016-03-29 11:13:32 +03:00
Damien George
6ca17c1922 esp8266: Implement os.urandom function.
Uses what is suspected to be a hardware random number generator.
2016-03-29 10:29:57 +03:00
Paul Sokolovsky
b4070ee8a4 esp8266: Allow to build without FatFs support again. 2016-03-28 21:35:41 +03:00
Paul Sokolovsky
2f02302e22 esp8266: Support importing modules from filesystem. 2016-03-28 18:39:34 +03:00
danicampora
193795398d docs: Correct pin interrupt example code for the WiPy. 2016-03-28 13:12:58 +02:00
Damien George
71d40f132d esp8266: Zero out fs_user_mount state on (soft) reset.
Otherwise device stays mounted on soft reset and leads to corruption
(since block device object is now gone).
2016-03-28 13:28:41 +03:00
Paul Sokolovsky
9edd736ee6 esp8266/moduos: Add os.remove(), proxying to VFS object. 2016-03-28 12:50:07 +03:00
Paul Sokolovsky
e8e116e7fc esp8266/moduos: Factor out VFS method proxy helper. 2016-03-28 12:44:36 +03:00
Paul Sokolovsky
8b08a0d9ed esp8266/moduos: Add listdir() proxy for MP_STATE_PORT(fs_user_mount)[0].
I.e. os.listdir(...) will redirect to
MP_STATE_PORT(fs_user_mount)[0].listdir(...).
2016-03-28 12:29:47 +03:00
Damien George
61230e007d esp8266/moduos: Use mp_rom_map_elem_t for static const dictionary. 2016-03-28 12:08:36 +03:00
Paul Sokolovsky
b01a373adb esp8266: deploy: Use --flash_size=8m option to esptool.py.
Most esp8266 modules have at least 1MB (8Mbit) of flash. If not set, vendor
functions allow to access only first 512K.
2016-03-28 11:28:16 +03:00
Paul Sokolovsky
cd6194aefc esp8266/esp8266.ld: Put FatFs to FlashROM. 2016-03-27 17:15:25 +03:00
Paul Sokolovsky
374654f2b8 esp8266: Enable FatFs support. 2016-03-27 17:13:47 +03:00
Paul Sokolovsky
fe9bc0c573 esp8266/README: Update for the current status of the port. 2016-03-27 16:10:58 +03:00
Paul Sokolovsky
bbc65d4eda esp8266/modesp: flash_read(): Accept buffer to read to as a second argument. 2016-03-27 15:34:35 +03:00
Paul Sokolovsky
fd86bf5917 esp8266/modesp: flash_write(): Writes in multiples of 4 bytes. 2016-03-27 15:32:58 +03:00
Paul Sokolovsky
53302f1616 esp8266: Set up UART handling task soon into init process.
Otherwise, events may be posted to non-initialized task, which leads to
segfaults.
2016-03-27 14:33:17 +03:00
Paul Sokolovsky
651a188299 extmod/vfs_fat_diskio: Actually support sectors != 512 with Python blockdevs. 2016-03-27 14:21:06 +03:00
Paul Sokolovsky
13394a632d unix/unix_mphal: Hack to make uos.dupterm() actually work.
See https://github.com/micropython/micropython/issues/1736 for the
list of complications. This workaround instead of duplicating REPL
to another stream, switches to it, because read(STDIN) we use otherwise
is blocking call, so it and custom REPL stream can't be used together.
2016-03-27 14:02:03 +03:00
Paul Sokolovsky
53ad5edc01 py/stream: Fix stupid thinko with variable naming/shadowing. 2016-03-27 12:58:33 +03:00
Paul Sokolovsky
87c783b454 docs/esp8266: esp.mac() replaced with network.WLAN.mac(). 2016-03-27 06:59:39 +03:00
Paul Sokolovsky
679fe0abae docs/esp8266: esp.wifi_mode() replaced with network.WLAN.active(). 2016-03-27 06:59:00 +03:00
Paul Sokolovsky
eda8746324 docs/esp8266: phy_mode() moved to network module. 2016-03-27 06:58:06 +03:00
Paul Sokolovsky
935e021250 esp8266: Put modpybi2c.o to FlashROM. 2016-03-26 10:59:25 +02:00
Damien George
c33a76059f esp8266/tests: Add neopixel.py test. 2016-03-26 10:55:29 +02:00
Damien George
3962766be0 esp8266: Add esp.neopixel_write function to bit-bang WS2812 data. 2016-03-26 10:55:21 +02:00
Damien George
b62beadae0 esp8266: Link ADC class into machine module. 2016-03-26 00:41:37 +02:00
Paul Sokolovsky
f71c0699a5 esp8266: Put utils.o to FlashROM. 2016-03-26 00:39:51 +02:00
Paul Sokolovsky
9c7e3353e5 esp8266: Put lexerstr32.o into FlashROM. 2016-03-26 00:39:02 +02:00
Paul Sokolovsky
ba640bde55 esp8266/esppwm.c: Fix IRQ handler prototype. 2016-03-26 00:34:28 +02:00
Damien George
632d8efa05 esp8266: Add PWM support.
PWM implementation uses a timer and interrupts (FRC1), taken from
Espressif's/NodeMCU's implementation and adapted for our use.

8 channels are supported, on pins 0, 2, 4, 5, 12, 13, 14, 15.

Usage:

    import machine
    pwm0 = machine.PWM(machine.Pin(0))
    pwm0.freq(1000)
    pwm0.duty(500)

Frequency is shared (ie the same) for all channels.  Frequency is
between 1 and 1000.  Duty is between 0 and 1023.
2016-03-26 00:32:37 +02:00
Damien George
82b95f625e esp8266: Implement software SPI class.
Supports speeds up to 500k baud, polarity=0/1, phase=0/1, and using any
pins.  Only supports MSB output at the moment.
2016-03-25 23:28:13 +02:00
Paul Sokolovsky
91031a75a1 extmod/modlwip: lwip_socket_setsockopt: Handle option value properly. 2016-03-25 20:53:52 +02:00
Paul Sokolovsky
4332d72fd8 extmod/modlwip: Add lwip->POSIX error map for lwIP 1.4.0.
Between 1.4.0 and 1.4.1, lwIP errors were renumbered.
2016-03-25 20:32:01 +02:00
Paul Sokolovsky
de0c84ebf1 extmod/modlwip: lwip_tcp_send: Handle properly send buffer full condition.
Per POSIX http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html :
"If space is not available at the sending socket to hold the message to be
transmitted, and the socket file descriptor does not have O_NONBLOCK set,
send() shall block until space is available. If space is not available at the
sending socket to hold the message to be transmitted, and the socket file
descriptor does have O_NONBLOCK set, send() shall fail [with EAGAIN]."
2016-03-25 18:38:13 +02:00
Paul Sokolovsky
5e75f335e6 extmod/modlwip: Implement setsocketopt(SO_REUSEADDR). 2016-03-25 17:44:24 +02:00
Paul Sokolovsky
0cb10b5220 docs/esp8266/quickref: Add note about GPIO16. 2016-03-25 16:48:15 +02:00
Paul Sokolovsky
159f1aaca8 docs/esp8266/quickref: Note that timers supported are virtual ones. 2016-03-25 16:44:13 +02:00
Paul Sokolovsky
e589cddcd4 docs/esp: Remove getaddrinfo(), now in socket module as expected. 2016-03-25 16:39:18 +02:00
Paul Sokolovsky
6e6488530e docs: More standard modules for esp8266. 2016-03-25 16:33:05 +02:00
Paul Sokolovsky
4b5606bc09 docs/network: esp8266: Update docs on WLAN constructor. 2016-03-25 16:30:06 +02:00
Paul Sokolovsky
ee6fcc6f91 docs: Add standard modules list for esp8266. 2016-03-25 15:17:55 +02:00
Paul Sokolovsky
96a644076d docs/topindex.html: Refer to "pyb" module only for pyboard. 2016-03-25 15:12:26 +02:00
Paul Sokolovsky
8f1854ad2d extmod/modlwip: Add SOL_SOCKET and SO_REUSEADDR constants for setsockopt(). 2016-03-25 15:06:12 +02:00
Paul Sokolovsky
ac671546d1 esp8266/README: Remove outdated reference to initial port heap size. 2016-03-25 15:02:23 +02:00
Paul Sokolovsky
88f60de914 tests: Add test for io.BufferedWriter. 2016-03-25 15:01:19 +02:00
Paul Sokolovsky
2c81b9be28 py/modio: io.BufferedWriter: Describe flushing policy. 2016-03-25 14:59:30 +02:00
Paul Sokolovsky
063e6e7d0a py/modio: Implement io.BufferedWriter.flush(). 2016-03-25 14:33:38 +02:00
Paul Sokolovsky
5d93dfbc2c py/modio: Initial implementation of io.BufferedWriter class.
Just .write() method implemented currently.
2016-03-25 01:10:49 +02:00
Paul Sokolovsky
3dbd2ee926 extmod/modwebsocket: Implement read support. 2016-03-25 00:51:51 +02:00
Paul Sokolovsky
4a02a8f74d py/stream: Fix object vs ptr usecase in mp_stream_writeall(). 2016-03-24 19:43:08 +02:00
Paul Sokolovsky
24342dd65e extmod/modwebsocket: Start module for WebSocket helper functions.
Currently, only write support is implemented (of limited buffer size).
2016-03-24 19:16:00 +02:00
Paul Sokolovsky
d4c8e626f2 py/stream: Add mp_stream_writeall() helper function.
Spools entire output buffer to a blocking stream (chunk by chunk if
needed).
2016-03-24 19:09:00 +02:00
Damien George
a5d48b1162 esp8266: Add tests/onewire.py as a driver and test code for ds18b20 dev. 2016-03-24 17:35:26 +02:00
Damien George
78d0dde562 esp8266: Add onewire helper functions as C module.
Includes functions to read and write bits and bytes.
2016-03-24 17:33:42 +02:00
Damien George
0cdbd356fd esp8266: Implement bit-bang I2C read, and add i2c.readfrom method.
I2C reading tested with TSL2561 luminosity sensor.
2016-03-24 11:46:05 +02:00
Damien George
5b9f361824 esp8266: Clean up bit-bang I2C implementation.
Changed from using set_sda_scl function to independent set_sda and
set_scl functions.
2016-03-24 11:37:52 +02:00
Paul Sokolovsky
667d64b430 esp8266/modpybi2c: Add missing include. 2016-03-24 11:21:36 +02:00
Damien George
dd32f02cc3 esp8266: Add basic I2C driver, with init and writeto methods.
Tested and working with SSD1306 I2C display.
2016-03-24 11:17:17 +02:00
Damien George
7059c8c23c esp8266: Expose pin object as a public structure for use as C pin API.
This is an initial attempt at making a simple C pin API for writing
things like I2C drivers in C.
2016-03-24 11:07:41 +02:00
Paul Sokolovsky
a1d072df81 esp8266: Enable auto-indent in REPL. 2016-03-23 16:30:29 +02:00
Paul Sokolovsky
df1f6783f2 esp8266: Add "socket" and "usocket" aliases for lwip module. 2016-03-23 16:25:55 +02:00
Paul Sokolovsky
494aea3e86 esp8266: Enable non-blocking stream support. 2016-03-23 16:15:49 +02:00
Damien George
5bc9398d9d esp8266: Enable more extmod's: uheapq, ure, uzlib. 2016-03-23 14:19:14 +02:00
Damien George
8000d51b68 esp8266: Add module weak link from json to ujson. 2016-03-23 14:16:46 +02:00
Paul Sokolovsky
1a0adf49df esp8266: Enable urandom module. 2016-03-23 13:33:17 +02:00
Damien George
e673714cfe esp8266: Make mp_hal_delay_us work with new event framework. 2016-03-23 13:01:21 +02:00
Paul Sokolovsky
58e2ad42ae esp8266: Update README with the latest features. 2016-03-23 12:08:15 +02:00
Damien George
b894551772 extmod/uctypes: Change param type from void* to byte*. 2016-03-19 22:13:17 +00:00
Damien George
da161fd9f0 extmod/uctypes: Finish support for FLOAT32 and FLOAT64 types. 2016-03-19 21:59:42 +00:00
Damien George
12154b1774 extmod/uctypes: Use mp_binary_get_val helper when extracting value.
It handles more cases than mp_binary_get_int.
2016-03-19 21:41:01 +00:00
Damien George
8d4d6731f5 py/parse: When looking up consts, check they exist before checking type. 2016-03-19 21:36:32 +00:00
Peter Hinch
2b302dad51 docs: Update pyb.UART.any() to mention that it returns character count. 2016-03-17 20:19:36 +00:00
Peter Hinch
6d5a549067 docs: Mention that pyb.SPI constructor accepts "X" and "Y" arguments. 2016-03-17 20:19:08 +00:00
Peter Hinch
b8133c4c0f docs: Update pyb.I2C constructor to reflect changes in Pyboard Lite. 2016-03-17 20:18:36 +00:00
Peter Hinch
4a6cac4643 docs: Update asm tutorial, maximum number of allowed args is now 4. 2016-03-17 20:17:40 +00:00
Damien George
99146ea444 tests/io: Remove "testfile" at end of open_plus test. 2016-03-17 20:09:33 +00:00
Damien George
556a1df6fd esp8266/ets_alt_task: Make FIRST_PRIO=0 to cover all task priorities.
FIRST_PRIO=2 works but using 0 is hopefully safer, and can anyway be
optimised in the future.
2016-03-17 16:28:06 +00:00
Paul Sokolovsky
9d7b871f58 esp8266: Store frozen modules in FlashROM.
Requires special lexer to access their contents.
2016-03-17 23:06:47 +08:00
Damien George
2466cb67f8 docs/esp8266: Update quick reference: i2c.readfrom and neopixel example. 2016-03-16 13:37:39 +00:00
Damien George
3acaa28b52 py: Don't allocate an extra parse node for power exponent.
Previous to this patch, the "**b" in "a**b" had its own parse node with
just one item (the "b").  Now, the "b" is just the last element of the
power parse-node.  This saves (a tiny bit of) RAM when compiling.
2016-03-16 13:04:51 +00:00
Paul Sokolovsky
52e062ef33 py/frozenmod: Allow port to override lexer to use for frozen modules. 2016-03-16 17:42:37 +07:00
Damien George
664f03f466 tests: Add a test for argument passing to inline-asm functions. 2016-03-16 08:24:07 +00:00
Damien George
9a58316de2 py/objfun: Allow inline-asm functions to be called with 4 arguments. 2016-03-16 08:22:26 +00:00
Damien George
be989be861 qemu-arm: Enable builtin override feature, and enable more tests.
Hopefully these tests run reliably on Travis.
2016-03-15 13:45:32 +00:00
Damien George
1ded19d4b3 qemu-arm: Reinitialise uPy heap and runtime at start of each test.
Previous to this patch, all qemu-arm tests were running in the same
session, and global variables could be left over from the previous test.
This patch makes it so that the heap and runtime are reinitialised at
the start of each test.
2016-03-15 13:42:36 +00:00
Damien George
157056ecdf tests: Add new subdir "stress/" specifically for stress tests. 2016-03-15 13:20:18 +00:00
Damien George
ab69ed7dac tests: Split large tests into smaller files, to run with a small heap.
All tests in basics/ directory can now run and pass using 64-bit unix
port with only a 16k heap (./run-tests --heapsize 16k).  Tests in this
directory should remain small so they can be used for ports with a
small heap.
2016-03-15 13:07:41 +00:00
Damien George
9996adc37d tests/run-tests: Add cmd line option "--heapsize".
This allows you to specify the heapsize that unix will use when running
the test suite, eg: ./run-tests --heapsize 16k
2016-03-15 13:04:43 +00:00
Damien George
cea6cf8a5e py/formatfloat: Fix buffer overflow when formatting tiny numbers. 2016-03-15 12:21:56 +00:00
Damien George
0d1f8868b6 py: For mp_buffer_info_t, change len type from mp_uint_t to size_t. 2016-03-15 12:20:57 +00:00
Damien George
77f85db41e py/objarray: Fix array slice assignment when array is reallocated.
Addresses issue #1898.
2016-03-14 23:12:54 +00:00
Damien George
06b398489e py/parsenum: Fix compiler warnings for no decl and signed comparison. 2016-03-14 22:52:52 +00:00
Damien George
0be6359f39 py: When printf'ing an object as a pointer, pass the concrete pointer. 2016-03-14 22:41:14 +00:00
Damien George
2a1cca20b1 py: Fix passing of some wide int types to printf varg format list.
Passing an mp_uint_t to a %d printf format is incorrect for builds where
mp_uint_t is larger than word size (eg a nanboxing build).  This patch
adds some simple casting to int in these cases.
2016-03-14 22:40:39 +00:00
Damien George
e7cd1699df py/argcheck: Use size_t instead of mp_uint_t to count number of args. 2016-03-14 22:35:48 +00:00
Damien George
dddb98db8b py/parsenum: Use size_t to count bytes, and int for type of base arg.
size_t is the proper type to count number of bytes in a string.  The base
argument does not need to be a full mp_uint_t, int is enough.
2016-03-14 22:34:03 +00:00
Dave Hylands
99fc0d120a stmhal: NUCELO_F401RE cleanup
Added definitions for SPI1, SPI2, and SPI3
Removed USB stuff (that could be removed)
Updated BOARD name defintion
2016-03-13 12:36:39 +00:00
Dave Hylands
00f921ce02 stmhal: Rename STM32F401NUCLEO to NUCLEO_F401RE
This makes the board match the name printed on the board (and
agree with the documentation)
2016-03-13 12:36:39 +00:00
Dave Hylands
031fadd10e stmhal: Add board definition files for NUCLEO_F411RE 2016-03-12 16:16:15 -08:00
Paul Sokolovsky
e5c39a3a9e esp8266: Switch to lwIP built from source.
Using https://github.com/pfalcon/esp-open-lwip project.
2016-03-12 11:45:53 +07:00
Paul Sokolovsky
0779409d0d extmod/modlwip: lwip_tcp_receive: Properly map lwIP error to POSIX errno. 2016-03-12 11:42:15 +07:00
Paul Sokolovsky
ba8f7d5171 extmod/modlwip: Add socket.setblocking() method. 2016-03-12 10:52:50 +07:00
Paul Sokolovsky
09ed5bcbbb extmod/modlwip: Rework getaddrinfo() data passing.
The code is based on Damien George's implementation for esp8266 port,
avoids use of global variables and associated re-entrancy issues, and
fixes returning stale data in some cases.
2016-03-12 10:50:51 +07:00
Peter Hinch
21b74604f9 docs: Add Python speed optimisation guide, including minimal viper ref. 2016-03-11 16:33:36 +00:00
Peter Hinch
85d3b6165a docs: Update details on using ADCAll object for vref/vbat channels. 2016-03-11 16:33:09 +00:00
Peter Hinch
70f32f0f73 docs: Update asm_thumb2_hints_tips re return type of asm funcs. 2016-03-11 16:32:42 +00:00
Christopher Arndt
3d0e3a3d3e esp8266: Mention git submodule in build instructions for esp8266 port. 2016-03-11 10:07:02 +00:00
Damien George
932f07ccf5 esp8266: Rejig Makefile so extmod/modlwip.o is placed under build/. 2016-03-11 12:00:01 +07:00
Paul Sokolovsky
4c2cb7e384 esp8266: Define MICROPY_EVENT_POLL_HOOK for the port. 2016-03-11 10:41:10 +07:00
Paul Sokolovsky
6e5c31c947 esp8266: Be sure to build ets_alt_task. 2016-03-11 09:43:39 +07:00
Paul Sokolovsky
a099bfe89c esp8266/esp_mphal: Add higher-level event polling function.
ets_event_poll() polls both system events and uPy pending exception.
2016-03-11 09:42:03 +07:00
Paul Sokolovsky
e5b047369b extmod/modlwip: Use MICROPY_EVENT_POLL_HOOK for event polling if defined.
Instead of just delaying 100ms if event isn't yet ready.

So far applies only to default, "infinite" socket timeout.
2016-03-11 09:32:07 +07:00
Paul Sokolovsky
54fc247f9b esp8266/ets_alt_task: Update for vendor SDK 1.5.0.
SDK 1.5.0 has a task with priority 3: ets_task(401001f4, 3, 3fff9808, 4).
Recognizing SDK version requires the latets esp-open-sdk build.
2016-03-11 09:17:57 +07:00
Paul Sokolovsky
97375f4576 esp8266/ets_alt_task: Be sure to "pop" event before calling its handler.
Otherwise, if handler calls recursive event loop, there's infinite
recursion (because the loop calls the same handler on same event again).
2016-03-11 09:16:34 +07:00
Damien George
7261f17b9e esp8266: Feed WDT in ets_loop_iter(). 2016-03-11 09:15:06 +07:00
Paul Sokolovsky
97c2628900 esp8266: Add alternative event loop implementation.
This implementation provides the same interface and uses the same
datastructures as used by BootROM, i.e. is a drop-in replacement for it.
But it offers one advantage: it allows to run single iteration of
event-pumping loop.

Original BootROM function are renamed, prefixed with underscore. There's
a switch which allows to use forward calls to them, for compatibility
testing.

The implementation also includes workarounds for hardware timer handler,
and these workarounds may be SDK version specific.
2016-03-11 09:13:31 +07:00
Damien George
9ae51257bd py: Use MP_SMALL_INT_POSITIVE_MASK to check if uint fits in a small int.
Using the original WORD_MSBIT_HIGH-logic resulted in errors when the
object model is not REPR_A or REPR_C.
2016-03-10 21:52:56 +00:00
Paul Sokolovsky
5239a8a82b esp8266/modnetwork: Add symbolic names for network interfaces: STA_IF & AP_IF.
These are expected to be passed to network.WLAN() to instantiate network
interface objects.
2016-03-10 10:44:15 +07:00
Paul Sokolovsky
a49c16069c esp8266/modnetwork: Introduce interface .config() method.
Allows to set (in case keyword args are given) or query (in case a single
"symbolic keyword" (a string, value is the same as keyword)) arbitrary
interface paramters (i.e. extensible and adaptable to various hardware).

Example usage:

ap_if = network.WLAN(1)
ap_if.config(essid="MicroPython on Air")
print(ap_if.config("essid"))
2016-03-10 10:41:55 +07:00
Paul Sokolovsky
d5a12a6608 esp8266/modnetwork: Move config defines to the top. 2016-03-10 10:39:52 +07:00
Paul Sokolovsky
1c43a0fbf8 esp8266/modnetwork: Add per-interface .active() method.
Allows to up/down interface when called with a boolean, or query current
state if called without args. This per-interface method is intended to
supersede adhoc network.wifi_mode() function.
2016-03-10 09:31:23 +07:00
Paul Sokolovsky
7378c50b2f esp8266: Move wifi_mode() and phy_mode() to network module. 2016-03-10 09:29:21 +07:00
Paul Sokolovsky
9e8396accb esp8266/modnetwork: Allow to configure STA and AP interfaces separately.
On ESP8266, there're 2 different interfaces. Pretending it's not the case
desn't make sense. So, network.WLAN() now takes interface id, and returns
interface object. Individual operations are then methods of interface
object. Some operations require i/f of specific type (e.g. .connect()
makes sense only for STA), other are defined for any (e.g. .ifconfig(),
.mac()).
2016-03-10 09:24:54 +07:00
Christopher Arndt
9b5e05a7c7 stmhal: Add makefile target and configuration to deploy via OpenOCD. 2016-03-09 23:00:17 +00:00
Ryan Shaw
ad725a6661 stmhal: Add support for generic STM32F439 board (non DISCO). 2016-03-09 22:46:41 +00:00
Damien George
853fb08d0d mpy-cross: Remove setting of MICROPY_FORCE_32BIT=1 from Makefile.
Building in 32-bit mode was only to reduce binary size on 64-bit machines
and is otherwise not needed.  Having it forced to 32-bit meant an
unnecessary dependency on 32-bit libraries that is now removed.
2016-03-09 15:56:11 +00:00
Christopher Arndt
07554486ee stmhal: Add makefile target to deploy stmhal build via ST-LINK. 2016-03-09 13:26:23 +00:00
Damien George
6b80ebe32e docs/esp8266: Fix indent errors, typos, and add info about REPL UART. 2016-03-09 13:01:32 +00:00
Damien George
42ef5a1567 docs: Allow list of versions to be specified by environment variable. 2016-03-09 12:43:22 +00:00
Damien George
5b74bba3a3 docs: Add versions.html template and support code for a version sidebar. 2016-03-09 12:15:47 +00:00
Damien George
4b6077b3fe docs/esp8266: Minor tweaks to quickref, Timer and I2C classes. 2016-03-09 11:02:38 +00:00
Paul Sokolovsky
43d497592f extmod/modlwip: Factor out "socket connected" check to a function.
Same code repeated for each send*() and recv*() function.
2016-03-09 12:43:09 +07:00
Paul Sokolovsky
fda874e406 extmod/modlwip: Support non-blocking recv(). 2016-03-09 12:39:33 +07:00
Paul Sokolovsky
7379be3673 extmod/modlwip: Add .write() stream method. 2016-03-09 12:35:43 +07:00
Damien George
4f64f6bfd3 extmod/modlwip: Still process remaining incoming data of a closed socket.
It can happen that a socket gets closed while the pbuf is not completely
drained by the application.  It can also happen that a new pbuf comes in
via the recv callback, and then a "peer closed" event comes via the same
callback (pbuf=NULL) before the previous event has been handled.  In both
cases the socket is closed but there is remaining data.  This patch makes
sure such data is passed to the application.
2016-03-09 12:31:25 +07:00
Damien George
6d2e9e70b3 extmod/modlwip: Check for state change during recv busy-wait loop.
For example, the peer may close the connection while recv is waiting for
incoming data.
2016-03-09 12:29:40 +07:00
Paul Sokolovsky
6185dc5f3d extmod/modlwip: Add stream .read() and .readline() methods. 2016-03-09 09:20:22 +07:00
Paul Sokolovsky
f1919b7c98 extmod/modlwip: Add dummy .makefile() method. 2016-03-09 09:14:45 +07:00
Paul Sokolovsky
c7fb87caff extmod/modlwip: Add stream protocol read method. 2016-03-09 09:12:32 +07:00
Damien George
f7be80398e esp8266: Move pyb.freq to machine.freq. 2016-03-09 09:03:59 +07:00
Damien George
809fbeefb7 docs: Add esp8266 quick reference page, with basic info. 2016-03-08 23:06:15 +00:00
Damien George
dcdf8f2d14 py/objboundmeth: Allocate arg state on stack if heap alloc fails.
If the heap is locked, or memory allocation fails, then calling a bound
method will still succeed by allocating the argument state on the stack.

The new code also allocates less stack than before if less than 4
arguments are passed.  It's also a tiny bit smaller in code size.

This was done as part of the ESA project.
2016-03-08 15:36:53 +00:00
Damien George
bb293e6bcf stmhal: Add stmhal-specific README.md with extra details for this port. 2016-03-08 12:00:38 +00:00
Damien George
2c72ae5c29 stmhal: Switch from dfu-util to tools/pydfu.py for deflt deploy method.
tools/pydfu.py is now the recommended way of deploying a DFU file.  Old
behaviour of dfu-util can be obtained by passing USE_PYDFU=0 when invoking
make.

The main README.md file has been updated to reflect this change.
2016-03-08 11:58:39 +00:00
Damien George
f0e2d13fd2 tests/run-tests: Simplify handling of newline in output from tests.
Now, all output has newlines converted to \n, regardless of port or
platform.
2016-03-08 10:20:38 +00:00
Paul Sokolovsky
ed593780bf extmod/modlwip: Implement dummy setsockopt(). 2016-03-08 14:24:49 +07:00
Paul Sokolovsky
a0cd118b14 esp8266/main: Module to run on boot is "boot", not "main". 2016-03-08 12:37:24 +07:00
Paul Sokolovsky
f8d42da104 extmod/modlwip: Add .print() method. 2016-03-08 11:37:15 +07:00
Damien George
3fbbbecec9 esp8266: Put more code in iROM section.
Also explicitly name the py/*.o files in the linker file, to enable easy
testing of putting certain ones in iRAM.
2016-03-08 11:31:39 +07:00
Paul Sokolovsky
04a9ac7f38 extmod/modlwip: Update make_new() arguments for recent refactor. 2016-03-08 10:31:21 +07:00
Paul Sokolovsky
d684f872bd esp8266/Makefile: Add define for ESP8266 lwIP. 2016-03-08 10:29:05 +07:00
Damien George
05dda0ee9e esp8266: Enable modlwip. 2016-03-08 10:21:50 +07:00
Paul Sokolovsky
88b0490945 esp8266: Don't gc-collect BSS.
None of the other ports do, since introduction of mp_state_ctx_t. In
the case of current esp8266 port, heap is inside BSS, so scanning it
picked up a lot of dead pointers.
2016-03-08 10:16:06 +07:00
Markus Fix
4f0080346b py/emitglue: Get persistent bytecode working on Linux ARM platform. 2016-03-07 15:15:23 +00:00
Dave Hylands
484a471f9b stmhal: Fix some typos in stm32f411 files, regarding FS layout and CSV. 2016-03-07 12:42:30 +00:00
Dave Hylands
367c084c4b stmhal: Fix typo in stm32f401.ld file, regarding flash size. 2016-03-07 12:38:57 +00:00
Dave Hylands
0edfb7a115 stmhal: Make spi use mp_hal_gpio_set_af 2016-03-07 12:24:53 +00:00
Damien George
d964873e56 tests/run-tests: Fix logic when selecting test-dirs for a given target. 2016-03-07 12:00:16 +00:00
Pavol Rusnak
ce3beb1672 stmhal: Unify comments in stm32f4xx_hal_conf.h across all boards.
To make it easier to spot differences.
2016-03-07 11:28:36 +00:00
Paul Sokolovsky
b86c20676e tests/recursive_iternext.py: Make low-heap friendly. 2016-03-07 15:30:02 +07:00
Paul Sokolovsky
db984b73f3 esp8266: Enable stack overflow checking. 2016-03-07 14:15:00 +07:00
Paul Sokolovsky
1d5d4f49d9 py/stackctrl: Add mp_stack_set_top() to explicitly set stack top value.
Useful for embedded targets with fixed stack layout.
2016-03-07 14:12:24 +07:00
Paul Sokolovsky
419bb26ddc tests/print_exception: Use exception which prints the same regardless of config.
NameError may either include offending name or not. Unfortunately, this
change makes test float-dependent. And using integer division leads to
different error message than CPython.
2016-03-07 14:10:06 +07:00
Paul Sokolovsky
d973c1bc12 test/string_format_fp30: Variant of string_format for 30-bit stuffed float. 2016-03-06 06:10:40 +02:00
Paul Sokolovsky
50e0a7b9d4 test/float2int_fp30: Variant of float2int for 30-bit stuffed float. 2016-03-06 06:08:38 +02:00
Damien George
fbb3c190f9 tests: Remove commented out tests so test script is not too big. 2016-03-06 06:00:28 +02:00
Damien George
14848ffa12 tests: Reduce large object allocations so tests can run with small heap. 2016-03-06 05:59:46 +02:00
Damien George
52d7685d9a esp8266: Allow Makefile's BAUD variable to be overridden. 2016-03-06 05:57:36 +02:00
Paul Sokolovsky
d9d4a72679 esp8266/uart: Add uart_flush() function. 2016-03-05 22:13:26 +02:00
Paul Sokolovsky
d3a4d39687 esp8266: Support raising KeyboardInterrupt on Ctrl+C. 2016-03-05 22:01:27 +02:00
Damien George
077448328a esp8266/etshal.h: More prototypes of ESP8266 SDK/BootROM functions. 2016-03-05 21:56:32 +02:00
Paul Sokolovsky
26f0616e8f esp8266/modmachine: Add Pin class from modpyb. 2016-03-05 21:43:11 +02:00
Paul Sokolovsky
eb247eacd8 esp8266/modpybpin: Add support for GPIO16.
GPIO16 is actually special-function I/O, though some boards have LED there.
2016-03-05 21:37:55 +02:00
Damien George
342d903a13 esp8266: Expose simple pin API at C level. 2016-03-05 21:36:32 +02:00
Damien George
cdad2b6f4d esp8266: Implement Pin.__call__() and Pin.OPEN_DRAIN mode.
OPEN_DRAIN is of course synthesised.  All pin modes are tested and
working.
2016-03-05 21:35:32 +02:00
Paul Sokolovsky
8ab16b6af0 esp8266: Add custom _assert() function.
Enabling standard assert() (by removing -DNDEBUG) produces non-bootable
binary (because all messages go to .rodata which silently overflows).
So, for once-off debugging, have a custom _assert().
2016-03-05 11:30:15 +02:00
Paul Sokolovsky
c70637bc00 esp8266/modmachine: Timer: Add ONE_SHOT and PERIODIC symbolic constants. 2016-03-04 22:26:59 +02:00
Paul Sokolovsky
98b727c931 esp8266/modmachine: Use etshal.h. 2016-03-04 19:41:15 +02:00
Paul Sokolovsky
f22a4f8e0a esp8266/etshal.h: Add timer functions prototypes. 2016-03-04 19:39:24 +02:00
Paul Sokolovsky
f39bcb304b esp8266/modmachine: Changing params of a timer requires disarming it first. 2016-03-04 18:41:37 +02:00
Paul Sokolovsky
7193086c03 esp8266/modmachine: Basic implementation of Timer for OS virtual timers. 2016-03-04 18:40:35 +02:00
Paul Sokolovsky
4284b3811f esp8266: Enable modmachine. 2016-03-04 17:37:13 +02:00
Paul Sokolovsky
5d7c408ba8 esp8266: Add modmachine with mem* arrays. 2016-03-04 17:34:25 +02:00
Paul Sokolovsky
6abafca1aa esp8266/modutime: Support float argument to time.sleep(). 2016-03-04 16:52:30 +02:00
Paul Sokolovsky
a4c8ef9d16 esp8266: Reset "virtual RTC" on power on.
Initialize RTC period coefficients, etc. if RTC RAM doesn't contain valid
values. time.time() then will return number of seconds since power-on, unless
set to different timebase.

This reuses MEM_MAGIC for the purpose beyond its initial purpose (but the whole
modpybrtc.c need to be eventually reworked completely anyway).
2016-03-04 16:49:01 +02:00
Damien George
57884996b9 esp8266: Add time.{sleep_ms,sleep_us,ticks_ms,ticks_us,ticks_diff}.
Framework for time.ticks_cpu added, but not implemented.
2016-03-04 09:25:53 +02:00
Damien George
b41a14a4b9 esp8266: Add mp_hal_delay_us function. 2016-03-04 09:25:05 +02:00
Damien George
f70873db23 esp8266: Enable more features in mpconfigport.h.
This is to get the test suite running and passing.
2016-03-03 23:34:31 +02:00
Paul Sokolovsky
7480ee5892 esp8266: Enable uhashlib module. 2016-03-03 20:14:50 +02:00
Paul Sokolovsky
70fb9ee99b esp8266: Enable config settings helpful for debugging. 2016-03-03 20:12:26 +02:00
Paul Sokolovsky
2382d30318 tests/run-tests: Skips for esp8266. 2016-03-03 15:38:43 +02:00
Paul Sokolovsky
259f1344ca esp8266/esp8266.ld: Link in SDK version section.
Otherwise, os.uname() returns empty string for SDK version.
2016-03-03 15:37:19 +02:00
Paul Sokolovsky
ff69a1d27d esp8266: Enable ujson, ubinascii, and uctypes modules. 2016-03-03 15:35:29 +02:00
Paul Sokolovsky
65405247a0 extmod/vfs_fat_lexer: Add func prototype for pedantic warnings. 2016-03-03 14:53:36 +02:00
Paul Sokolovsky
3aa0f2eed3 extmod/vfs_fat_lexer: Make conditional on FatFs support enabled. 2016-03-03 14:08:27 +02:00
Paul Sokolovsky
453a2a3d7c extmod/vfs_fat: Add lexer, move from stmhal port for reuse. 2016-03-03 13:25:44 +02:00
Paul Sokolovsky
701c4152c1 tarvis: Unbreak build by ignoring lack of i386 arch in some repos.
For some reason, Travis now has Google Chrome PPA included in the builder
image, that lacks i386 arch, that leads to apt-get update error. So, ignore
it (this is not ideal as may lead to actual repo update failures to be missed,
leading to installation of old package, leading to weird errors; let's keep
that in mind).
2016-03-03 11:06:36 +02:00
Damien George
02ea74d8f5 esp8266: Add network.ifconfig(). 2016-03-02 23:04:21 +02:00
Damien George
1febaf3ac3 esp8266: Change "soft reboot" message to work with pyboard.py. 2016-03-02 22:58:48 +02:00
Damien George
d083d7d610 esp8266: Allow Makefile's PORT variable to be overridden. 2016-03-02 22:50:55 +02:00
Damien George
6f4357c28e esp8266: Enable math module. 2016-03-02 22:43:10 +02:00
Damien George
6d0629bddc esp8266: Enable float support, using 30-bit stuffed floats.
No complex numbers though.
2016-03-02 22:43:10 +02:00
Damien George
ecd1272d16 esp8266: Switch bignum implementation from long-long to mpz. 2016-03-02 22:43:10 +02:00
Damien George
3d1d92acfc mpy-cross: Give a more sensible error message when file doesn't exist. 2016-03-02 16:12:00 +00:00
Noah Rosamilia
6bb9d3ea3e docs/uctypes.rst: Fix typo (steamlined -> streamlined). 2016-03-02 00:25:10 +02:00
Paul Sokolovsky
dc320164d8 unix/modsocket: Add comment regarding close() error checking (which is none). 2016-03-02 00:20:48 +02:00
Damien George
4f72aa86bf py/qstrdefs: Add mkdir and remove qstrs for user-mountable filesystems. 2016-02-29 10:54:00 +00:00
Paul Sokolovsky
2740dd85f2 tests/vfs_fat_ramdisk: Add testcase for .rename(). 2016-02-29 01:24:18 +02:00
Paul Sokolovsky
e0821830b0 extmod/vfs_fat: Add .rename() method. 2016-02-29 01:23:53 +02:00
Paul Sokolovsky
09e363316f extmod/vfs_fat_misc: Fix cc3200 port build. 2016-02-29 01:15:19 +02:00
Paul Sokolovsky
9fb36af9af tests/vfs_fat_ramdisk: Allow to run in native mode (don't use "with"). 2016-02-29 01:03:32 +02:00
Paul Sokolovsky
08fed6992f extmod/vfs_fat_misc: Add func prototype for pedantic warnings. 2016-02-29 00:48:45 +02:00
Paul Sokolovsky
6ef65e70af extmod/vfs_fat: Add fat_vfs_import_stat(), reusable import stat routine.
Moved from stmhal.
2016-02-29 00:44:32 +02:00
Paul Sokolovsky
eaa96a7610 tests/vfs_fat_ramdisk: Add testcase for .mkdir(). 2016-02-29 00:06:44 +02:00
Paul Sokolovsky
bbe832a0b2 extmod/vfs_fat: Add .mkdir() method. 2016-02-29 00:03:20 +02:00
Paul Sokolovsky
6f469209e9 extmod/vfs_fat: Fix unused param warning/error. 2016-02-28 20:45:51 +02:00
Paul Sokolovsky
57425b648f tests/vfs_fat_ramdisk: Add testcase for .remove(). 2016-02-28 20:30:59 +02:00
Paul Sokolovsky
19749db7bf extmod/vfs_fat: Add .remove() method.
Based on stmhal implementation - rather small, so just duplicating.
2016-02-28 20:30:07 +02:00
Paul Sokolovsky
9c081b740b tests/vfs_fat_ramdisk: Add .listdir() testcase. 2016-02-28 17:19:12 +02:00
Paul Sokolovsky
cd6d189f48 extmod/vfs_fat: Move listdir() method from stmhal for reuse. 2016-02-28 17:17:24 +02:00
danicampora
8a18084571 cc3200: Update WiPy software version to 1.2.0 2016-02-27 00:19:53 +01:00
Damien George
ac23662550 unix: Enabled importing of persistent bytecode (.mpy files). 2016-02-25 10:12:30 +00:00
Damien George
476c15290d stmhal: Enabled importing of persistent bytecode (.mpy files). 2016-02-25 10:12:30 +00:00
Damien George
56f76b873a mpy-cross: Add new component, a cross compiler for MicroPython bytecode.
This component allows to generate .mpy files (pre compiled bytecode)
which can be executed within any MicroPython runtime/VM.
2016-02-25 10:12:21 +00:00
Damien George
ea23520403 py: Add MICROPY_DYNAMIC_COMPILER option to config compiler at runtime.
This new compile-time option allows to make the bytecode compiler
configurable at runtime by setting the fields in the mp_dynamic_compiler
structure.  By using this feature, the compiler can generate bytecode
that targets any MicroPython runtime/VM, regardless of the host and
target compile-time settings.

Options so far that fall under this dynamic setting are:
- maximum number of bits that a small int can hold;
- whether caching of lookups is used in the bytecode;
- whether to use unicode strings or not (lexer behaviour differs, and
  therefore generated string constants differ).
2016-02-25 10:05:46 +00:00
danicampora
57b96a7be2 docs: Correct machine.Timer code examples related to duty cycle. 2016-02-23 20:22:26 +01:00
danicampora
8e1fdf2eb3 docs: Add note on machine.Timer class regarding PWM output pins. 2016-02-23 19:53:59 +01:00
Damien George
28adab36c7 py/emitinlinethumb: Use qstrs instead of char* for names of asm ops.
Reduces code size by 112 bytes on Thumb2 arch, and makes assembler faster
because comparison can be a simple equals instead of a string compare.

Not all ops have been converted, only those that were simple to convert
and reduced code size.
2016-02-23 15:20:39 +00:00
Damien George
e9d1a94bf0 py/malloc: Provide a proper malloc-based implementation of realloc_ext. 2016-02-23 13:53:38 +00:00
Damien George
d6c558c0aa py/parse: Use m_renew_maybe to ensure that memory is shrunk in-place.
The chunks of memory that the parser allocates contain parse nodes and
are pointed to from many places, so these chunks cannot be relocated
by the memory manager.  This patch makes it so that when a chunk is
shrunk to fit, it is not relocated.
2016-02-23 13:44:29 +00:00
danicampora
add930c4b5 cc3200: Rename 'server' class to 'Server' for consistency. 2016-02-22 22:54:34 +01:00
danicampora
12547ce737 docs: Minor change to improve clarity in machine.Timer docs. 2016-02-22 19:16:30 +01:00
danicampora
cc7a4d7db2 tests/wipy: Correct machine test expected result. 2016-02-22 00:42:05 +01:00
danicampora
5148860332 tests: Skip uctypes and urandom tests not supported byt the WiPy. 2016-02-21 22:30:35 +01:00
danicampora
495e7cfebc cc3200: Improve robustness of WLAN during sleep modes. 2016-02-21 22:01:18 +01:00
danicampora
f5248a087a cc3200: Fix "debug" build. 2016-02-21 21:53:21 +01:00
danicampora
0d210a0be8 docs: Correct WiPy Timer docs. 2016-02-21 21:53:20 +01:00
danicampora
fe9620a2bd test/wipy: Add Timer class tests. 2016-02-21 21:53:20 +01:00
danicampora
73c9f85b4c cc3200: Simplify the Timer API and correct the documents.
Make the PWM duty cycle configurable from 0.00 to 100.00 by
accepting values from 0 to 10000.
Add automatic Pin assignment when operating in PWM mode.
2016-02-21 21:53:16 +01:00
danicampora
562bcffd3a cc3200: Improve robustness of the I2C driver.
When scanning for devices, try reading then writing. Increase the
timeout of the transactions from 10 to 20 ms.
2016-02-21 21:41:06 +01:00
danicampora
ed8db2e371 cc3200: Finally fix the Timer class API.
Properly calculate the period and the prescaler, this now allows to
set the PWM frequency down to 5Hz. Make Timer IDs go from 0 to 3.
Add the trigger definitions for the channel IRQ.
2016-02-21 21:41:06 +01:00
Damien George
53fec1ef48 README.md: Add link to micropython.org. 2016-02-17 23:01:49 +00:00
Damien George
40d8430ee3 py/vm: Add macros to hook into various points in the VM.
These can be used to insert arbitrary checks, polling, etc into the VM.
They are left general because the VM is a highly tuned loop and it should
be up to a given port how that port wants to modify the VM internals.

One common use would be to insert a polling check, but only done after
a certain number of opcodes were executed, so as not to slow down the VM
too much.  For example:

 #define MICROPY_VM_HOOK_COUNT (30)
 #define MICROPY_VM_HOOK_INIT static uint vm_hook_divisor = MICROPY_VM_HOOK_COUNT
 #define MICROPY_VM_HOOK_POLL if (--vm_hook_divisor == 0) { \
     vm_hook_divisor = MICROPY_VM_HOOK_COUNT;
     extern void vm_hook_function(void);
     vm_hook_function();
 }
 #define MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_POLL
 #define MICROPY_VM_HOOK_RETURN MICROPY_VM_HOOK_POLL
2016-02-17 09:02:19 +00:00
Alex March
69d9e7d27d py/repl: Check for an identifier char after the keyword.
- As described in the #1850.
- Add cmdline tests.
2016-02-17 08:56:15 +00:00
Paul Sokolovsky
dfc35afba1 tests/vfs_fat_ramdisk: Skip test if can't allocate ramdisk. 2016-02-15 17:27:57 +02:00
Paul Sokolovsky
6cee869feb py/qstrdefs.h: qstrs for VfsFat. 2016-02-15 12:49:32 +02:00
Dave Hylands
ec37239e53 stmhal: Improvements to the STM32F4DISC UART config settings. 2016-02-15 10:11:29 +00:00
Dave Hylands
4b2938a4b0 stmhal: Some NETDUINO_PLUS_2 cleanup
- Put the I2C bus on the corect pins
- Add the appropriate board_init to power the shield
2016-02-15 10:07:27 +00:00
Damien George
9598f36a84 py/emitnative: Add check that RHS of viper store is of integral type. 2016-02-15 09:38:02 +00:00
Damien George
94e4bd456f py/asmx64: Support all 16 regs in reg to memory move instructions. 2016-02-15 09:05:50 +00:00
Damien George
46fc7a3d75 py/asmx64: Add helper macro for generating REX_[WRXB] bits from a reg64. 2016-02-15 09:02:13 +00:00
Paul Sokolovsky
4cd45f48b1 cc3200: Fix breakage after VfsFat refactor. 2016-02-15 10:39:56 +02:00
Paul Sokolovsky
46a0ac02c5 extmod/vfs_fat_ffconf: Reusable FatFs module, move from stmhal/ffconf.
TODO: Probably merge into vfs_fat_diskio.
2016-02-15 00:19:27 +02:00
Paul Sokolovsky
6b0c88256b extmod/vfs_fat_file: Reusable FatFs module, move from stmhal/file. 2016-02-15 00:16:46 +02:00
Paul Sokolovsky
8cb78e0e53 extmod/vfs_fat_diskio: Reusable FatFs module, move from stmhal/diskio. 2016-02-15 00:08:37 +02:00
Paul Sokolovsky
72085a669b py/mpstate.h: fs_user_mount is now standard, reusable uPy functionality. 2016-02-15 00:02:03 +02:00
Paul Sokolovsky
9fdac9144d tests/vfs_fat_ramdisk: Allow to override sector size. 2016-02-14 20:52:38 +02:00
Paul Sokolovsky
9d0525182d tests/vfs_fat_ramdisk: Switch to ioctl-based blockdev API. 2016-02-14 20:45:08 +02:00
Paul Sokolovsky
9e0478a902 stmhal/diskio: Add provision for default returns for ioctl INIT/SEC_SIZE.
If None was returned for such requests (which likely means that user simply
didn't handle them), it means successful init and default sector size of 512
bytes respectively. This makes only BP_IOCTL_SEC_COUNT a mandatory request,
and thus re-establishes parity with old interface, where only .count() is
mandatory().
2016-02-14 20:34:30 +02:00
Paul Sokolovsky
0ee1d0f407 tests/vfs_fat_ramdisk: Add test for VfsFat. 2016-02-14 19:15:22 +02:00
Paul Sokolovsky
e3c66a5a67 stmhal/file: Paranoid compiler warnings cleanness. 2016-02-14 19:15:22 +02:00
Paul Sokolovsky
baf47c84c4 stmhal/diskio,file: Nanbox cleanness. 2016-02-14 19:15:22 +02:00
Paul Sokolovsky
1bb15ca427 extmod/fsusermount,vfs_fat: Nanbox cleanness. 2016-02-14 19:15:22 +02:00
Paul Sokolovsky
8a43a41b3a unix: Enable VfsFat support. 2016-02-14 19:15:22 +02:00
Paul Sokolovsky
e9be6a378c extmod/vfs_fat: Object-oriented encapsulation of FatFs VFS.
This implements OO interface based on existing fsusermount code and with
minimal changes to it, to serve as a proof of concept of OO interface.

Examle of usage:

bdev = RAMFS(48)
uos.VfsFat.mkfs(bdev)
vfs = uos.VfsFat(bdev, "/ramdisk")
f = vfs.open("foo", "w")
f.write("hello!")
f.close()
2016-02-14 19:15:21 +02:00
Paul Sokolovsky
dc3eb55e6a py/obj.h: If not float support is enabled, define mp_obj_is_float(o) to false.
We have so many configuration options, that finally having shortcuts like
this is helpful and cuts on number of ifdef's.
2016-02-14 19:12:57 +02:00
Paul Sokolovsky
e5cff5b223 tests/bytearray1: Add testcases for "in" operator. 2016-02-14 18:57:18 +02:00
Paul Sokolovsky
c38809e26b py/objarray: Implement "in" operator for bytearray. 2016-02-14 18:57:11 +02:00
Paul Sokolovsky
609a9c6b71 eagle.rom.addr.v6.ld: More symbols from SDK 1.5.0. 2016-02-14 13:09:42 +02:00
Paul Sokolovsky
bf904b238d extmod/fsusermount: umount: Add NULL pointer checks. 2016-02-13 22:55:35 +02:00
Paul Sokolovsky
d4315a6caf float/string_format: Split large test in 2. 2016-02-13 17:18:55 +02:00
Paul Sokolovsky
2850e7cd97 tests/run-tests: Add esp8266 target. 2016-02-13 17:03:12 +02:00
Paul Sokolovsky
dc587a3623 test/float2int: Make test output clearer. 2016-02-13 17:03:02 +02:00
Paul Sokolovsky
a2e39a756c esp8266/modpybrtc: Simplify multiplication by fixed-point value. 2016-02-12 23:20:52 +02:00
Dave Hylands
32b7e93535 stmhal: NUCLEO 401 - Add definitions for I2C2 and I2C3 2016-02-10 21:26:14 -08:00
Dave Hylands
f791e14750 stmhal: CERB40 - Add pins defines for I2C3 2016-02-10 21:25:30 -08:00
Dave Hylands
38ac23c942 stmhal: NUCLEO 401 - Add a bunch of missing pins and reorder the pins
This groups the pins for a port together and puts them in numerical
order. It also adds ARDUINO pin names.
2016-02-10 21:23:45 -08:00
Dave Hylands
7bb501ef9f stmhal: Add a function for setting the pin alternate function
mp_hal_gpio_set_af will search for a given function and unit
and set the alternate function to the alternate function index
found.
2016-02-10 21:20:14 -08:00
Damien George
e372e83b30 extmod/fsusermount: Move BP_IOCTL_xxx constants to fsusermount.h. 2016-02-10 23:40:35 +00:00
Damien George
b33a770596 extmod/fsusermount: Support mounting of multiple block devices.
This patch adds support to fsusermount for multiple block devices
(instead of just one).  The maximum allowed is fixed at compile time by
the size of the fs_user_mount array accessed via MP_STATE_PORT, which
in turn is set by MICROPY_FATFS_VOLUMES.

With this patch, stmhal (which is still tightly coupled to fsusermount)
is also modified to support mounting multiple devices   And the flash and
SD card are now just two block devices that are mounted at start up if
they exist (and they have special native code to make them more
efficient).
2016-02-10 23:40:10 +00:00
Damien George
34023eb673 stmhal: Add mount/umount/mkfs to os module. 2016-02-10 23:40:10 +00:00
Damien George
0e0ce47e65 extmod/fsusermount: Expose umount as a public function. 2016-02-10 23:40:10 +00:00
Damien George
3770cd2e70 stmhal: Expose flash and SD card as proper objects with block protocol.
You can now create (singleton) objects representing the flash and SD
card, using:

    flash = pyb.Flash()
    sdcard = pyb.SDCard()

These objects provide the block protocol.
2016-02-10 23:40:10 +00:00
Damien George
f7e5e677df tests/pyb: Add simple test for stm module on pyboard. 2016-02-10 17:06:07 +00:00
Damien George
3a042fb921 extmod/modmachine: Truncate integers that are to be stored using mem*.
Addresses issue #1835.
2016-02-10 17:05:03 +00:00
Dave Hylands
a888d5ab91 stmhal: Improve NUCLEO-F401RE build, with UART2 as REPL.
This enables MICROPY_HW_HAS_FLASH which got missed.

The HW has UART2 on the 401 connected to the STLINK procesor
which exposes it as USB serial. This connects that up so that
you can get a REPL using the USB serial.
2016-02-10 16:50:05 +00:00
Damien George
13a4c120ce lib/fatfs: Add support for sector sizes larger than 512 bytes.
If MICROPY_FATFS_MAX_SS is defined to power of 2 value between 1024 and
4096, support for dynamic sector size in FatFs will be enabled.  Note
that FatFs reserves static buffer of MICROPY_FATFS_MAX_SS size for each
filesystem in use, so that value should be set sparingly.

Initial patch provided by @pfalcon.
2016-02-10 08:59:58 +00:00
Damien George
c33ad60a67 extmod/fsusermount: Change block protocol to support ioctl method.
The new block protocol is:
- readblocks(self, n, buf)
- writeblocks(self, n, buf)
- ioctl(self, cmd, arg)

The new ioctl method handles the old sync and count methods, as well as
a new "get sector size" method.

The old protocol is still supported, and used if the device doesn't have
the ioctl method.
2016-02-10 08:59:31 +00:00
Paul Sokolovsky
3846fd56c1 extmod/fsusermount: Implement separate umount() function. 2016-02-10 00:51:47 +02:00
Paul Sokolovsky
5b85a86ce3 extmod/fsusermount: Introduce separate mkfs() function.
Per the previously discussed plan. mount() still stays backward-compatible,
and new mkfs() is rought and takes more args than needed. But is a step
in a forward direction.
2016-02-10 00:50:07 +02:00
Damien George
a2e5e4c3d8 py/viper: Allow uint as index to load/store, and give better error msg. 2016-02-09 13:46:49 +00:00
Damien George
3e02b1d19a py/viper: Allow casting of Python integers to viper pointers.
This allows you to pass a number (being an address) to a viper function
that expects a pointer, and also allows casting of integers to pointers
within viper functions.

This was actually the original behaviour, but it regressed due to native
type identifiers being promoted to 4 bits in width.
2016-02-09 13:29:20 +00:00
Paul Sokolovsky
9e78ab4b86 esp8266/README: Add hint about adding toolchain to PATH. 2016-02-08 22:35:24 +02:00
Paul Sokolovsky
814b1ae3a9 esp8266/modpybrtc: pyb_rtc_memory(): Fix copy-paste error. 2016-02-08 21:39:33 +02:00
Alex March
81407729a5 esp8266/modesp: Implement flash_write(), flash_erase(). 2016-02-08 11:42:24 +02:00
Paul Sokolovsky
96688de601 cc3200: Add stmhal/builtin_open.c to build. 2016-02-07 01:26:01 +02:00
Paul Sokolovsky
ab0e36b3da stmhal/file: For self-contained usecase, don't define global types.
If MICROPY_VFS_FAT is defined, mp_type_fileio & mp_type_textio won't be
defined, as these may be alredy defined elsewhere. The idea is to have
compartmentalized VFS FatFs class, which can work in parallel with some
other "main" filesystem. E.g., for unix port, mp_type_fileio, etc. will
be defined for the main POSIX filesystem, while stmhal/file.c will be
a self-contained VFS file class.
2016-02-07 01:25:28 +02:00
Paul Sokolovsky
350ab0f570 stmhal/file: Recast as "FatFs file" class, to support other VFS types.
Move definition of mp_builtin_open_obj to a separate module, then file.c
becomes more or less compartmentalized FatFs file class, which can be used
together with file class implementations for other (V)FSes.
2016-02-07 01:25:28 +02:00
Paul Sokolovsky
103fbaaf27 extmod/fsusermount: Common subexpression elimination.
Don't repeat MP_STATE_PORT(fs_user_mount), use local var.
2016-02-06 22:26:34 +02:00
Paul Sokolovsky
5bf6eba845 tests/open_plus: Add tests for "r+", "w+" open modes. 2016-02-06 21:59:54 +02:00
Paul Sokolovsky
a63a4761cd unix/file: Stop assuming that O_RDWR == O_RDONLY | O_WRONLY.
That's not true e.g. on Linux.
2016-02-06 21:59:44 +02:00
Paul Sokolovsky
71206f02c3 stmhal: Move stmhal-specific FatFs routines/structs to fatfs_port.c. 2016-02-06 15:31:00 +02:00
Paul Sokolovsky
97a0846af9 stmhal/diskio: Introduce MICROPY_HW_HAS_FLASH setting.
To allow to reuse stmhal/diskio for ports which don't have flash but have
other storage devices.
2016-02-06 15:07:01 +02:00
Damien George
ff1a96ce2c py/mpz: Add commented-out mpz_pow3_inpl function, to compute (x**y)%z.
This function computes (x**y)%z in an efficient way.  For large arguments
this operation is otherwise not computable by doing x**y and then %z.

It's currently not used, but is added in case it's useful one day.
2016-02-03 22:30:49 +00:00
Doug Currie
2e2e15cec2 py/mpz: Complete implementation of mpz_{and,or,xor} for negative args.
For these 3 bitwise operations there are now fast functions for
positive-only arguments, and general functions for arbitrary sign
arguments (the fast functions are the existing implementation).

By default the fast functions are not used (to save space) and instead
the general functions are used for all operations.

Enable MICROPY_OPT_MPZ_BITWISE to use the fast functions for positive
arguments.
2016-02-03 22:13:39 +00:00
Damien George
5f3e005b67 py: Extend native type-sig to use 4 bits, so uint is separate to ptr.
Before this patch, the native types for uint and ptr/ptr8/ptr16/ptr32
all overlapped and it was possible to make a mistake in casting.  Now,
these types are all separate and any coding mistakes will be raised
as runtime errors.
2016-02-02 23:16:05 +00:00
Damien George
086d98cbde py/objstr: Make mp_obj_str_format_helper static. 2016-02-02 16:51:52 +00:00
Damien George
87e07ea943 py/objstr: For str.format, don't allocate on the heap for field name. 2016-02-02 16:26:21 +00:00
pohmelie
e3a29de1dc py/objstr: For str.format, add nested/computed fields support.
Eg: '{:{}}'.format(123, '>20')

@pohmelie was the original author of this patch, but @dpgeorge made
significant changes to reduce code size and improve efficiency.
2016-02-02 16:25:24 +00:00
Peter Hinch
2bd758fe96 drivers/sdcard: Add support for multi-block read/write; add SD test. 2016-02-02 11:16:15 +00:00
Paul Sokolovsky
67e8108345 extmod: Update uzlib to 1.2.2.
Fixes use of uninitialized structure field by tinf_uncompress().
2016-02-01 23:05:45 +02:00
Damien George
93bb7dffd2 py/vm: Fix popping of exception block in UNWIND_JUMP opcode.
Fixes issue #1812.
2016-02-01 16:07:21 +00:00
Damien George
9e677114e4 py/mpprint: Fix sign extension when printf'ing %u, %x and %X. 2016-02-01 15:08:42 +00:00
Damien George
331a48195d docs: Bump version to 1.6. 2016-01-31 23:22:41 +00:00
Damien George
ef5f2669dc tests: For pyboard, add test for I2C error handling and recovery. 2016-01-30 00:06:04 +00:00
Damien George
db573082b5 stmhal: Update HALCOMMITS due to change to hal. 2016-01-30 00:05:46 +00:00
Damien George
ea040a4f9a stmhal: In HAL I2C driver, move DMA setup to after sending I2C address.
Previous to this patch the DMA was setup and then the I2C address sent.
If the I2C address sending failed (eg no I2C device on the bus) then the
DMA was left in an inconsistent state.

This patch moves the DMA setup to after a successful sending of the I2C
address(es).

See issue #1765.
2016-01-30 00:02:21 +00:00
Damien George
3cfb15cf4d tests: Update pyboard LED test. 2016-01-29 23:12:59 +00:00
Damien George
0f87a010e3 docs: Update to say that Timer(3) is free, and detail LED intensity. 2016-01-29 23:06:13 +00:00
Damien George
a8a4b01af6 stmhal: Add PWM capability for LED(3) and LED(4) on pyboards.
USB CDC no longer needs TIM3 (which was originally used for LED(4) PWM)
and so TIM3 has been freed for general purpose use by the user.  Hence
LED(4) lost its PWM capabilities.

This patch reinstates the PWM capabilities using a semi-generic piece
of code which allows to configure a timer and PWM channel to use for any
LED.  But the PWM capability is only configured if the LED is set to an
intensity between 1 and 254 (ie only when needed).  In that case the
relevant timer is configured for PWM.  It's up to the user to make sure
the timers are not used if PWM is active.

This patch also makes sure that PWM LEDs are turned off using standard
GPIO when calling led.off() or led.intensity(0), instead of just setting
the PWM counter to zero.
2016-01-29 22:44:43 +00:00
Damien George
ea89b80ff4 stmhal: Make TIM3 available for use by the user.
TIM3 is no longer used by USB CDC for triggering outgoing data, so we
can now make it available to the user.

PWM fading on LED(4) is now gone, but will be reinstated in a new way.
2016-01-29 22:31:56 +00:00
Damien George
d363133917 stmhal: Make USB CDC driver use SOF instead of TIM3 for outgoing data.
Previous to this patch the USB CDC driver used TIM3 to trigger the
sending of outgoing data over USB serial.  This patch changes the
behaviour so that the USB SOF interrupt is used to trigger the processing
of the sending.  This reduces latency and increases bandwidth of outgoing
data.

Thanks to Martin Fischer, aka @hoihu, for the idea and initial prototype.

See PR #1713.
2016-01-29 15:21:43 +00:00
Damien George
7417ccfb0d py/formatfloat: Add ability to format doubles with exponents > 99.
For single prec, exponents never get larger than about 37.  For double
prec, exponents can be larger than 99 and need 3 bytes to format.  This
patch makes the number of bytes needed configurable.

Addresses issue #1772.
2016-01-29 11:39:12 +00:00
Paul Sokolovsky
d3b1f0b627 py/runtime: mp_stack_ctrl_init() should be called immediately on startup.
Calling it from mp_init() is too late for some ports (like Unix), and leads
to incomplete stack frame being captured, with following GC issues. So, now
each port should call mp_stack_ctrl_init() on its own, ASAP after startup,
and taking special precautions so it really was called before stack variables
get allocated (because if such variable with a pointer is missed, it may lead
to over-collecting (typical symptom is segfaulting)).
2016-01-29 02:13:42 +02:00
Paul Sokolovsky
850212203a unix/main: Remove debug code left from MP_OBJ_TO_PTR refactor. 2016-01-29 01:00:36 +02:00
Dave Hylands
6a804cbaba lib/utils/printf: Fix printf on release builds
When using newer glibc's the compiler automatically sets
_FORTIFY_SOURCE when building with -O1 and this causes
a special inlined version of printf to be declared which
then bypasses our version of printf.
2016-01-28 22:31:24 +02:00
Damien George
7b05b1b225 py/bc: Update opcode format table now that MP_BC_NOT opcode is gone.
MP_BC_NOT was removed and the "not" operation made a proper unary
operator, and the opcode format table needs to be updated to reflect
this change (but actually the change is only cosmetic).
2016-01-28 16:11:41 +00:00
Paul Sokolovsky
ac37e0fd1f unix/modsocket: sockaddr(): Handle AF_INET6 addresses. 2016-01-27 18:02:17 +02:00
Damien George
8f54c08691 py/inlineasm: Add ability to specify return type of asm_thumb funcs.
Supported return types are: object, bool, int, uint.

For example:

@micropython.asm_thumb
def foo(r0, r1) -> uint:
    add(r0, r0, r1)
2016-01-27 14:27:10 +00:00
Carmine Noviello
3d42aa07dd stmhal: Add support for the STM32F401NUCLEO board.
Includes full version of pins.csv file with correct mapping of the Nucleo
STM32F401RE chip (LQFP64 package).
2016-01-27 12:30:36 +00:00
Damien George
ac11e89fa3 tests: For urandom test, use sys.exit() instead of sys.exit(1). 2016-01-26 21:57:02 +00:00
Damien George
e713222fab windows/msvc: Add modurandom.c to list of source files. 2016-01-26 19:38:59 +00:00
Damien George
0ae97f531d tests: Add some tests for urandom module. 2016-01-26 15:27:00 +00:00
Damien George
d22bdad6dd windows: Enable urandom module. 2016-01-26 15:27:00 +00:00
Damien George
a53af6c875 extmod/modurandom: Add some extra random functions.
Functions added are:
- randint
- randrange
- choice
- random
- uniform

They are enabled with configuration variable
MICROPY_PY_URANDOM_EXTRA_FUNCS, which is disabled by default.  It is
enabled for unix coverage build and stmhal.
2016-01-26 15:27:00 +00:00
Paul Sokolovsky
f5c42dd9d1 extmod/moduhashlib: Use MICROPY_PY_UHASHLIB_SHA1 config define. 2016-01-25 00:49:00 +02:00
Paul Sokolovsky
ee1656e148 extmod/moduhashlib: Add support for SHA1 (based on axTLS).
SHA1 is used in a number of protocols and algorithm originated 5 years ago
or so, in other words, it's in "wide use", and only newer protocols use
SHA2.

The implementation depends on axTLS enabled. TODO: Make separate config
option specifically for sha1().
2016-01-24 20:55:09 +02:00
Damien George
df4ce930e3 py/modmicropython: Add stack_use, heap_lock and heap_unlock functions.
micropython.stack_use() returns an integer being the number of bytes used
on the stack.

micropython.heap_lock() and heap_unlock() can be used to prevent the
memory manager from allocating anything on the heap.  Calls to these are
allowed to be nested.
2016-01-24 09:12:06 +00:00
Dave Hylands
42a6364a31 stmhal: Add support for building frozen files.
This allows FROZEN_DIR=some-directory to be specified on the make
command line, which will then add all of the files contained within
the indicated frozen directory as frozen files in the image.

There is no change in flash/ram usage if not using the feature.

This is especially useful on smaller MCUs (like the 401) which only
has 64K flash file system.
2016-01-23 21:53:04 +00:00
Paul Sokolovsky
6c8b3a7fee py/objgetitemiter: Typo fix in comment. 2016-01-23 23:30:06 +02:00
Paul Sokolovsky
cb4fbc8861 unix/modsocket: accept(): Make IPv6-clean.
By reserving enough space for peer address.
2016-01-21 23:55:20 +02:00
Dave Hylands
f22844b4e5 stmhal: Add os.statvfs
Implement enough of statvfs to determine the amount of free
space on a volume.
2016-01-19 12:29:47 +00:00
Dave Hylands
a17755ee8b py: Add ustruct.pack_into and unpack_from 2016-01-19 12:25:28 +00:00
Paul Sokolovsky
ac16cc9a35 .travis.yml: Switch to Ubuntu 14.04 Trusty.
This allows to cut number of packages installed from 3rd-party package repos,
and otherwise cut number of overrides and hacks.
2016-01-17 20:07:41 +02:00
Paul Sokolovsky
ea495d6aa6 extmod/modurandom: Make yasmarang() function static. 2016-01-17 14:12:33 +02:00
Paul Sokolovsky
a58a91eb04 extmod/modurandom: Add "urandom" module.
Seedable and reproducible pseudo-random number generator. Implemented
functions are getrandbits(n) (n <= 32) and seed().

The algorithm used is Yasmarang by Ilya Levin:
http://www.literatecode.com/yasmarang
2016-01-17 12:13:01 +02:00
Damien George
e7bee6b35e pic16bit: Minor updates to types to allow port to compile again. 2016-01-16 21:07:26 +00:00
Damien George
31dd312f83 unix/modffi: Allow to compile modffi in OBJ_REPR_D mode. 2016-01-15 14:26:24 +00:00
Damien George
55ad083061 unix/.gitignore: Add nanbox build output to ignore list. 2016-01-15 14:25:53 +00:00
Damien George
aeadda4eac travis: Add unix NaN-boxing build to Travis builds.
This will help make sure new commits work with OBJ_REPR_D.
2016-01-15 11:13:42 +00:00
Damien George
d8b08cf5fc unix: Add option to build 64-bit NaN-boxing interpreter.
Build using: make nanbox
2016-01-15 11:12:08 +00:00
Damien George
ff133cdb07 py/objproperty: Fix static struct to build with OBJ_REPR_D. 2016-01-15 11:09:20 +00:00
chrysn
f8ba2eca80 builtin property: accept keyword arguments
this allows python code to use property(lambda:..., doc=...) idiom.

named versions for the fget, fset and fdel arguments are left out in the
interest of saving space; they are rarely used and easy to enable when
actually needed.

a test case is included.
2016-01-14 21:15:18 +02:00
stijn
dea585f8ae tests: Remove builtin_dict test
This is essentially a duplicate of obj_dict.py
2016-01-14 21:10:59 +02:00
Peter Hinch
c13b2f2d00 docs: Several minor changes: network, pyb, ADCAll and inline asm. 2016-01-13 21:53:26 +00:00
Damien George
22d85ec5be py: Use new code pattern for parsing kw args with mp_arg_parse_all.
Makes code easier to read and more maintainable.
2016-01-13 15:47:56 +00:00
Damien George
8bb4931fec py/emitglue: Use mp_obj_is_float instead of MP_OBJ_IS_TYPE. 2016-01-13 15:24:41 +00:00
Antonin ENFRUN
efc971e8f9 py: unary_op enum type fix, and a cast to remove clang warning 2016-01-12 22:06:39 +01:00
Damien George
c9845a0685 unix: Allow to build coverage build with OBJ_REPR_D. 2016-01-11 16:30:58 +00:00
Dave Hylands
11b97d7ec5 unix: Add socket.inet_ntop function 2016-01-11 12:08:07 +02:00
Damien George
5b3f0b7f39 py: Change first arg of type.make_new from mp_obj_t to mp_obj_type_t*.
The first argument to the type.make_new method is naturally a uPy type,
and all uses of this argument cast it directly to a pointer to a type
structure.  So it makes sense to just have it a pointer to a type from
the very beginning (and a const pointer at that).  This patch makes
such a change, and removes all unnecessary casting to/from mp_obj_t.
2016-01-11 00:49:27 +00:00
Damien George
4b72b3a133 py: Change type signature of builtin funs that take variable or kw args.
With this patch the n_args parameter is changed type from mp_uint_t to
size_t.
2016-01-11 00:49:27 +00:00
Damien George
a0c97814df py: Change type of .make_new and .call args: mp_uint_t becomes size_t.
This patch changes the type signature of .make_new and .call object method
slots to use size_t for n_args and n_kw (was mp_uint_t.  Makes code more
efficient when mp_uint_t is larger than a machine word.  Doesn't affect
ports when size_t and mp_uint_t have the same size.
2016-01-11 00:48:41 +00:00
Dave Hylands
66d0c1052a extmod: Fix uctypes size calculation for bitfields 2016-01-10 23:31:26 +02:00
Paul Sokolovsky
8175877ad6 unix/modtime: strftime(): Support 2nd argument, but as time_t value.
Instead of struct tm like structure, as required by CPython.
2016-01-10 12:08:27 +02:00
Damien George
fe6756aa2d py: Remove long-obsolete mp_method_t typedef. 2016-01-10 00:06:36 +00:00
Paul Sokolovsky
bae052d420 examples/unix: Rename example be importable as modules.
Replace hyphens with undescores in modules.
2016-01-09 12:04:25 +02:00
Damien George
3b936a5f4c tests: Fix math_fun_special test so it passes with single prec float. 2016-01-08 17:58:02 +00:00
Damien George
da3dffa79d py/objint: Fix classification of float so it works for OBJ_REPR_D. 2016-01-08 17:57:30 +00:00
Damien George
2adf7ec3dd py/mpz: Fix conversion of float to mpz so it works on big endian archs. 2016-01-08 17:56:58 +00:00
Damien George
b1fa907d56 tests: Allow float tests to run when MATH_SPECIAL_FUNCTIONS is disabled. 2016-01-08 14:27:21 +00:00
Damien George
978d2e55ef py/runtime: Use appropriate printf fmt for malloc num_bytes. 2016-01-08 13:49:58 +00:00
Damien George
c1c57eafac py/smallint: Allow to override MP_SMALL_INT_MIN et al.
This allows a port to specify exactly how many bits are in a small
int (eg for a uPy bytecode cross compiler).
2016-01-08 13:43:56 +00:00
Damien George
1fa6be5264 py/obj: For OBJ_REPR_D, use uint32_t cast when extracting qstr value. 2016-01-08 13:43:13 +00:00
Damien George
7dbf74c5b9 py/parse: Include unistd.h for ssize_t definition.
In some cases ssize_t is not defined by already included headers.
2016-01-08 13:42:00 +00:00
Damien George
1404d620c0 py/emitglue: Add more feature flags to .mpy persistent bytecode output.
Need to record in .mpy file whether unicode is enabled, and how many bits
are in a small int.
2016-01-08 13:35:35 +00:00
Paul Sokolovsky
adfe4ff72a esp8266: Support CFLAGS_EXTRA. 2016-01-08 01:30:20 +02:00
Damien George
54729247e1 minimal: Add enough code to run minimal build on STM32F4xx hardware.
Minimal support code for a Cortex-M CPU is added, along with set-up
code for an STM32F4xx MCU, including a UART for a REPL.  Tested on
a pyboard.  Code size is 77592 bytes.
2016-01-07 17:43:07 +00:00
Damien George
dd0a0f79d7 py/viper: Truncate viper integer args so they can be up to 32-bit. 2016-01-07 16:48:20 +00:00
Damien George
daa1a455c6 stmhal: Remove custom mod_machine_mem_get_{read,write}_addr functions.
They are no longer needed because stm constants can now be 32 bits wide.
2016-01-07 16:34:11 +00:00
Damien George
2621f8a340 stmhal: Make stm constants big ints when they don't fit in a small int.
Adds 924 bytes of code, but means that no more hacks and work-arounds are
needed due to large constants becoming negative.
2016-01-07 16:34:11 +00:00
Damien George
ea8be373a9 py/inlinethumb: Remove 30-bit restriction on movwt instruction.
movwt can now move a full 32-bit constant into a register.
2016-01-07 16:34:11 +00:00
Damien George
47dc5922ca py/inlinethumb: Allow assembler to use big ints as args to instructions. 2016-01-07 16:21:07 +00:00
Damien George
22b2265053 py/parse: Improve constant folding to operate on small and big ints.
Constant folding in the parser can now operate on big ints, whatever
their representation.  This is now possible because the parser can create
parse nodes holding arbitrary objects.  For the case of small ints the
folding is still efficient in RAM because the folded small int is stored
inplace in the parse node.

Adds 48 bytes to code size on Thumb2 architecture.  Helps reduce heap
usage because more constants can be computed at compile time, leading to
a smaller parse tree, and most importantly means that the constants don't
have to be computed at runtime (perhaps more than once).  Parser will now
be a little slower when folding due to calls to runtime to do the
arithmetic.
2016-01-07 14:40:35 +00:00
Damien George
d6b31e4578 py: Change mp_obj_int_is_positive to more general mp_obj_int_sign.
This function returns the sign (-1, 0 or 1) of the integer object.
2016-01-07 14:29:12 +00:00
Damien George
93b3726240 py/parse: Optimise away parse node that's just parenthesis around expr.
Before this patch, (x+y)*z would be parsed to a tree that contained a
redundant identity parse node corresponding to the parenthesis.  With
this patch such nodes are optimised away, which reduces memory
requirements for expressions with parenthesis, and simplifies the
compiler because it doesn't need to handle this identity case.

A parenthesis parse node is still needed for tuples.
2016-01-07 13:07:52 +00:00
Henrik Sölver
67f40fb237 docs: Include extra functions in time documentation for pyboard. 2016-01-04 22:57:21 +00:00
Damien George
1d191fdf03 docs: Add link from pyboard switch tutorial to ISR rules document. 2016-01-04 16:18:44 +00:00
Damien George
43cab7c283 py/modbuiltins: Fix access of mp_obj_t variable, wrap in MP_OBJ_TO_PTR. 2016-01-04 14:19:33 +00:00
Damien George
d4df8f4925 py/objstr: In str.format, handle case of no format spec for string arg.
Handles, eg, "{:>20}".format("foo"), where there is no explicit spec for
the type of the argument.
2016-01-04 13:13:39 +00:00
Paul Sokolovsky
824f83fd20 docs: Set author as 'Damien P. George and contributors'. 2016-01-03 22:17:00 +02:00
Paul Sokolovsky
275a0f25d3 docs: Fix readthedocs build by updating Latex params. 2016-01-03 22:15:07 +02:00
Paul Sokolovsky
ee7b8f32e3 tests/object_dict.py: Add test for obj.__dict__ . 2016-01-03 20:51:36 +02:00
stijn
3c014a67ea py: Implement __dict__ for instances.
Note that even though wrapped in MICROPY_CPYTHON_COMPAT, it is not
fully compatible because the modifications to the dictionary do not
propagate to the actual instance members.
2016-01-03 20:51:26 +02:00
Dave Hylands
7281d95aee py: Make dir report instance members 2016-01-03 20:37:18 +02:00
Antonin ENFRUN
b50030b1d0 tests/uctypes: Test item assignment for scalar arrays. 2016-01-03 20:32:51 +02:00
Antonin ENFRUN
26ed00118b uctypes: Implement assignment for scalar array 2016-01-03 20:23:20 +02:00
Damien George
8212d97317 py: Use polymorphic iterator type where possible to reduce code size.
Only types whose iterator instances still fit in 4 machine words have
been changed to use the polymorphic iterator.

Reduces Thumb2 arch code size by 264 bytes.
2016-01-03 16:27:55 +00:00
Paul Sokolovsky
17f324b836 py/frozenmod: Store frozen module names together, to quickly scan them. 2016-01-03 18:08:45 +02:00
Damien George
1b0aab621b py: Change struct and macro for builtin fun so they can be type checked. 2016-01-03 11:53:44 +00:00
Damien George
3d2daa2d03 py: Change exception traceback data to use size_t instead of mp_uint_t.
The traceback array stores qstrs and line numbers.  qstrs are typed as
size_t, and line numbers should safely fit in size_t as well.
2016-01-02 22:04:12 +00:00
Damien George
ae4865efa1 unix/Makefile: Move include of mpconfigport.mk to before mkenv.mk.
So that if MICROPY_FORCE_32BIT is set mpconfigport.mk it influences
mkenv.mk.
2016-01-02 21:56:03 +00:00
Paul Sokolovsky
09630e48ce unix/.gitignore: Ignore gcov files. 2016-01-02 14:50:17 +02:00
Paul Sokolovsky
98f7729848 unix/unix_mphal: Be sure to wrap dupterm code with MICROPY_PY_OS_DUPTERM. 2016-01-01 22:55:45 +02:00
Paul Sokolovsky
8fa9264430 unix/unix_mphal: Handle exceptions in call to dupterm's .read(). 2016-01-01 22:39:29 +02:00
Paul Sokolovsky
467504da01 extmod/moduos_dupterm: Handle exceptions in call to dupterm's .write() 2016-01-01 22:06:38 +02:00
Paul Sokolovsky
30b7344eb0 extmod/moduos_dupterm: Make mp_uos_dupterm_tx_strn() function reusable.
Function to actually spool output terminal data to dupterm object.
2016-01-01 16:43:35 +02:00
Paul Sokolovsky
00ee84e1e1 py: Clean up instantiation of dupterm object.
To comply with already established scheme for extmod's.
2016-01-01 14:22:57 +02:00
Paul Sokolovsky
9bbfd5efd4 py/mpconfig: Make configuration of dupterm object reusable. 2016-01-01 13:16:18 +02:00
Paul Sokolovsky
ddea7cb702 extmod/moduos_dupterm: Make uos.dupterm() implementation reusable.
That's just function which sets/gets dup terminal object, and can be
easily reused across ports.
2016-01-01 13:04:32 +02:00
Paul Sokolovsky
0992588811 py/frozenmod: Make frozen module content be 0-terminated.
To allow simple zero-terminated lexers.
2016-01-01 07:51:07 +02:00
Damien George
ed584e2ffd docs: Bump version to 1.5.2. 2015-12-31 14:43:19 +00:00
Damien George
64ececb72f lib/libc/string0: Use uintptr_t instead of uint32_t.
This makes the code portable to non-32-bit architectures.
2015-12-31 14:11:18 +00:00
Dave Hylands
8c936edeb2 stmhal: Fix USB on the STM32F429DISC board
The USB REPL has been broken since commit 1be0fde45c
This patch allows the STM32F429DISC board (which uses the USB_HS PHY)
2015-12-30 23:36:41 -08:00
Damien George
6dde019d93 py/map: In map lookup, check for fixed map independent of ordered map.
It's possible to have a fixed map that is properly hashed (ie not
simply ordered).
2015-12-31 00:24:33 +00:00
Damien George
4bd95f8b44 tools: Add C middle-processor to make builtin tables proper hash tables. 2015-12-31 00:24:33 +00:00
Peter Hinch
521759ee18 docs: Add discussion on interrupt handlers incl uPy specific techniques. 2015-12-31 00:02:09 +00:00
Paul Sokolovsky
fb7b715b7b extmod/modlwip: Use _ERR_BADF instead of magic number. 2015-12-30 16:43:35 +02:00
Paul Sokolovsky
bc25545fbb extmod/modlwip: Avoid magic numeric values in memcpy(). 2015-12-30 16:40:23 +02:00
Paul Sokolovsky
722fb2d251 extmod/modlwip: User proper field name and value names for socket state. 2015-12-30 16:26:23 +02:00
Paul Sokolovsky
43fecb0acb esp8266/modesp: Allow to compile out proprietary espconn stuff. 2015-12-30 15:53:51 +02:00
Paul Sokolovsky
fff2dd2627 extmod/modlwip: Mark some lwip_socket_obj_t's fields as volatile.
Any fields changed by asynchronous callbacks must be volatile.
2015-12-29 21:02:02 +02:00
Paul Sokolovsky
a63d4a6cc2 extmod/modlwip: tcp_recv: Use more regular and responsive poll pattern.
Polling once in 100ms means dismal performance.

TODO: Propagate this pattern to other polling places.
2015-12-29 20:37:22 +02:00
Dave Hylands
0dce9a21ce stmhal: Add struct qstr to block of qstrs needed for MICROPY_PY_STRUCT.
Otherwise build fails if uctypes is disabled.
2015-12-28 00:28:56 +00:00
Paul Sokolovsky
1e06e81b3d windows: Propagate MICROPY_PY_OS_DUPTERM handling from unix port. 2015-12-28 01:30:58 +02:00
Paul Sokolovsky
2c1620ce1f unix: Implement uos.dupterm(). Conditional on MICROPY_PY_OS_DUPTERM. 2015-12-28 01:13:21 +02:00
Paul Sokolovsky
3ea03a1188 py/gc: Improve mark/sweep debug output.
Previously, mark operation weren't logged at all, while it's quite useful
to see cascade of marks in case of over-marking (and in other cases too).
Previously, sweep was logged for each block of object in memory, but that
doesn't make much sense and just lead to longer output, harder to parse
by a human. Instead, log sweep only once per object. This is similar to
other memory manager operations, e.g. an object is allocated, then freed.
Or object is allocated, then marked, otherwise swept (one log entry per
operation, with the same memory address in each case).
2015-12-27 20:40:36 +02:00
Paul Sokolovsky
fce0036a67 esp8266: mac() function belongs to network module per the latest API. 2015-12-27 10:03:32 +02:00
stijn
1aa4599ddd windows/msvc: Nicer handling of asserts and 'invalid' parameters
The default bahaviour for debug builds is to show dialog boxes for asserts
and invalid parameter handling. This is not so nice in general and causes
the Appveyor debug builds to hang because the io\file_seek.py test passes
a closed file descriptor to lseek. Disable this behaviour by printing
assert messages to the output instead of showing the dialog, and by
disabling 'invalid' parameter handling which causes the affected functions
to just return an error and set errno appropriately.
2015-12-26 22:14:16 +00:00
Damien George
bbe8d51bd9 py/map: Add fast-path for hashing of map index when it is a qstr.
Map indicies are most commonly a qstr, and adding a fast-path for hashing
of a qstr increases overall performance of the runtime.

On pyboard there is a 4% improvement in the pystone benchmark for a cost
of 20 bytes of code size.  It's about a 2% improvement on unix.
2015-12-26 21:15:47 +00:00
Damien George
e5ce5e2a43 tests: Skip class_bind_self.py for native emitter. 2015-12-26 13:06:50 +00:00
Damien George
78913211a9 py: Be more restrictive binding self when looking up instance attrs.
When looking up and extracting an attribute of an instance, some
attributes must bind self as the first argument to make a working method
call.  Previously to this patch, any attribute that was callable had self
bound as the first argument.  But Python specs require the check to be
more restrictive, and only functions, closures and generators should have
self bound as the first argument

Addresses issue #1675.
2015-12-26 12:41:31 +00:00
Damien George
84b245f187 lib/utils: Add pyexec_frozen_module to load and execute frozen module.
This is a convenience function similar to pyexec_file.  It should be used
instead of raw mp_parse_compile_execute because the latter does not catch
and report exceptions.
2015-12-26 12:32:33 +00:00
Paul Sokolovsky
7203b58e87 extmod/modubinascii: Add "separator" argument to hexlify().
This is extension to CPython, it allows to easily produce human-readable
hex dump:

>>> ubinascii.hexlify(b"\xaa\x55\xaa\x55", b" ")
b'aa 55 aa 55'
2015-12-26 02:15:56 +02:00
Paul Sokolovsky
b4c65c253f extmod/fsusermount: Move module qstrs to global pool from stmhal port. 2015-12-25 19:22:16 +02:00
Damien George
7ce8860b6b tests: Skip try-finally test for native emitter. 2015-12-24 12:49:31 +00:00
Damien George
8047340d75 py: Handle case of return within the finally block of try-finally.
Addresses issue #1636.
2015-12-24 12:47:39 +00:00
Damien George
117158fcd5 tests: Add tests for stream IO errors. 2015-12-23 22:37:02 +00:00
Paul Sokolovsky
1c9210bc2b unix/unix_mphal: Raise KeyboardInterrupt straight from signal handler.
POSIX doesn't guarantee something like that to work, but it works on any
system with careful signal implementation. Roughly, the requirement is
that signal handler is executed in the context of the process, its main
thread, etc. This is true for Linux. Also tested to work without issues
on MacOSX.
2015-12-23 00:07:00 +02:00
Damien George
e9751d2ac0 unix: Properly cancel REPL input when Ctrl-C is pressed. 2015-12-22 22:06:09 +00:00
Damien George
401af50dc0 stmhal: Add pyb.irq_stats() to get statistics about IRQ calls.
Adds a lot of code, makes IRQs a bit less efficient, but is very useful
for debugging.  Usage: pyb.irq_stats() returns a memory view that can be
read and written, eg:

    list(pyb.irq_stats())
    pyb.irq_stats()[0]
    pyb.irq_stats()[0] = 0

The patch provides general IRQ_ENTER() and IRQ_EXIT() macros that can be
modified to provide further IRQ statistics if desired.
2015-12-22 21:00:20 +00:00
Paul Sokolovsky
abd0fcfc86 esp8266: Remove superfluous includes. 2015-12-21 22:08:06 +02:00
Paul Sokolovsky
e13d462f77 esp8266/modesp: flash_read() takes 2 args (fix typo). 2015-12-21 22:07:11 +02:00
stijn
a5aa03acaf windows: Better handling of Ctrl-C
This builds upon the changes made in 2195046365. Using signal() does not
produce reliable results so SetConsoleCtrlHandler is used, and the handler
is installed only once during initialization instead of removing it in
mp_hal_set_interrupt_char when it is not strictly needed anymore, since
removing it might lead to Ctrl-C events being missed because they are
fired on a seperate thread which might only become alive after the handler
was removed.
2015-12-21 20:51:27 +02:00
Paul Sokolovsky
1b7f622410 extmod/moduhashlib: Add namespace prefix for crypto-algorithms/sha256.h.
Everyone loves to names similar things the same, then there're conflicts
between different libraries. The namespace prefix used is "CRYAL_", which
is weird, and that's good, as that minimizes chance of another conflict.
2015-12-20 23:14:47 +02:00
Paul Sokolovsky
664bc44f30 tests: Add tests for %-formatting of bytes.
This requires CPython3.5, to not require switching to it, just use .exp
file.
2015-12-20 16:54:34 +02:00
Paul Sokolovsky
d50f649cf8 py/objstr: Applying % (format) operator to bytes should return bytes, not str. 2015-12-20 16:52:11 +02:00
Paul Sokolovsky
ef63ab5724 py/objstr: Make sure that b"%s" % b"foo" uses undecorated bytes value.
I.e. the expected result for above is b"foo", whereas previously we got
b"b'foo'".
2015-12-20 16:51:59 +02:00
stijn
0a4eb4dbf2 py/mpprint: Fix printing of 64bit integers for 64bit windows builds
This makes all tests pass again for 64bit windows builds which would
previously fail for anything printing ranges (builtin_range/unpack1)
because they were printed as range( ld, ld ).

This is done by reusing the mp_vprintf implementation for MICROPY_OBJ_REPR_D
for 64bit windows builds (both msvc and mingw-w64) since the format specifier
used for 64bit integers is also %lld, or %llu for the unsigned version.

Note these specifiers used to be fetched from inttypes.h, which is the
C99 way of working with printf/scanf in a portable way, but mingw-w64
wants to be backwards compatible with older MS C runtimes and uses
the non-portable %I64i instead of %lld in inttypes.h, so remove the use
of said header again in mpconfig.h and define the specifiers manually.
2015-12-19 01:15:58 +00:00
Dave Hylands
b61336483b stmhal: Add mem8/mem16/mem32 operations to machine module.
This uses the newly factored machine_mem functions.
2015-12-19 01:05:44 +00:00
Fabian
d0f31ccf33 stmhal: Change PLL configuration for STM32F7DISC.
Changes USB clock from 50MHz to 48MHz which improves USB communication.
2015-12-18 22:16:49 +00:00
stijn
da199e4407 windows: Add Appveyor CI builds for msvc port.
Appveyor is like Travis, but for Windows builds. The appveyor.yml configuration
will build the msvc port in all configuration/platform conbinations,
and run the tests for each of those.
2015-12-18 21:49:35 +00:00
Damien George
fe03e7bcb7 py/obj: Fix float constants for MICROPY_OBJ_REPR_C. 2015-12-18 21:44:01 +00:00
Damien George
a67651406d lib/libm: Allow math funcs to be used by non-Thumb archs.
Requires addition of software implementation of sqrtf function.
2015-12-18 21:05:44 +00:00
Paul Sokolovsky
0e1b5faad5 stmhal, cc3200: Actually implement machine -> umachine module weak link. 2015-12-18 22:22:43 +02:00
stijn
c5f52b845b msvc: Add dirent.h/.c implementation
This fixes the build after adding directory iteration in d874702
2015-12-18 22:10:51 +02:00
Dave Hylands
755b01439b unix: machine_mem improvements
This basically introduces the MICROPY_MACHINE_MEM_GET_READ_ADDR
and MICROPY_MACHINE_MEM_GET_WRITE_ADDR macros. If one of them is
not defined, then a default identity function is provided.
2015-12-18 22:01:03 +02:00
Damien George
acaccb37ec py/gc: When printing info, use %u instead of UINT_FMT for size_t args.
Ideally we'd use %zu for size_t args, but that's unlikely to be supported
by all runtimes, and we would then need to implement it in mp_printf.
So simplest and most portable option is to use %u and cast the argument
to uint(=unsigned int).

Note: reason for the change is that UINT_FMT can be %llu (size suitable
for mp_uint_t) which is wider than size_t and prints incorrect results.
2015-12-18 12:52:45 +00:00
Damien George
dd5353a405 py: Add MICROPY_ENABLE_COMPILER and MICROPY_PY_BUILTINS_EVAL_EXEC opts.
MICROPY_ENABLE_COMPILER can be used to enable/disable the entire compiler,
which is useful when only loading of pre-compiled bytecode is supported.
It is enabled by default.

MICROPY_PY_BUILTINS_EVAL_EXEC controls support of eval and exec builtin
functions.  By default they are only included if MICROPY_ENABLE_COMPILER
is enabled.

Disabling both options saves about 40k of code size on 32-bit x86.
2015-12-18 12:35:44 +00:00
Damien George
ab8012bd80 py/emitglue: Add include of unistd.h for read function. 2015-12-18 12:33:08 +00:00
Damien George
a83124361e py/compile: Simplify compilation of comprehension iterators.
Saves 88 bytes on Thumb2, and 200 bytes on x86-64 archs.
2015-12-18 01:37:55 +00:00
Paul Sokolovsky
2eb844e0b4 ports: Rename "machine" module to "umachine".
To let unix port implement "machine" functionality on Python level, and
keep consistent naming in other ports (baremetal ports will use magic
module "symlinking" to still load it on "import machine").

Fixes #1701.
2015-12-18 02:39:52 +02:00
Paul Sokolovsky
2195046365 windows/windows_mphal: Add basic support for raising KeyboardInterrupt.
Compiles with mingw32, tested to work erratically under Wine due to
not fully implemented emulation in it.
2015-12-18 01:12:59 +02:00
Paul Sokolovsky
5efd3f0dca windows: Make keyboard_interrupt_obj available, it's standard feature. 2015-12-18 01:07:27 +02:00
Paul Sokolovsky
3c2b377711 unix/unix_mphal: Just consistently set sigaction.sa_flags to 0. 2015-12-18 01:07:27 +02:00
Damien George
2fe7e6bef0 py/parse: Include stddef.h for definition of size_t. 2015-12-17 22:17:26 +00:00
Paul Sokolovsky
3db2b23060 unix/unix_mphal: Properly initialize struct sigaction.
This solves long-standing non-deterministic bug, which manifested itself
on x86 32-bit (at least of reported cases) - segfault on Ctrl+C (i.e.
SIGINT).
2015-12-17 23:24:35 +02:00
Damien George
02fa8dff85 py/modgc: Remove obsolete extern declaration. 2015-12-17 13:20:40 +00:00
Damien George
831137b807 py/compile: Use size_t or uintptr_t instead of mp_uint_t. 2015-12-17 13:13:18 +00:00
Damien George
16a6a47a7b py/parse: Replace mp_int_t/mp_uint_t with size_t etc, where appropriate. 2015-12-17 13:06:05 +00:00
Damien George
6e2fb56d40 py/qstr: Change type of qstr from mp_uint_t to size_t.
For builds where mp_uint_t is larger than size_t, it doesn't make
sense to use such a wide type for qstrs.  There can only be as many
qstrs as there is address space on the machine, so size_t is the correct
type to use.

Saves about 3000 bytes of code size when building unix/ port with
MICROPY_OBJ_REPR_D.
2015-12-17 12:45:22 +00:00
Damien George
257848587f py/qstr: Use size_t instead of mp_uint_t when counting allocated bytes. 2015-12-17 12:41:40 +00:00
Damien George
1d899e1783 py/bc: Use size_t instead of mp_uint_t to count size of state and args. 2015-12-17 12:33:42 +00:00
Damien George
7a30e87d2b py: Fix MICROPY_STACKLESS mode to compile with MICROPY_OBJ_REPR_D. 2015-12-17 12:32:41 +00:00
Damien George
ab1e36dcf9 py/mpprint: Implement %llu and %lld format specifiers for mp_printf.
Only enabled for MICROPY_OBJ_REPR_D.
2015-12-17 11:41:10 +00:00
Damien George
d977d268e8 py/gc: Use size_t instead of mp_uint_t to count things related to heap.
size_t is the correct type to use to count things related to the size of
the address space.  Using size_t (instead of mp_uint_t) is important for
the efficiency of ports that configure mp_uint_t to larger than the
machine word size.
2015-12-16 20:09:11 -05:00
Damien George
f7782f8082 py/gc: For finaliser, interpret a pointer into the heap as concrete obj. 2015-12-16 19:45:42 -05:00
Damien George
969e4bbe6a py/gc: Scan GC blocks as an array of pointers, not an array of objects.
The GC should search for pointers within the heap.  This patch makes a
difference when an object is larger than a pointer (eg 64-bit NaN
boxing).
2015-12-16 19:41:37 -05:00
Damien George
3911d5af32 py/modsys: Fix module globals table to use MP_ROM_QSTR. 2015-12-16 19:40:14 -05:00
danicampora
67a5bfc6d8 docs/library: Add network server example. 2015-12-16 22:35:14 +01:00
Damien George
0d7de08e06 unix: Change define logic of _DIRENT_HAVE_D_INO to match other macros. 2015-12-16 14:17:56 +00:00
pohmelie
64a909ef51 unix: Add FreeDos target 2015-12-16 13:28:12 +00:00
Damien George
a1528364b3 unix/modos: Fix silly bugs in ilistdir tuple creation. 2015-12-16 13:26:20 +00:00
Damien George
3386477b29 unix/modos: Allow to configure use of d_ino using _DIRENT_HAVE_D_INO.
Ports will need to #define _DIRENT_HAVE_D_INO (0) to disable d_ino use.
2015-12-16 13:21:09 +00:00
Paul Sokolovsky
be3ae9d13c stmhal/moduselect: Implement "oneshot polling" flag.
Similar to recently added feature in unix port: if event triggers for an
objects, its polling flags are automatically reset, so it won't be polled
until they are set again explicitly.
2015-12-16 11:07:58 +00:00
Tobias Badertscher
c5d8ffef58 stmhal: Extend SPI support to fully support all SPI devices on STM32F429.
This includes SPI4, SPI5 and SPI6.
2015-12-16 00:38:36 +00:00
Paul Sokolovsky
130fde8130 uos: Add errno() function to get/set errno value. 2015-12-16 00:38:26 +02:00
stijn
951fc7e993 msvc: Use new modmachine infrastructure per changes in f925165 2015-12-15 00:13:21 +02:00
Paul Sokolovsky
d874702fe1 unix/modos: Implement ilistdir().
ilistdir() returns iterator which yields triples of (name, type, ino)
where ino is inode number for entry's data, type of entry (file/dir/etc.),
and name of file/dir. listdir() can be easily implemented in terms of this
iterator (which is otherwise more efficient in terms of memory use and may
save expensive call to stat() for each returned entry).

CPython has os.scandir() which also returns an iterator, but it yields
more complex objects of DirEntry type. scandir() can also be easily
implemented in terms of ilistdir().
2015-12-14 23:48:12 +02:00
Paul Sokolovsky
1a1cceaf6f py/objpolyiter: Implement instance-polymorphic iterator type.
This allows to have single itertaor type for various internal iterator
types (save rodata space by not having repeating almost-empty type
structures). It works by looking "iternext" method stored in particular
object instance (should be first object field after "base").
2015-12-14 23:48:12 +02:00
Paul Sokolovsky
8fb255dc34 unix/modtime: Add strftime() function (only single argument is supported).
Following "don't rely on FFI for basic functionality" approach.
2015-12-14 00:10:57 +02:00
Paul Sokolovsky
2d11b17419 unix/moduselect: Make configurable with MICROPY_PY_USELECT. 2015-12-13 08:47:42 +02:00
Dave Hylands
f925165942 unix: Move modmachine into unix directory
This leaves behind the common functionality in extmod/machine_mem.c
which can be used by all ports.
2015-12-13 01:21:36 +02:00
Paul Sokolovsky
f2ed736b29 lib/utils/printf: Add vsnprintf alias for Clang.
Was reported to break MacOSX build.
2015-12-12 20:19:42 +02:00
Damien George
36ccdc952c stmhal: Make uart init use struct instead of array for parsing args.
This makes it much easier to understand which arg is which, less error
prone, and simpler to add a new arg.
2015-12-12 15:55:51 +00:00
Michael Buesch
17298af61e py/modmath: Add domain error checking to sqrt, log, log2, log10.
These functions will raise 'ValueError: math domain error' on invalid
input.
2015-12-12 15:12:54 +00:00
Damien George
f7c4f9a640 stmhal: For SPI config, use HW_SPIx_SCK instead of HW_ENABLE_SPIx.
Previously, SPI was configured by a board defining MICROPY_HW_ENABLE_SPIx
to 0 or 1.  Now, the board should define MICROPY_HW_SPIx_SCK, MISO, MOSI
and NSS.  This makes it the same as how I2C is configured.
2015-12-12 15:02:02 +00:00
Damien George
29e9db0c58 py: Fix compiler to handle lambdas used as default arguments.
Addresses issue #1709.
2015-12-12 13:42:51 +00:00
Paul Sokolovsky
bb7f5b5501 tools: Upgrade upip to 0.6.3.
Updated for _os -> uos builtin module rename.
2015-12-12 00:20:10 +02:00
Paul Sokolovsky
a6eff059b9 unix: Rename "_os" module to "uos" for consistency with baremetal ports. 2015-12-12 00:04:35 +02:00
stijn
967ceba5b7 msvc: Use different output directories depending on build type
This allows multiple versions (e.g. Debug/Release, x86/x64) of micropython.exe
to co-exist instead and also solves potential problems where msbuild does not
completely rebuild the output and/or pdb files when switching between builds,
which in turn can cause linker errors in dependent projects.

By default exe/map/... files go in windows/build/$(Configuration)$(Platform)

After each build micropython.exe is still copied from the above directory to
the windows directory though, as that is consistent with the other ports and
the test runner by default uses that location as well.

Also rename env.props -> path.props which is a clearer name,
and add ample documentation in the affected build files.

(also see discussion in #1538)
2015-12-11 23:42:30 +02:00
Paul Sokolovsky
c1481bb0ab unix/moduselect: Implement "one-shot" flag for poll.poll().
After an I/O event is triggered for fd, event flags are automatically reset,
so no further events are reported until new event flags are set. This is
an optimization for uasyncio, required to account for coroutine semantics:
each coroutine issues explicit read/write async call, and once that trigger,
no events should be reported to coroutine, unless it again explicitly
requests it. One-shot mode saves one linear scan over the poll array.
2015-12-11 23:36:37 +02:00
Sven Wegener
4651c4381e stmhal: add order-only dependency on build directory
Signed-off-by: Sven Wegener <sven.wegener@stealer.net>
2015-12-10 22:25:36 +00:00
Damien George
de2a2e296b tests: Add test for "not" of a user defined class. 2015-12-10 22:21:57 +00:00
Damien George
bdbe8c9ae2 py: Make UNARY_OP_NOT a first-class op, to agree with Py not semantics.
Fixes #1684 and makes "not" match Python semantics.  The code is also
simplified (the separate MP_BC_NOT opcode is removed) and the patch saves
68 bytes for bare-arm/ and 52 bytes for minimal/.

Previously "not x" was implemented as !mp_unary_op(x, MP_UNARY_OP_BOOL),
so any given object only needs to implement MP_UNARY_OP_BOOL (and the VM
had a special opcode to do the ! bit).

With this patch "not x" is implemented as mp_unary_op(x, MP_UNARY_OP_NOT),
but this operation is caught at the start of mp_unary_op and dispatched as
!mp_obj_is_true(x).  mp_obj_is_true has special logic to test for
truthness, and is the correct way to handle the not operation.
2015-12-10 22:19:48 +00:00
Henrik Sölver
e242b1785f py/emitinlinethumb: Add support for MRS instruction.
Only IPSR and BASEPRI special registers supported at the moment, but easy
to extend in the future.
2015-12-10 17:32:54 +00:00
Paul Sokolovsky
1f0aaece3a lib/utils/printf: Apply workaround for static linking with uclibc.
uclibc objects call __GI_vsnprintf().
2015-12-10 14:42:01 +02:00
Paul Sokolovsky
645045a799 py/mkrules.mk: Don't pass COPT to linker.
Oftentimes, libc, libm, etc. don't come compiled with CPU compressed code
option (Thumb, MIPS16, etc.), but we may still want to use such compressed
code for MicroPython itself.
2015-12-10 00:49:25 +02:00
Paul Sokolovsky
d288ae8eb9 unix/modtermios: DJGPP appears to have unicode-capable cc_t type.
At least it's defined as "unsiged". We don't try to support unicode still,
but at least apply workaround for DJGPP build.
2015-12-09 22:01:29 +02:00
Paul Sokolovsky
ce936edf62 unix/modtermios: Provide B57600 and B115200 constants only if defined. 2015-12-09 21:49:09 +02:00
Paul Sokolovsky
d4a874b81e extmod/moductypes: sizeof operation depends on layout type of structure.
Previously, sizeof() blindly assumed LAYOUT_NATIVE and tried to align
size even for packed LAYOUT_LITTLE_ENDIAN & LAYOUT_BIG_ENDIAN. As sizeof()
is implemented on a strucuture descriptor dictionary (not an structure
object), resolving this required passing layout type around.
2015-12-09 21:43:28 +02:00
Dave Hylands
5a4a2b1db3 extmod: Add test which demonstrates LITTLE_ENDIAN packing failure 2015-12-09 21:43:28 +02:00
Damien George
e84325bd1d py: Add mp_get_stream_raise to factor out check for stream methods. 2015-12-09 18:47:43 +00:00
Damien George
f54a96d6a2 stmhal/timer: Use mp_float_t instead of float.
This way mp_float_t can be changed to, eg, double.
2015-12-09 17:39:34 +00:00
Damien George
3ff259a262 py: Fix calling of parent classmethod from instance of subclass.
Addresses issue #1697.
2015-12-09 17:30:01 +00:00
neilh10
1be0fde45c stmhal: Enable two USB phys to be supported together.
This is refactoring to enable support for the two USB PHYs available on
some STM32F4 processors to be used at the same time. The F405/7 & F429
have two USB PHYs, others such as the F411 only have one PHY.

This has been tested separately on a pyb10 (USB_FS PHY) and F429DISC
(USB_HS PHY) to be able to invoke a REPL/USB.  I have modified a PYBV10
to support two PHYs.

The long term objective is to support a 2nd USB PHY to be brought up as a
USB HOST, and possibly a single USB PHY to be OTG.
2015-12-09 09:56:36 +00:00
Damien George
0891cf7d2d tests: Disable for_range.py test for native emitter (it requires yield). 2015-12-08 21:39:21 +00:00
Damien George
33ac0fd09f py: Don't try to optimise for+range when args are not simple expressions.
Addresses issue #1693.
2015-12-08 21:05:14 +00:00
Damien George
bbe2e22fcb tools: Fix pyboard.py to work under Python 3. 2015-12-08 12:55:28 +00:00
Peter Hinch
f4fcc14cfb tools: Add option to pyboard.py to wait for serial device to be ready.
Also prints a nicer error message if the serial connection could not be
established.
2015-12-08 11:10:09 +00:00
Paul Sokolovsky
946f870e3c py/misc.h: Include stdint.h only once (unconditionally at the top). 2015-12-08 02:23:58 +02:00
Paul Sokolovsky
3a309d93b1 unix/main: mp_verbose_flag available only if MICROPY_DEBUG_PRINTERS is true.
Not available for minimal build for example.
2015-12-07 20:09:20 +02:00
Paul Sokolovsky
9f001b09a8 py/misc.h: Include stdint.h, as large share of code now depends on it. 2015-12-07 20:08:07 +02:00
Paul Sokolovsky
55995869e5 tests/builtin_minmax: Make compatible with @native codegen. 2015-12-07 19:32:48 +02:00
Dave Hylands
f380904bd9 stmhal: Print exception information in nlr_jump_failed
Currently nlr_jump_fail prints that there was an uncaught exception
but nothing about the exception.
This patch causes nlr_jump_failed to try to print the exception.
Given that printf was called on the line above, I think that
the call to mp_obj_print_exception has about as much likelyhood
of succeeding as the printf does.
2015-12-07 17:21:51 +00:00
Paul Sokolovsky
36c6d2fa7d tests/builtin_minmax: Add testcase for lazy iterable (generator). 2015-12-07 18:59:18 +02:00
pohmelie
e23d5a64cf tests: Add min/max "default" agrument test 2015-12-07 18:56:25 +02:00
pohmelie
c6ee273410 py: Add min/max "default" keyword argument 2015-12-07 18:56:25 +02:00
pohmelie
354e688d8e py: Add MICROPY_PY_BUILTINS_MIN_MAX, disable for minimal ports. 2015-12-07 18:56:25 +02:00
Dave Hylands
acc208418b stmhal: Execute boot.py and main.py when formatting the file system.
When you use the USER button to perform a filesystem reset
at boot time then it wipes out the filesystem and creates
a new boot.py and main.py.  With this patch these files are
executed after formatting, ensuring that pyb and machine modules
get imported.
2015-12-07 15:11:42 +00:00
Paul Sokolovsky
2b7236d249 py: Make it easy to build without MICROPY_PY_BUILTINS_COMPLEX.
Automagically skip related modules.
2015-12-07 00:19:24 +02:00
Dave Hylands
519cef813e tools: Allow pyboard.py to work when boot.py prints things. 2015-12-06 21:45:10 +00:00
Paul Sokolovsky
cbc489dff5 tests: Actuall add feature check for complex type being available. 2015-12-06 15:13:26 +02:00
Paul Sokolovsky
eed2f36ae2 tests/run-tests: Allow to skip complex tests if it's not compiled in. 2015-12-06 14:57:31 +02:00
Paul Sokolovsky
082b12128d unix/moduselect: register(): Allow to call with duplicate file descriptor.
Per CPython docs, "Registering a file descriptor that’s already registered
is not an error, and has the same effect as registering the descriptor
exactly once."
https://docs.python.org/3/library/select.html#select.poll.register

That's somewhat ambiguous, what's implemented here is that if fd si not
yet registered, it is registered. Otherwise, the effect is equivalent to
modify() method.
2015-12-05 15:16:49 +02:00
Paul Sokolovsky
f2d532c404 py/modsys: Use MP_ROM_PTR() initializer for sys.modules.
Based on similar usage for sys.argv/sys.path.
2015-12-05 00:27:04 +02:00
Ryan Shaw
c03dd3b2f9 stmhal: Fix uart off by 1 circular buffer size. 2015-12-04 22:20:47 +00:00
Paul Sokolovsky
54a1d9ecb7 tests/extra_coverage: Update for sys.modules addition. 2015-12-05 00:13:29 +02:00
Paul Sokolovsky
1a1d11fa32 py/modsys: Implement sys.modules.
This for example will allow people to reload modules which didn't load
successfully (e.g. due to syntax error).
2015-12-05 00:13:29 +02:00
Paul Sokolovsky
5ae3ddcc9a unix/main: Check pending exception at the end of code block execution.
Usually this checking is done by VM on jump instructions, but for linear
sequences of instructions and builtin functions this won't happen. Particular
target of this change is long-running builtin functions like time.sleep().
2015-12-04 19:16:56 +02:00
Damien George
66b96822fb stmhal: Add option to free up TIM3 from USB VCP polling.
This is a hack to free up TIM3 so that it can be used by the user.
Instead we use the PVD irq to call the USB VCP polling function, and
trigger it from SysTick (so SysTick itself does not do any processing).

The feature is enabled for pyboard lite only, since it lacks timers.
2015-12-04 14:07:15 +00:00
Damien George
9aaf888b42 cc3200: Add __get_BASEPRI and __set_BASEPRI inline function definitions. 2015-12-04 12:13:57 +00:00
Damien George
dd7d2e0810 stmhal: Only use BASEPRI irq stuff if Cortex is M3 or higher. 2015-12-04 12:13:12 +00:00
Damien George
f7697ff393 stmhal: Add rtc.init() method to force RTC to re-initialise. 2015-12-04 12:05:05 +00:00
Damien George
f4c17378b3 stmhal: Protect SD card DMA transactions against USB MSC contention.
Consider the following scenario: SD card is being read by pyboard; USB
irq comes in for MSC read request; SD card needs to be read from within
USB irq while SD read is already ongoing.  Such contention needs to be
avoided.

This patch provides a simple solution, to raise the irq priority above
that of the USB irq during SD DMA transfers.  Pyboard and PC can now
read from the SD card at the same time (well, reads are interleaved).
2015-12-04 11:39:21 +00:00
Damien George
95c9cc8114 stmhal: Add raise_irq_pri and restore_irq_pri functions.
These can be used to disable only certain interrupts, ones at or above
the given priority value.
2015-12-04 11:38:23 +00:00
Paul Sokolovsky
add6f4556e extmod/moductypes: set_aligned(): Handle INT64/UINT64. 2015-12-04 00:59:08 +02:00
Damien George
7a99639cff py: Fix function calls that have positional and a star-arg-with-iterator.
Addresses issue #1678.
2015-12-03 17:59:49 +00:00
Paul Sokolovsky
b4eccfd02d py/mpconfig: Actually allow to override MICROPY_BYTES_PER_GC_BLOCK. 2015-12-03 01:58:25 +02:00
Paul Sokolovsky
30d0cf4885 unix/mpconfigport: Typo fix in comment. 2015-12-03 01:41:26 +02:00
Paul Sokolovsky
75feece208 py/gc: Make GC block size be configurable. 2015-12-03 01:40:52 +02:00
Dave Hylands
0077958ad0 stmhal: Put all DMA channel & stream definitions in dma.h 2015-12-02 22:55:57 +00:00
Paul Sokolovsky
d735278c9f unix/mpconfigport.h: For MICROPY_NO_ALLOCA=1, don't even include alloca.h. 2015-12-02 16:05:02 +02:00
Damien George
e9a684d741 stmhal: Add board config files for PYBv1.1 and PYBLITEv1.0. 2015-12-02 12:47:09 +00:00
fabien.lementec
e042f485ed py/mpprint: Printing of doubles is now supported (by uPy own routine). 2015-12-02 14:21:36 +02:00
Paul Sokolovsky
3376875bc8 unix/modtime: sleep(): Return early if KeyboardInterrupt is pending
As set by signal handler. This assumes that exception will be raised
somewhere else, which so far doesn't happen for single function call.
Still, it makes sense to handle that in some common place.
2015-12-02 00:37:25 +02:00
Damien George
0d9b450701 stmhal: Make uart.write() function correctly for timeout=0.
In non-blocking mode (timeout=0), uart.write() can now transmit all of its
data without raising an exception.  uart.read() also works correctly in
this mode.

As part of this patch, timout_char now has a minimum value which is long
enough to transfer 1 character.

Addresses issue #1533.
2015-11-30 17:29:52 +00:00
Ryan Shaw
f99491cbf7 stmhal: uart.any() function now returns number of bytes available. 2015-11-30 13:07:20 +00:00
Paul Sokolovsky
bd33aa313e unix/moduselect: Support growing of poll array. 2015-11-30 00:54:14 +02:00
danicampora
5d8164167e cc3200: Correct buffer offset in serial flash diskio module. 2015-11-29 18:34:51 +01:00
Damien George
b8cfb0d7b2 py: Add support for 64-bit NaN-boxing object model, on 32-bit machine.
To use, put the following in mpconfigport.h:

    #define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_D)
    #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
    typedef int64_t mp_int_t;
    typedef uint64_t mp_uint_t;
    #define UINT_FMT "%llu"
    #define INT_FMT "%lld"

Currently does not work with native emitter enabled.
2015-11-29 14:25:36 +00:00
Damien George
999cedb90f py: Wrap all obj-ptr conversions in MP_OBJ_TO_PTR/MP_OBJ_FROM_PTR.
This allows the mp_obj_t type to be configured to something other than a
pointer-sized primitive type.

This patch also includes additional changes to allow the code to compile
when sizeof(mp_uint_t) != sizeof(void*), such as using size_t instead of
mp_uint_t, and various casts.
2015-11-29 14:25:35 +00:00
Damien George
cbf7674025 py: Add MP_ROM_* macros and mp_rom_* types and use them. 2015-11-29 14:25:04 +00:00
Damien George
94fe6e523d py/gc: Move away from using mp_uint_t, instead use uintptr_t and size_t.
The GC works with concrete pointers and so the types should reflect this.
2015-11-29 14:25:04 +00:00
Damien George
254cfa6c31 py: Use uintptr_t instead of mp_uint_t in MP_TAGPTR_* macros. 2015-11-29 14:25:04 +00:00
Damien George
9f6976b74e py: Make mp_setup_code_state take concrete pointer for func arg. 2015-11-29 14:25:04 +00:00
Damien George
278f3592d4 extmod/modmachine: Use uintptr_t instead of mp_uint_t for address type. 2015-11-29 14:25:04 +00:00
Damien George
5d66b427e2 py/emit: Change type of arg of load_const_obj from void* to mp_obj_t. 2015-11-29 14:25:04 +00:00
Damien George
c3f64d9799 py: Change qstr_* functions to use size_t as the type for str len arg. 2015-11-29 14:25:04 +00:00
Damien George
4e7107a572 py: Change mp_print_strn_t func type to use size_t for the str length. 2015-11-29 14:25:04 +00:00
Paul Sokolovsky
fad7d9317b unix/modtime: Unbreak Windows build after changes to check select() result. 2015-11-29 14:31:58 +02:00
Paul Sokolovsky
0bb57bf5bf unix/modtime: sleep(): Automatically restart after receiving EINTR.
THis is required to deal well with signals, signals being the closest
analogue of hardware interrupts for POSIX. This is also CPython 3.5
compliant behavior (PEP 475).

The main problem implementing this is to figure out how much time was
spent in waiting so far/how much is remaining. It's well-known fact that
Linux updates select()'s timeout value when returning with EINTR to the
remaining wait time. Here's what POSIX-based standards say about this:
(http://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html):

"Upon successful completion, the select() function may modify the object
pointed to by the timeout argument."

I.e. it allows to modify timeout value, but doesn't say how exactly it is
modified. And actually, it allows such modification only "upon successful
completion", which returning with EINTR error hardly is.

POSIX also allows to request automatic EINTR restart for system calls using
sigaction call with SA_RESTART flag, but here's what the same document says
about it:

"If SA_RESTART has been set for the interrupting signal, it is
implementation-defined whether the function restarts or returns with
[EINTR]."

In other words, POSIX doesn't leave room for both portable and efficient
handling of this matter, so the code just allows to manually select
Linux-compatible behavior with MICROPY_SELECT_REMAINING_TIME option,
or otherwise will just raise OSError. When systems with non-Linux behavior
are found, they can be handled separately.
2015-11-29 14:21:06 +02:00
Paul Sokolovsky
9d0d6d3830 examples/accel_i2c.py: Switch to "machine" module. 2015-11-29 02:56:26 +02:00
Paul Sokolovsky
698a6a9d7d unix/moduselect: poll.register(): Reuse freed entries in poll array. 2015-11-29 00:06:51 +02:00
Paul Sokolovsky
19920e25f9 unix/moduselect: Fix bug in poll.poll() scanning loop. 2015-11-28 17:34:46 +02:00
Damien George
0786716c5a py/asmx86: Fix function definition to use int32_t instead of int. 2015-11-27 14:06:53 +00:00
Damien George
7a5a4fe271 unix/unix_mphal: Use size_t instead of mp_uint_t in stdout_tx_strn decls. 2015-11-27 14:03:53 +00:00
Damien George
88a9103b3c py/binary: Make use of MP_ALIGN. 2015-11-27 12:05:11 +00:00
Dave Hylands
3048433809 stmhal: Make stm.mem* support large integers.
With these you can now do things like:

stm.mem32[0x20000000] = 0x80000000

and read 32-bit values. You can also read all the way to the end
of memory using either stm.mem32[0xfffffffc] or stm.mem32[-4].

IRQs shouldn't use mem32 at all since they'd fail if the top 2 bits
weren't equal, so IRQs should be using 16-bit I/O.
2015-11-26 22:19:42 +00:00
Paul Sokolovsky
61e85a8ce0 pic16bit: Use global MICROPY_NO_ALLOCA setting. 2015-11-26 23:11:38 +02:00
Dave Hylands
061eb6fa6b stmahl: Fix usbd_conf.c for devices which don't have USB_HS at all.
The STMCube examples define both USE_USB_HS and USE_USB_HS_IN_FS when they
use the HS in FS mode.

The STM32F401 doesn't have a USB_HS at all, so the USB_OTG_HS instance
doesn't even exist.
2015-11-26 16:17:26 +00:00
Paul Sokolovsky
7dec35d7cc unix/modos: Remove duplicate level of #if MICROPY_PY_OS_STATVFS. 2015-11-26 17:46:26 +02:00
Dave Hylands
364bb61df3 stmhal: Allow make DEBUG=1 to build 2015-11-26 00:04:34 +00:00
Tobias Badertscher
8844d031e4 stmhal: Add support for the STM32F429I-DISCO kit by STMicro. 2015-11-25 23:53:26 +00:00
Paul Sokolovsky
f32020ef3d py/mpconfig.h: Allow to build without alloca() for ANSI C compliance.
Define MICROPY_NO_ALLOCA=1 and memory will be allocated from heap instead
and freed by garbage collection.
2015-11-25 23:24:51 +02:00
Paul Sokolovsky
f0fbab7ca7 extmod/fsusermount: Make configurable with MICROPY_FSUSERMOUNT. 2015-11-25 13:19:36 +02:00
Paul Sokolovsky
3a1bbcc2ef extmod: Move fsusermount.c from stmhal for cross-port reuse. 2015-11-25 13:19:36 +02:00
Dave Hylands
c8437f97ae stmhal: Increase the priority of UART IRQ.
The UARTs have no FIFOs, so if interrupts are disabled
for more than a character time (10 usec at 1 Mbit/sec)
then characters get dropped.

The overhead for handling a UART ISR is about 0.5 usec,
so even at baud rates of 1 Mbit/sec this only corresponds
to about 5% of the CPU. Lower baud rates will have less
of an impact.
2015-11-25 08:03:44 +00:00
Paul Sokolovsky
90202b4c0d esp8266/modesp: Implement flash_read(offset, size_bytes) function.
Based on vendor API documentation, untested on real hardware.
2015-11-24 23:29:26 +02:00
Paul Sokolovsky
ff8c4188f4 tests/run-tests: Improve robustness of REPL tests.
Unconditionally wait for MicroPython banner. On overloaded systems, when
using emulators, etc. initial executable startup may take more than 20ms.
2015-11-24 19:52:30 +02:00
Damien George
65888e2006 stmhal: Process storage idle tick handler in different slot to DMA. 2015-11-24 16:57:13 +00:00
Damien George
36bd10779c stmhal: In SysTick IRQ handler, make uwTick variable non-volatile.
uwTick can only change in the SysTick IRQ so this IRQ function does not
need to take special care with this variable.  It's important to make
this IRQ function as efficient as possible.
2015-11-24 16:23:54 +00:00
Damien George
e99e6c883d stmhal: Move flash storage idle tick handler from TIM3 to SysTick.
Using SysTick to do the counting and dispatch of the flash storage idle
handler is more efficient than requiring a dedicated hardware timer.
No new counter is needed, just the existing uwTick variable.  The
processing is not actually done in the SysTick IRQ, it is deferred to
the flash IRQ (which runs at lower priority).
2015-11-24 16:18:07 +00:00
Damien George
3cfb02f166 stmhal/irq: Set all IRQ subpriorities to 0, since they aren't used. 2015-11-24 15:56:33 +00:00
Damien George
18820471ae stmhal/irq: Add comment about SDIO priority being higher than DMA. 2015-11-24 15:51:07 +00:00
Damien George
22bd23114a stmhal: On SysTick IRQ, only process one DMA channel at a time.
This can be generalised if/when more processing is needed by SysTick.

Thanks to @chuckbook for the idea.
2015-11-24 15:44:16 +00:00
Damien George
9936aa3f87 stmhal: Save RAM and ROM by making SD DMA init structure const for tx/rx. 2015-11-24 15:44:16 +00:00
Damien George
522d454e34 stmhal: Small simplification of code to tickle DMA idle counter. 2015-11-24 15:44:16 +00:00
stijn
3baf6b5319 windows/py: Support 64bit mingw-w64 builds
- add mp_int_t/mp_uint_t typedefs in mpconfigport.h
- fix integer suffixes/formatting in mpconfig.h and mpz.h
- use MICROPY_NLR_SETJMP=1 in Makefile since the current nlrx64.S
  implementation causes segfaults in gc_free()
- update README
2015-11-24 17:34:14 +02:00
stijn
a58fa27c24 windows: Cleanup makefile
The BSD stuff is a copy from the unix makefile but at least there it
makes some sense, a windows makefile on BSD doesn't.
The -lmman flag is probably for mmap functions but there is no other build
support for it on windows so just that flag won't cut it anyway.
2015-11-24 17:34:14 +02:00
stijn
bf1570cb25 nlr: Use single preprocessor symbol to check if building on Windows 2015-11-24 17:34:14 +02:00
Dave Hylands
6edffd0df5 stmhal: Add dma support for sdcard.
This started out using IgorLektorovEpam work in PR #1389
and reworked it.
2015-11-24 09:37:25 +00:00
Dave Hylands
b677f03407 stmhal: Turn off DMA clocks when idle for 100 msec
Turning on each DMA block increases the current consumption
by about 8 mA. This code adds an idle timer for each DMA
block and turns off the clocks when no streams are in use
for 128 msec. Having a small timeout allows for improved
performance when back-to-back transfers are being performed.

The 128 msec is basically a guess.
2015-11-24 09:37:25 +00:00
Dave Hylands
9f5486c7e2 stmhal: Put IRQs into priority order.
- added some comments to explain the priority/sub-priority.
- adds an entry for SDIO (to be used in a later patch)
- increases DMA priority above USB so that DMA can be used
  for sdcard I/O when using USB Mass Storage.
2015-11-24 09:37:25 +00:00
Damien George
056abbcf31 stmhal: Fix unused variables when HW_CLK_LAST_FREQ not defined. 2015-11-23 23:52:09 +00:00
T S
86aa16bea6 stmhal: Implement delayed RTC initialization with LSI fallback.
If RTC is already running at boot then it's left alone.  Otherwise, RTC is
started at boot but startup function returns straight away.  RTC startup
is then finished the first time it is used.  Fallback to LSI if LSE fails
to start in a certain time.

Also included:
 MICROPY_HW_CLK_LAST_FREQ
        hold pyb.freq() parameters in RTC backup reg
 MICROPY_HW_RTC_USE_US
        option to present datetime sub-seconds in microseconds
 MICROPY_HW_RTC_USE_CALOUT
        option to enable RTC calibration output

CLK_LAST_FREQ and RTC_USE_CALOUT are enabled for PYBv1.0.
2015-11-23 23:23:07 +00:00
544 changed files with 22502 additions and 6138 deletions

View File

@@ -1,22 +1,31 @@
sudo: required
dist: trusty
language: c
compiler:
- gcc
before_script:
- sudo add-apt-repository -y ppa:fkrull/deadsnakes
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
# Extra CPython versions
# - sudo add-apt-repository -y ppa:fkrull/deadsnakes
# Extra gcc versions
# - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
- sudo add-apt-repository -y ppa:terry.guo/gcc-arm-embedded
- sudo apt-get update -qq
- sudo apt-get install -y python3.4 python3 gcc-4.7 gcc-multilib gcc-arm-none-eabi qemu-system mingw32
- sudo dpkg --add-architecture i386
- sudo apt-get update -qq || true
- sudo apt-get install -y python3 gcc-multilib gcc-arm-none-eabi pkg-config libffi-dev libffi-dev:i386 qemu-system mingw32
# For teensy build
- sudo apt-get install realpath
# For coverage testing
- sudo pip install cpp-coveralls
- gcc --version
- arm-none-eabi-gcc --version
- python3 --version
script:
- make -C minimal test
- make -C unix deplibs CC=gcc-4.7
- make -C unix CC=gcc-4.7
- make -C unix deplibs
- make -C unix
- make -C unix nanbox
- make -C bare-arm
- make -C qemu-arm test
- make -C stmhal
@@ -32,12 +41,12 @@ script:
#- (cd tests && MICROPY_CPYTHON3=python3.4 ./run-tests --emit native)
# run tests with coverage info
- make -C unix CC=gcc-4.7 coverage
- make -C unix coverage
- (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 --emit native)
after_success:
- (cd unix && coveralls --root .. --build-root . --gcov $(which gcov-4.7) --gcov-options '\-o build-coverage/' --include py --include extmod)
- (cd unix && coveralls --root .. --build-root . --gcov $(which gcov) --gcov-options '\-o build-coverage/' --include py --include extmod)
after_failure:
- (cd tests && for exp in *.exp; do testbase=$(basename $exp .exp); echo -e "\nFAILURE $testbase"; diff -u $testbase.exp $testbase.out; done)

View File

@@ -16,6 +16,7 @@ The MicroPython project
This is the MicroPython project, which aims to put an implementation
of Python 3.x on microcontrollers and small embedded systems.
You can find the official website at [micropython.org](http://www.micropython.org).
WARNING: this project is in beta stage and is subject to changes of the
code-base, including project-wide name changes and API changes.
@@ -129,7 +130,7 @@ The STM version
The "stmhal" port requires an ARM compiler, arm-none-eabi-gcc, and associated
bin-utils. For those using Arch Linux, you need arm-none-eabi-binutils and
arm-none-eabi-gcc packages from the AUR. Otherwise, try here:
arm-none-eabi-gcc packages. Otherwise, try here:
https://launchpad.net/gcc-arm-embedded
To build:
@@ -145,9 +146,7 @@ Then to flash the code via USB DFU to your device:
$ make deploy
You will need the dfu-util program, on Arch Linux it's dfu-util-git in the
AUR. If the above does not work it may be because you don't have the
correct permissions. Try then:
$ sudo dfu-util -a 0 -d 0483:df11 -D build-PYBV10/firmware.dfu
This will use the included `tools/pydfu.py` script. If flashing the firmware
does not work it may be because you don't have the correct permissions, and
need to use `sudo make deploy`.
See the README.md file in the stmhal/ directory for further details.

View File

@@ -45,7 +45,7 @@ mp_import_stat_t mp_import_stat(const char *path) {
return MP_IMPORT_STAT_NO_EXIST;
}
mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) {
mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);

View File

@@ -17,7 +17,7 @@ include ../py/mkenv.mk
CROSS_COMPILE ?= arm-none-eabi-
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -march=armv7e-m -mabi=aapcs -mcpu=cortex-m4 -msoft-float -mfloat-abi=soft -fsingle-precision-constant -Wdouble-promotion
CFLAGS = -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4)
CFLAGS = -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os
CFLAGS += -g -ffunction-sections -fdata-sections -fno-common -fsigned-char -mno-unaligned-access
CFLAGS += -Iboards/$(BOARD)

View File

@@ -24,7 +24,7 @@
* THE SOFTWARE.
*/
__stack_size__ = 3K; /* interrupts are handled within this stack */
__stack_size__ = 2K; /* interrupts are handled within this stack */
__min_heap_size__ = 8K;
MEMORY

View File

@@ -157,7 +157,7 @@ APP_LIB_SRC_C = $(addprefix lib/,\
APP_STM_SRC_C = $(addprefix stmhal/,\
bufhelper.c \
file.c \
builtin_open.c \
import.c \
input.c \
irq.c \
@@ -183,31 +183,10 @@ $(BUILD)/drivers/cc3100/src/driver.o: CFLAGS += -fno-strict-aliasing
# Check if we would like to debug the port code
ifeq ($(BTYPE), release)
# Optimize everything and define the NDEBUG flag
CFLAGS += -Os -DNDEBUG
CFLAGS += -DNDEBUG
else
ifeq ($(BTYPE), debug)
# Define the DEBUG flag
CFLAGS += -DDEBUG=DEBUG
# Optimize the stable sources only
$(BUILD)/extmod/%.o: CFLAGS += -Os
$(BUILD)/lib/%.o: CFLAGS += -Os
$(BUILD)/fatfs/src/%.o: CFLAGS += -Os
$(BUILD)/FreeRTOS/Source/%.o: CFLAGS += -Os
$(BUILD)/ftp/%.o: CFLAGS += -Os
$(BUILD)/hal/%.o: CFLAGS += -Os
$(BUILD)/misc/%.o: CFLAGS += -Os
$(BUILD)/mods/%.o: CFLAGS += -Os
$(BUILD)/py/%.o: CFLAGS += -Os
$(BUILD)/simplelink/%.o: CFLAGS += -Os
$(BUILD)/drivers/cc3100/%.o: CFLAGS += -Os
$(BUILD)/stmhal/%.o: CFLAGS += -Os
$(BUILD)/telnet/%.o: CFLAGS += -Os
$(BUILD)/util/%.o: CFLAGS += -Os
$(BUILD)/pins.o: CFLAGS += -Os
$(BUILD)/main.o: CFLAGS += -Os
$(BUILD)/mptask.o: CFLAGS += -Os
$(BUILD)/servertask.o: CFLAGS += -Os
CFLAGS += -DNDEBUG
else
$(error Invalid BTYPE specified)
endif

View File

@@ -1,11 +1,11 @@
Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,ADC
1,GP10,GP10,GP10,I2C0_SCL,,TIM3_PWM0,,,SD0_CLK,UART1_TX,,,,,TIM0_CC1,,,,
2,GP11,GP11,GP11,I2C0_SDA,,TIM3_PWM1,pXCLK(XVCLK),,SD0_CMD,UART1_RX,,,,,TIM1_CC0,I2S0_FS,,,
3,GP12,GP12,GP12,,,I2S0_CLK,pVS(VSYNC),I2C0_SCL,,UART0_TX,,,,,TIM1_CC1,,,,
4,GP13,GP13,GP13,,,,pHS(HSYNC),I2C0_SDA,,UART0_RX,,,,,TIM2_CC0,,,,
5,GP14,GP14,GP14,,,,pDATA8(CAM_D4),I2C0_SCL,,SPI0_CLK,,,,,TIM2_CC1,,,,
6,GP15,GP15,GP15,,,,pDATA9(CAM_D5),I2C0_SDA,,SPI0_MISO,SD0_DAT0,,,,,TIM3_CC0,,,
7,GP16,GP16,GP16,,,,pDATA10(CAM_D6),UART1_TX,,SPI0_MOSI,SD0_CLK,,,,,TIM3_CC1,,,
1,GP10,GP10,GP10,I2C0_SCL,,TIM3_PWM,,,SD0_CLK,UART1_TX,,,,,TIM0_CC,,,,
2,GP11,GP11,GP11,I2C0_SDA,,TIM3_PWM,pXCLK(XVCLK),,SD0_CMD,UART1_RX,,,,,TIM1_CC,I2S0_FS,,,
3,GP12,GP12,GP12,,,I2S0_CLK,pVS(VSYNC),I2C0_SCL,,UART0_TX,,,,,TIM1_CC,,,,
4,GP13,GP13,GP13,,,,pHS(HSYNC),I2C0_SDA,,UART0_RX,,,,,TIM2_CC,,,,
5,GP14,GP14,GP14,,,,pDATA8(CAM_D4),I2C0_SCL,,SPI0_CLK,,,,,TIM2_CC,,,,
6,GP15,GP15,GP15,,,,pDATA9(CAM_D5),I2C0_SDA,,SPI0_MISO,SD0_DAT0,,,,,TIM3_CC,,,
7,GP16,GP16,GP16,,,,pDATA10(CAM_D6),UART1_TX,,SPI0_MOSI,SD0_CLK,,,,,TIM3_CC,,,
8,GP17,GP17,GP17,,,,pDATA11(CAM_D7),UART1_RX,,SPI0_CS0,SD0_CMD,,,,,,,,
9,VDD_DIG1,VDD_DIG1,VDD_DIG1,,,,,,,,,,,,,,,,
10,VIN_IO1,VIN_IO1,VIN_IO1,,,,,,,,,,,,,,,,
@@ -13,13 +13,13 @@ Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF1
12,FLASH_SPI_DOUT,FLASH_SPI_DOUT,FLASH_SPI_DOUT,,,,,,,,,,,,,,,,
13,FLASH_SPI_DIN,FLASH_SPI_DIN,FLASH_SPI_DIN,,,,,,,,,,,,,,,,
14,FLASH_SPI_CS,FLASH_SPI_CS,FLASH_SPI_CS,,,,,,,,,,,,,,,,
15,GP22,GP22,GP22,,,,,TIM2_CC0,,I2S0_FS,,,,,,,,,
15,GP22,GP22,GP22,,,,,TIM2_CC,,I2S0_FS,,,,,,,,,
16,GP23,TDI,GP23,TDI,UART1_TX,,,,,,,I2C0_SCL,,,,,,,
17,GP24,TDO,GP24,TDO,UART1_RX,,TIM3_CC0,TIM0_PWM0,I2S0_FS,,,I2C0_SDA,,,,,,,
17,GP24,TDO,GP24,TDO,UART1_RX,,TIM3_CC,TIM0_PWM,I2S0_FS,,,I2C0_SDA,,,,,,,
18,GP28,GP28,GP28,,,,,,,,,,,,,,,,
19,TCK,TCK,,TCK,,,,,,,TIM1_PWM2,,,,,,,,
19,TCK,TCK,,TCK,,,,,,,TIM1_PWM,,,,,,,,
20,GP29,TMS,GP29,TMS,,,,,,,,,,,,,,,
21,GP25,SOP2,GP25,,I2S0_FS,,,,,,,TIM1_PWM0,,,,,,,
21,GP25,SOP2,GP25,,I2S0_FS,,,,,,,TIM1_PWM,,,,,,,
22,WLAN_XTAL_N,WLAN_XTAL_N,WLAN_XTAL_N,,,,,,,,,,,,,,,,
23,WLAN_XTAL_P,WLAN_XTAL_P,WLAN_XTAL_P,,,,,,,,,,,,,,,,
24,VDD_PLL,VDD_PLL,VDD_PLL,,,,,,,,,,,,,,,,
@@ -48,19 +48,19 @@ Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF1
47,VDD_ANA2,VDD_ANA2,VDD_ANA2,,,,,,,,,,,,,,,,
48,VDD_ANA1,VDD_ANA1,VDD_ANA1,,,,,,,,,,,,,,,,
49,VDD_RAM,VDD_RAM,VDD_RAM,,,,,,,,,,,,,,,,
50,GP0,GP0,GP0,,,UART0_RTS,I2S0_DAT0,,I2S0_DAT1,TIM0_CC0,,SPI0_CS0,UART1_RTS,,UART0_CTS,,,,
50,GP0,GP0,GP0,,,UART0_RTS,I2S0_DAT0,,I2S0_DAT1,TIM0_CC,,SPI0_CS0,UART1_RTS,,UART0_CTS,,,,
51,RTC_XTAL_P,RTC_XTAL_P,RTC_XTAL_P,,,,,,,,,,,,,,,,
52,RTC_XTAL_N,RTC_XTAL_N,GP32,,I2S0_CLK,,I2S0_DAT0,,UART0_RTS,,SPI0_MOSI,,,,,,,,
53,GP30,GP30,GP30,,I2S0_CLK,I2S0_FS,TIM2_CC1,,,SPI0_MISO,,UART0_TX,,,,,,,
53,GP30,GP30,GP30,,I2S0_CLK,I2S0_FS,TIM2_CC,,,SPI0_MISO,,UART0_TX,,,,,,,
54,VIN_IO2,VIN_IO2,VIN_IO2,,,,,,,,,,,,,,,,
55,GP1,GP1,GP1,,,UART0_TX,pCLK (PIXCLK),,UART1_TX,TIM0_CC1,,,,,,,,,
55,GP1,GP1,GP1,,,UART0_TX,pCLK (PIXCLK),,UART1_TX,TIM0_CC,,,,,,,,,
56,VDD_DIG2,VDD_DIG2,VDD_DIG2,,,,,,,,,,,,,,,,
57,GP2,GP2,GP2,,,UART0_RX,,,UART1_RX,TIM1_CC0,,,,,,,,,ADC0_CH0
57,GP2,GP2,GP2,,,UART0_RX,,,UART1_RX,TIM1_CC,,,,,,,,,ADC0_CH0
58,GP3,GP3,GP3,,,,pDATA7(CAM_D3),,UART1_TX,,,,,,,,,,ADC0_CH1
59,GP4,GP4,GP4,,,,pDATA6(CAM_D2),,UART1_RX,,,,,,,,,,ADC0_CH2
60,GP5,GP5,GP5,,,,pDATA5(CAM_D1),,I2S0_DAT1,TIM2_CC1,,,,,,,,,ADC0_CH3
61,GP6,GP6,GP6,,,UART1_CTS,pDATA4(CAM_D0),UART0_RTS,UART0_CTS,TIM3_CC0,,,,,,,,,
60,GP5,GP5,GP5,,,,pDATA5(CAM_D1),,I2S0_DAT1,TIM2_CC,,,,,,,,,ADC0_CH3
61,GP6,GP6,GP6,,,UART1_CTS,pDATA4(CAM_D0),UART0_RTS,UART0_CTS,TIM3_CC,,,,,,,,,
62,GP7,GP7,GP7,,,UART1_RTS,,,,,,,UART0_RTS,UART0_TX,,I2S0_CLK,,,
63,GP8,GP8,GP8,,,,,,SD0_IRQ,I2S0_FS,,,,,TIM3_CC0,,,,
64,GP9,GP9,GP9,,,TIM2_PWM1,,,SD0_DAT0,I2S0_DAT0,,,,,TIM0_CC0,,,,
63,GP8,GP8,GP8,,,,,,SD0_IRQ,I2S0_FS,,,,,TIM3_CC,,,,
64,GP9,GP9,GP9,,,TIM2_PWM,,,SD0_DAT0,I2S0_DAT0,,,,,TIM0_CC,,,,
65,GND_TAB,GND_TAB,GND_TAB,,,,,,,,,,,,,,,,
1 Pin Name Default AF0 AF1 AF2 AF3 AF4 AF5 AF6 AF7 AF8 AF9 AF10 AF11 AF12 AF13 AF14 AF15 ADC
2 1 GP10 GP10 GP10 I2C0_SCL TIM3_PWM0 TIM3_PWM SD0_CLK UART1_TX TIM0_CC1 TIM0_CC
3 2 GP11 GP11 GP11 I2C0_SDA TIM3_PWM1 TIM3_PWM pXCLK(XVCLK) SD0_CMD UART1_RX TIM1_CC0 TIM1_CC I2S0_FS
4 3 GP12 GP12 GP12 I2S0_CLK pVS(VSYNC) I2C0_SCL UART0_TX TIM1_CC1 TIM1_CC
5 4 GP13 GP13 GP13 pHS(HSYNC) I2C0_SDA UART0_RX TIM2_CC0 TIM2_CC
6 5 GP14 GP14 GP14 pDATA8(CAM_D4) I2C0_SCL SPI0_CLK TIM2_CC1 TIM2_CC
7 6 GP15 GP15 GP15 pDATA9(CAM_D5) I2C0_SDA SPI0_MISO SD0_DAT0 TIM3_CC0 TIM3_CC
8 7 GP16 GP16 GP16 pDATA10(CAM_D6) UART1_TX SPI0_MOSI SD0_CLK TIM3_CC1 TIM3_CC
9 8 GP17 GP17 GP17 pDATA11(CAM_D7) UART1_RX SPI0_CS0 SD0_CMD
10 9 VDD_DIG1 VDD_DIG1 VDD_DIG1
11 10 VIN_IO1 VIN_IO1 VIN_IO1
13 12 FLASH_SPI_DOUT FLASH_SPI_DOUT FLASH_SPI_DOUT
14 13 FLASH_SPI_DIN FLASH_SPI_DIN FLASH_SPI_DIN
15 14 FLASH_SPI_CS FLASH_SPI_CS FLASH_SPI_CS
16 15 GP22 GP22 GP22 TIM2_CC0 TIM2_CC I2S0_FS
17 16 GP23 TDI GP23 TDI UART1_TX I2C0_SCL
18 17 GP24 TDO GP24 TDO UART1_RX TIM3_CC0 TIM3_CC TIM0_PWM0 TIM0_PWM I2S0_FS I2C0_SDA
19 18 GP28 GP28 GP28
20 19 TCK TCK TCK TIM1_PWM2 TIM1_PWM
21 20 GP29 TMS GP29 TMS
22 21 GP25 SOP2 GP25 I2S0_FS TIM1_PWM0 TIM1_PWM
23 22 WLAN_XTAL_N WLAN_XTAL_N WLAN_XTAL_N
24 23 WLAN_XTAL_P WLAN_XTAL_P WLAN_XTAL_P
25 24 VDD_PLL VDD_PLL VDD_PLL
48 47 VDD_ANA2 VDD_ANA2 VDD_ANA2
49 48 VDD_ANA1 VDD_ANA1 VDD_ANA1
50 49 VDD_RAM VDD_RAM VDD_RAM
51 50 GP0 GP0 GP0 UART0_RTS I2S0_DAT0 I2S0_DAT1 TIM0_CC0 TIM0_CC SPI0_CS0 UART1_RTS UART0_CTS
52 51 RTC_XTAL_P RTC_XTAL_P RTC_XTAL_P
53 52 RTC_XTAL_N RTC_XTAL_N GP32 I2S0_CLK I2S0_DAT0 UART0_RTS SPI0_MOSI
54 53 GP30 GP30 GP30 I2S0_CLK I2S0_FS TIM2_CC1 TIM2_CC SPI0_MISO UART0_TX
55 54 VIN_IO2 VIN_IO2 VIN_IO2
56 55 GP1 GP1 GP1 UART0_TX pCLK (PIXCLK) UART1_TX TIM0_CC1 TIM0_CC
57 56 VDD_DIG2 VDD_DIG2 VDD_DIG2
58 57 GP2 GP2 GP2 UART0_RX UART1_RX TIM1_CC0 TIM1_CC ADC0_CH0
59 58 GP3 GP3 GP3 pDATA7(CAM_D3) UART1_TX ADC0_CH1
60 59 GP4 GP4 GP4 pDATA6(CAM_D2) UART1_RX ADC0_CH2
61 60 GP5 GP5 GP5 pDATA5(CAM_D1) I2S0_DAT1 TIM2_CC1 TIM2_CC ADC0_CH3
62 61 GP6 GP6 GP6 UART1_CTS pDATA4(CAM_D0) UART0_RTS UART0_CTS TIM3_CC0 TIM3_CC
63 62 GP7 GP7 GP7 UART1_RTS UART0_RTS UART0_TX I2S0_CLK
64 63 GP8 GP8 GP8 SD0_IRQ I2S0_FS TIM3_CC0 TIM3_CC
65 64 GP9 GP9 GP9 TIM2_PWM1 TIM2_PWM SD0_DAT0 I2S0_DAT0 TIM0_CC0 TIM0_CC
66 65 GND_TAB GND_TAB GND_TAB

View File

@@ -12,7 +12,7 @@ SUPPORTED_AFS = { 'UART': ('TX', 'RX', 'RTS', 'CTS'),
'SPI': ('CLK', 'MOSI', 'MISO', 'CS0'),
#'I2S': ('CLK', 'FS', 'DAT0', 'DAT1'),
'I2C': ('SDA', 'SCL'),
'TIM': ('PWM0', 'PWM1', 'CC0', 'CC1'),
'TIM': ('PWM'),
'SD': ('CLK', 'CMD', 'DAT0'),
'ADC': ('CH0', 'CH1', 'CH2', 'CH3')
}
@@ -44,6 +44,7 @@ class AF:
def print(self):
print (' AF({:16s}, {:4d}, {:8s}, {:4d}, {:8s}), // {}'.format(self.name, self.idx, self.fn, self.unit, self.type, self.name))
class Pin:
"""Holds the information associated with a pin."""
def __init__(self, name, port, gpio_bit, pin_num):

View File

@@ -414,7 +414,7 @@ int main (void) {
//*****************************************************************************
#include "py/qstr.h"
const byte *qstr_data(qstr q, mp_uint_t *len) {
const byte *qstr_data(qstr q, size_t *len) {
*len = 0;
return NULL;
}

View File

@@ -96,7 +96,7 @@ DRESULT sflash_disk_status(void) {
if (!sflash_init_done) {
return STA_NOINIT;
}
return 0;
return RES_OK;
}
DRESULT sflash_disk_read(BYTE *buff, DWORD sector, UINT count) {
@@ -126,7 +126,7 @@ DRESULT sflash_disk_read(BYTE *buff, DWORD sector, UINT count) {
}
// Copy the requested sector from the block cache
memcpy (buff, &sflash_block_cache[(secindex * SFLASH_SECTOR_SIZE)], SFLASH_SECTOR_SIZE);
buff += SFLASH_BLOCK_SIZE;
buff += SFLASH_SECTOR_SIZE;
}
return RES_OK;
}
@@ -161,7 +161,7 @@ DRESULT sflash_disk_write(const BYTE *buff, DWORD sector, UINT count) {
}
// Copy the input sector to the block cache
memcpy (&sflash_block_cache[(secindex * SFLASH_SECTOR_SIZE)], buff, SFLASH_SECTOR_SIZE);
buff += SFLASH_BLOCK_SIZE;
buff += SFLASH_SECTOR_SIZE;
sflash_cache_is_dirty = true;
} while (++index < count);

View File

@@ -67,6 +67,18 @@ static inline void __set_PRIMASK(uint32_t priMask) {
__asm volatile ("msr primask, %0" : : "r" (priMask) : "memory");
}
__attribute__(( always_inline ))
static inline uint32_t __get_BASEPRI(void) {
uint32_t result;
__asm volatile ("mrs %0, basepri" : "=r" (result));
return(result);
}
__attribute__(( always_inline ))
static inline void __set_BASEPRI(uint32_t value) {
__asm volatile ("msr basepri, %0" : : "r" (value) : "memory");
}
__attribute__(( always_inline ))
static inline void enable_irq(mp_uint_t state) {
__set_PRIMASK(state);

View File

@@ -196,6 +196,10 @@ void nlr_jump_fail(void *val) {
void mperror_enable_heartbeat (bool enable) {
if (enable) {
#ifndef BOOTLOADER
// configure the led again
pin_config ((pin_obj_t *)&MICROPY_SYS_LED_GPIO, PIN_MODE_0, GPIO_DIR_MODE_OUT, PIN_TYPE_STD, 0, PIN_STRENGTH_6MA);
#endif
mperror_heart_beat.enabled = true;
mperror_heart_beat.do_disable = false;
mperror_heartbeat_switch_off();

View File

@@ -165,7 +165,7 @@ STATIC mp_obj_t machine_wake_reason (void) {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_wake_reason_obj, machine_wake_reason);
STATIC const mp_map_elem_t machine_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_machine) },
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_umachine) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_reset), (mp_obj_t)&machine_reset_obj },
#ifdef DEBUG
@@ -212,6 +212,6 @@ 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_machine,
.name = MP_QSTR_umachine,
.globals = (mp_obj_dict_t*)&machine_module_globals,
};

View File

@@ -91,7 +91,7 @@ STATIC const mp_arg_t network_server_args[] = {
{ MP_QSTR_login, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
STATIC mp_obj_t network_server_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
STATIC mp_obj_t network_server_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
@@ -153,7 +153,7 @@ STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&mod_network_nic_type_wlan },
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
{ MP_OBJ_NEW_QSTR(MP_QSTR_server), (mp_obj_t)&network_server_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Server), (mp_obj_t)&network_server_type },
#endif
};
@@ -177,7 +177,7 @@ STATIC MP_DEFINE_CONST_DICT(network_server_locals_dict, network_server_locals_di
STATIC const mp_obj_type_t network_server_type = {
{ &mp_type_type },
.name = MP_QSTR_server,
.name = MP_QSTR_Server,
.make_new = network_server_make_new,
.locals_dict = (mp_obj_t)&network_server_locals_dict,
};

View File

@@ -37,7 +37,7 @@
#include "moduos.h"
#include "diskio.h"
#include "sflash_diskio.h"
#include "file.h"
#include "extmod/vfs_fat_file.h"
#include "random.h"
#include "mpexception.h"
#include "version.h"

View File

@@ -106,8 +106,10 @@ void modusocket_enter_sleep (void) {
}
}
// wait for any of the sockets to become ready...
sl_Select(maxfd + 1, &socketset, NULL, NULL, NULL);
if (maxfd > 0) {
// wait for any of the sockets to become ready...
sl_Select(maxfd + 1, &socketset, NULL, NULL, NULL);
}
}
void modusocket_close_all_user_sockets (void) {
@@ -125,7 +127,7 @@ void modusocket_close_all_user_sockets (void) {
// socket class
// constructor socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None)
STATIC mp_obj_t socket_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 4, false);
// create socket object

View File

@@ -33,6 +33,7 @@
#include "py/obj.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mphal.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
@@ -149,8 +150,8 @@ STATIC wlan_obj_t wlan_obj = {
.ssid = MICROPY_PORT_WLAN_AP_SSID,
.key = MICROPY_PORT_WLAN_AP_KEY,
.mac = {0},
.ssid_o = {0},
.bssid = {0},
//.ssid_o = {0},
//.bssid = {0},
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
.servers_enabled = false,
#endif
@@ -210,11 +211,11 @@ void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) {
{
case SL_WLAN_CONNECT_EVENT:
{
slWlanConnectAsyncResponse_t *pEventData = &pWlanEvent->EventData.STAandP2PModeWlanConnected;
//slWlanConnectAsyncResponse_t *pEventData = &pWlanEvent->EventData.STAandP2PModeWlanConnected;
// copy the new connection data
memcpy(wlan_obj.bssid, pEventData->bssid, SL_BSSID_LENGTH);
memcpy(wlan_obj.ssid_o, pEventData->ssid_name, pEventData->ssid_len);
wlan_obj.ssid_o[pEventData->ssid_len] = '\0';
//memcpy(wlan_obj.bssid, pEventData->bssid, SL_BSSID_LENGTH);
//memcpy(wlan_obj.ssid_o, pEventData->ssid_name, pEventData->ssid_len);
//wlan_obj.ssid_o[pEventData->ssid_len] = '\0';
SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION);
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
// we must reset the servers in case that the last connection
@@ -228,15 +229,16 @@ void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) {
CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED);
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
servers_reset();
servers_wlan_cycle_power();
#endif
break;
case SL_WLAN_STA_CONNECTED_EVENT:
{
slPeerInfoAsyncResponse_t *pEventData = &pWlanEvent->EventData.APModeStaConnected;
//slPeerInfoAsyncResponse_t *pEventData = &pWlanEvent->EventData.APModeStaConnected;
// get the mac address and name of the connected device
memcpy(wlan_obj.bssid, pEventData->mac, SL_BSSID_LENGTH);
memcpy(wlan_obj.ssid_o, pEventData->go_peer_device_name, pEventData->go_peer_device_name_len);
wlan_obj.ssid_o[pEventData->go_peer_device_name_len] = '\0';
//memcpy(wlan_obj.bssid, pEventData->mac, SL_BSSID_LENGTH);
//memcpy(wlan_obj.ssid_o, pEventData->go_peer_device_name, pEventData->go_peer_device_name_len);
//wlan_obj.ssid_o[pEventData->go_peer_device_name_len] = '\0';
SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION);
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
// we must reset the servers in case that the last connection
@@ -249,6 +251,7 @@ void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) {
CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION);
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
servers_reset();
servers_wlan_cycle_power();
#endif
break;
case SL_WLAN_P2P_DEV_FOUND_EVENT:
@@ -547,6 +550,12 @@ void wlan_set_current_time (uint32_t seconds_since_2000) {
sl_DevSet(SL_DEVICE_GENERAL_CONFIGURATION, SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME, sizeof(SlDateTime_t), (_u8 *)(&sl_datetime));
}
void wlan_off_on (void) {
// no need to lock the WLAN object on every API call since the servers and the MicroPtyhon
// task have the same priority
wlan_reenable(wlan_obj.mode);
}
//*****************************************************************************
// DEFINE STATIC FUNCTIONS
//*****************************************************************************
@@ -554,8 +563,8 @@ void wlan_set_current_time (uint32_t seconds_since_2000) {
STATIC void wlan_clear_data (void) {
CLR_STATUS_BIT_ALL(wlan_obj.status);
wlan_obj.ip = 0;
memset(wlan_obj.ssid_o, 0, sizeof(wlan_obj.ssid));
memset(wlan_obj.bssid, 0, sizeof(wlan_obj.bssid));
//memset(wlan_obj.ssid_o, 0, sizeof(wlan_obj.ssid));
//memset(wlan_obj.bssid, 0, sizeof(wlan_obj.bssid));
}
STATIC void wlan_reenable (SlWlanMode_t mode) {
@@ -821,7 +830,7 @@ STATIC const mp_arg_t wlan_init_args[] = {
{ MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_antenna, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ANTENNA_TYPE_INTERNAL} },
};
STATIC mp_obj_t wlan_make_new (mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);

View File

@@ -95,6 +95,7 @@ extern void wlan_get_mac (uint8_t *macAddress);
extern void wlan_get_ip (uint32_t *ip);
extern bool wlan_is_connected (void);
extern void wlan_set_current_time (uint32_t seconds_since_2000);
extern void wlan_off_on (void);
extern int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family);
extern int wlan_socket_socket(mod_network_socket_obj_t *s, int *_errno);

View File

@@ -140,7 +140,7 @@ STATIC const mp_arg_t pyb_adc_init_args[] = {
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 12} },
};
STATIC mp_obj_t adc_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);

View File

@@ -63,7 +63,7 @@ typedef struct _pyb_i2c_obj_t {
#define PYBI2C_MIN_BAUD_RATE_HZ (50000)
#define PYBI2C_MAX_BAUD_RATE_HZ (400000)
#define PYBI2C_TRANSC_TIMEOUT_MS (10)
#define PYBI2C_TRANSC_TIMEOUT_MS (20)
#define PYBI2C_TRANSAC_WAIT_DELAY_US (10)
#define PYBI2C_TIMEOUT_TO_COUNT(to_us, baud) (((baud) * to_us) / 16000000)
@@ -78,9 +78,13 @@ typedef struct _pyb_i2c_obj_t {
DECLARE PRIVATE DATA
******************************************************************************/
STATIC pyb_i2c_obj_t pyb_i2c_obj = {.baudrate = 0};
STATIC const mp_obj_t pyb_i2c_def_pin[2] = {&pin_GP13, &pin_GP23};
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC bool pyb_i2c_write(byte addr, byte *data, uint len, bool stop);
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
@@ -107,13 +111,13 @@ STATIC bool pyb_i2c_transaction(uint cmd) {
// Wait until the current byte has been transferred.
// Poll on the raw interrupt status.
while ((MAP_I2CMasterIntStatusEx(I2CA0_BASE, false) & (I2C_MASTER_INT_DATA | I2C_MASTER_INT_TIMEOUT)) == 0) {
// wait for a few microseconds
UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBI2C_TRANSAC_WAIT_DELAY_US));
timeout -= PYBI2C_TRANSAC_WAIT_DELAY_US;
if (timeout < 0) {
// the peripheral is not responding, so stop
return false;
}
// wait for a few microseconds
UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBI2C_TRANSAC_WAIT_DELAY_US));
timeout -= PYBI2C_TRANSAC_WAIT_DELAY_US;
}
// Check for any errors in the transfer
@@ -145,13 +149,22 @@ STATIC void pyb_i2c_check_init(pyb_i2c_obj_t *self) {
}
STATIC bool pyb_i2c_scan_device(byte devAddr) {
// Set I2C codec slave address
bool ret = false;
// Set the I2C slave address
MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, devAddr, true);
// Initiate the transfer.
RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_SINGLE_RECEIVE));
// Since this is a hack, send the stop bit anyway
if (pyb_i2c_transaction(I2C_MASTER_CMD_SINGLE_RECEIVE)) {
ret = true;
}
// Send the stop bit to cancel the read transaction
MAP_I2CMasterControl(I2CA0_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);
return true;
if (!ret) {
uint8_t data = 0;
if (pyb_i2c_write(devAddr, &data, sizeof(data), true)) {
ret = true;
}
}
return ret;
}
STATIC bool pyb_i2c_mem_addr_write (byte addr, byte *mem_addr, uint mem_addr_len) {
@@ -319,7 +332,7 @@ STATIC const mp_arg_t pyb_i2c_init_args[] = {
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} },
{ MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
@@ -365,7 +378,7 @@ STATIC mp_obj_t pyb_i2c_scan(mp_obj_t self_in) {
pyb_i2c_check_init(&pyb_i2c_obj);
mp_obj_t list = mp_obj_new_list(0, NULL);
for (uint addr = 1; addr <= 127; addr++) {
for (int i = 0; i < 7; i++) {
for (int i = 0; i < 3; i++) {
if (pyb_i2c_scan_device(addr)) {
mp_obj_list_append(list, mp_obj_new_int(addr));
break;

View File

@@ -60,7 +60,6 @@ DECLARE PRIVATE FUNCTIONS
STATIC pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name);
STATIC pin_obj_t *pin_find_pin_by_port_bit (const mp_obj_dict_t *named_pins, uint port, uint bit);
STATIC int8_t pin_obj_find_af (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type);
STATIC int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type);
STATIC void pin_free_af_from_pins (uint8_t fn, uint8_t unit, uint8_t type);
STATIC void pin_deassign (pin_obj_t* pin);
STATIC void pin_obj_configure (const pin_obj_t *self);
@@ -199,6 +198,14 @@ uint8_t pin_find_peripheral_type (const mp_obj_t pin, uint8_t fn, uint8_t unit)
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type) {
int8_t af = pin_obj_find_af(pin, fn, unit, type);
if (af < 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
return af;
}
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
@@ -231,14 +238,6 @@ STATIC int8_t pin_obj_find_af (const pin_obj_t* pin, uint8_t fn, uint8_t unit, u
return -1;
}
STATIC int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type) {
int8_t af = pin_obj_find_af(pin, fn, unit, type);
if (af < 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
return af;
}
STATIC void pin_free_af_from_pins (uint8_t fn, uint8_t unit, uint8_t type) {
mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)&pin_board_pins_locals_dict);
for (uint i = 0; i < named_map->used - 1; i++) {
@@ -248,7 +247,7 @@ STATIC void pin_free_af_from_pins (uint8_t fn, uint8_t unit, uint8_t type) {
// check if the pin supports the target af
int af = pin_obj_find_af(pin, fn, unit, type);
if (af > 0 && af == pin->af) {
// the pin is assigned to the target af, de-assign it
// the pin supports the target af, de-assign it
pin_deassign (pin);
}
}
@@ -648,7 +647,7 @@ STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
mp_printf(print, ", alt=%d)", alt);
}
STATIC mp_obj_t pin_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
STATIC mp_obj_t pin_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// Run an argument through the mapper and return the result.

View File

@@ -72,10 +72,7 @@ enum {
};
enum {
PIN_TYPE_TIM_PWM0 = 0,
PIN_TYPE_TIM_PWM1,
PIN_TYPE_TIM_CC0,
PIN_TYPE_TIM_CC1,
PIN_TYPE_TIM_PWM = 0,
};
enum {
@@ -139,5 +136,6 @@ pin_obj_t *pin_find(mp_obj_t user_obj);
void pin_assign_pins_af (mp_obj_t *pins, uint32_t n_pins, uint32_t pull, uint32_t fn, uint32_t unit);
uint8_t pin_find_peripheral_unit (const mp_obj_t pin, uint8_t fn, uint8_t type);
uint8_t pin_find_peripheral_type (const mp_obj_t pin, uint8_t fn, uint8_t unit);
int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type);;
#endif // PYBPIN_H_

View File

@@ -285,7 +285,7 @@ STATIC const mp_arg_t pyb_rtc_init_args[] = {
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_datetime, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
STATIC mp_obj_t pyb_rtc_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);

View File

@@ -64,7 +64,7 @@ STATIC const mp_obj_t pyb_sd_def_pin[3] = {&pin_GP10, &pin_GP11, &pin_GP15};
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC void pyb_sd_hw_init (pybsd_obj_t *self);
STATIC mp_obj_t pyb_sd_make_new (mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
STATIC mp_obj_t pyb_sd_make_new (const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
STATIC mp_obj_t pyb_sd_deinit (mp_obj_t self_in);
/******************************************************************************
@@ -123,7 +123,7 @@ STATIC const mp_arg_t pyb_sd_init_args[] = {
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_pins, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
STATIC mp_obj_t pyb_sd_make_new (mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
STATIC mp_obj_t pyb_sd_make_new (const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);

View File

@@ -231,7 +231,7 @@ static const mp_arg_t pyb_spi_init_args[] = {
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYBSPI_FIRST_BIT_MSB} },
{ MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
STATIC mp_obj_t pyb_spi_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);

View File

@@ -43,7 +43,10 @@
#include "interrupt.h"
#include "prcm.h"
#include "timer.h"
#include "pin.h"
#include "pybtimer.h"
#include "pybpin.h"
#include "pins.h"
#include "mpirq.h"
#include "pybsleep.h"
#include "mpexception.h"
@@ -55,30 +58,8 @@
/// Each timer consists of a counter that counts up at a certain rate. The rate
/// at which it counts is the peripheral clock frequency (in Hz) divided by the
/// timer prescaler. When the counter reaches the timer period it triggers an
/// event, and the counter resets back to zero. By using the callback method,
/// event, and the counter resets back to zero. By using the irq method,
/// the timer event can call a Python function.
///
/// Example usage to toggle an LED at a fixed frequency:
///
/// tim = pyb.Timer(4) # create a timer object using timer 4
/// tim.init(mode=Timer.PERIODIC) # initialize it in periodic mode
/// tim_ch = tim.channel(Timer.A, freq=2) # configure channel A at a frequency of 2Hz
/// tim_ch.callback(handler=lambda t:led.toggle()) # toggle a LED on every cycle of the timer
///
/// Further examples:
///
/// tim1 = pyb.Timer(2, mode=Timer.EVENT_COUNT) # initialize it capture mode
/// tim2 = pyb.Timer(1, mode=Timer.PWM) # initialize it in PWM mode
/// tim_ch = tim1.channel(Timer.A, freq=1, polarity=Timer.POSITIVE) # start the event counter with a frequency of 1Hz and triggered by positive edges
/// tim_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=50) # start the PWM on channel B with a 50% duty cycle
/// tim_ch.time() # get the current time in usec (can also be set)
/// tim_ch.freq(20) # set the frequency (can also get)
/// tim_ch.duty_cycle(30) # set the duty cycle to 30% (can also get)
/// tim_ch.duty_cycle(30, Timer.NEGATIVE) # set the duty cycle to 30% and change the polarity to negative
/// tim_ch.event_count() # get the number of captured events
/// tim_ch.event_time() # get the the time of the last captured event
/// tim_ch.period(2000000) # change the period to 2 seconds
///
/******************************************************************************
DECLARE PRIVATE CONSTANTS
@@ -87,6 +68,9 @@
#define PYBTIMER_POLARITY_POS (0x01)
#define PYBTIMER_POLARITY_NEG (0x02)
#define PYBTIMER_TIMEOUT_TRIGGER (0x01)
#define PYBTIMER_MATCH_TRIGGER (0x02)
#define PYBTIMER_SRC_FREQ_HZ HAL_FCPU_HZ
/******************************************************************************
@@ -108,8 +92,8 @@ typedef struct _pyb_timer_channel_obj_t {
uint32_t frequency;
uint32_t period;
uint16_t channel;
uint16_t duty_cycle;
uint8_t polarity;
uint8_t duty_cycle;
} pyb_timer_channel_obj_t;
/******************************************************************************
@@ -121,12 +105,14 @@ STATIC pyb_timer_obj_t pyb_timer_obj[PYBTIMER_NUM_TIMERS] = {{.timer = TIMERA0_B
{.timer = TIMERA2_BASE, .peripheral = PRCM_TIMERA2},
{.timer = TIMERA3_BASE, .peripheral = PRCM_TIMERA3}};
STATIC const mp_obj_type_t pyb_timer_channel_type;
STATIC const mp_obj_t pyb_timer_pwm_pin[8] = {&pin_GP24, MP_OBJ_NULL, &pin_GP25, MP_OBJ_NULL, MP_OBJ_NULL, &pin_GP9, &pin_GP10, &pin_GP11};
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
STATIC void timer_disable (pyb_timer_obj_t *tim);
STATIC void timer_channel_init (pyb_timer_channel_obj_t *ch);
STATIC void TIMER0AIntHandler(void);
STATIC void TIMER0BIntHandler(void);
STATIC void TIMER1AIntHandler(void);
@@ -177,6 +163,8 @@ STATIC void pyb_timer_channel_remove (pyb_timer_channel_obj_t *ch) {
pyb_timer_channel_obj_t *channel;
if ((channel = pyb_timer_channel_find(ch->timer->timer, ch->channel))) {
mp_obj_list_remove(&MP_STATE_PORT(pyb_timer_channel_obj_list), channel);
// unregister it with the sleep module
pyb_sleep_remove((const mp_obj_t)channel);
}
}
@@ -184,6 +172,8 @@ STATIC void pyb_timer_channel_add (pyb_timer_channel_obj_t *ch) {
// remove it in case it already exists
pyb_timer_channel_remove(ch);
mp_obj_list_append(&MP_STATE_PORT(pyb_timer_channel_obj_list), ch);
// register it with the sleep module
pyb_sleep_add((const mp_obj_t)ch, (WakeUpCB_t)timer_channel_init);
}
STATIC void timer_disable (pyb_timer_obj_t *tim) {
@@ -191,8 +181,15 @@ STATIC void timer_disable (pyb_timer_obj_t *tim) {
MAP_TimerDisable(tim->timer, TIMER_A | TIMER_B);
MAP_TimerIntDisable(tim->timer, tim->irq_trigger);
MAP_TimerIntClear(tim->timer, tim->irq_trigger);
pyb_timer_channel_obj_t *ch;
// disable its channels
if ((ch = pyb_timer_channel_find (tim->timer, TIMER_A))) {
pyb_sleep_remove(ch);
}
if ((ch = pyb_timer_channel_find (tim->timer, TIMER_B))) {
pyb_sleep_remove(ch);
}
MAP_PRCMPeripheralClkDisable(tim->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
memset(&pyb_timer_obj[tim->id], 0, sizeof(pyb_timer_obj_t));
}
// computes prescaler period and match value so timer triggers at freq-Hz
@@ -205,20 +202,23 @@ STATIC uint32_t compute_prescaler_period_and_match_value(pyb_timer_channel_obj_t
if (period_c == 0) {
goto error;
}
prescaler = period_c >> 16;
prescaler = period_c >> 16; // The prescaler is an extension of the timer counter
*period_out = period_c;
if (prescaler > 0xFF && maxcount == 0xFFFF) {
goto error;
}
// check limit values for the duty cycle
if (ch->duty_cycle == 0) {
*match_out = period_c - 1;
}
else {
*match_out = period_c - ((period_c * ch->duty_cycle) / 100);
}
if ((ch->timer->config & 0x0F) == TIMER_CFG_A_PWM && (*match_out > 0xFFFF)) {
goto error;
} else {
if (period_c > 0xFFFF) {
uint32_t match = (period_c * 100) / 10000;
*match_out = period_c - ((match * ch->duty_cycle) / 100);
} else {
*match_out = period_c - ((period_c * ch->duty_cycle) / 10000);
}
}
return prescaler;
@@ -250,17 +250,7 @@ STATIC void timer_channel_init (pyb_timer_channel_obj_t *ch) {
MAP_TimerControlLevel(ch->timer->timer, ch->channel, (ch->polarity == PYBTIMER_POLARITY_NEG) ? true : false);
// set the match value (which is simply the duty cycle translated to ticks)
MAP_TimerMatchSet(ch->timer->timer, ch->channel, match);
}
// configure the event edge type if we are in such mode
else if ((ch->timer->config & 0x0F) == TIMER_CFG_A_CAP_COUNT || (ch->timer->config & 0x0F) == TIMER_CFG_A_CAP_TIME) {
uint32_t polarity = TIMER_EVENT_BOTH_EDGES;
if (ch->polarity == PYBTIMER_POLARITY_POS) {
polarity = TIMER_EVENT_POS_EDGE;
}
else if (ch->polarity == PYBTIMER_POLARITY_NEG) {
polarity = TIMER_EVENT_NEG_EDGE;
}
MAP_TimerControlEvent(ch->timer->timer, ch->channel, polarity);
MAP_TimerPrescaleMatchSet(ch->timer->timer, ch->channel, match >> 16);
}
#ifdef DEBUG
@@ -282,37 +272,18 @@ STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_
// timer mode
qstr mode_qst = MP_QSTR_PWM;
switch(mode) {
case TIMER_CFG_A_ONE_SHOT:
case TIMER_CFG_A_ONE_SHOT_UP:
mode_qst = MP_QSTR_ONE_SHOT;
break;
case TIMER_CFG_A_PERIODIC:
case TIMER_CFG_A_PERIODIC_UP:
mode_qst = MP_QSTR_PERIODIC;
break;
case TIMER_CFG_A_CAP_COUNT:
mode_qst = MP_QSTR_EDGE_COUNT;
break;
case TIMER_CFG_A_CAP_TIME:
mode_qst = MP_QSTR_EDGE_TIME;
break;
default:
break;
}
mp_printf(print, "<Timer%u, mode=Timer.%q>", (tim->id + 1), mode_qst);
mp_printf(print, "Timer(%u, mode=Timer.%q)", tim->id, mode_qst);
}
/// \method init(mode, *, width)
/// Initialise the timer. Initialisation must give the desired mode
/// and an optional timer width
///
/// tim.init(mode=Timer.ONE_SHOT, width=32) # one shot mode
/// tim.init(mode=Timer.PERIODIC) # configure in free running periodic mode
/// split into two 16-bit independent timers
///
/// Keyword arguments:
///
/// - `width` - specifies the width of the timer. Default is 32 bit mode. When in 16 bit mode
/// the timer is splitted into 2 independent channels.
///
STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, },
@@ -325,8 +296,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, mp_uint_t n_args, co
// check the mode
uint32_t _mode = args[0].u_int;
if (_mode != TIMER_CFG_A_ONE_SHOT && _mode != TIMER_CFG_A_PERIODIC && _mode != TIMER_CFG_A_CAP_COUNT &&
_mode != TIMER_CFG_A_CAP_TIME && _mode != TIMER_CFG_A_PWM) {
if (_mode != TIMER_CFG_A_ONE_SHOT_UP && _mode != TIMER_CFG_A_PERIODIC_UP && _mode != TIMER_CFG_A_PWM) {
goto error;
}
@@ -336,7 +306,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, mp_uint_t n_args, co
}
bool is16bit = (args[1].u_int == 16);
if (!is16bit && (_mode != TIMER_CFG_A_ONE_SHOT && _mode != TIMER_CFG_A_PERIODIC)) {
if (!is16bit && _mode == TIMER_CFG_A_PWM) {
// 32-bit mode is only available when in free running modes
goto error;
}
@@ -352,16 +322,12 @@ error:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
/// \classmethod \constructor(id, ...)
/// Construct a new timer object of the given id. If additional
/// arguments are given, then the timer is initialised by `init(...)`.
/// `id` can be 1 to 4
STATIC mp_obj_t pyb_timer_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// create a new Timer object
int32_t timer_idx = mp_obj_get_int(args[0]) - 1;
int32_t timer_idx = mp_obj_get_int(args[0]);
if (timer_idx < 0 || timer_idx > (PYBTIMER_NUM_TIMERS - 1)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
@@ -379,15 +345,11 @@ STATIC mp_obj_t pyb_timer_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
return (mp_obj_t)tim;
}
// \method init()
/// initializes the timer
STATIC mp_obj_t pyb_timer_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
return pyb_timer_init_helper(args[0], n_args - 1, args + 1, kw_args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_init_obj, 1, pyb_timer_init);
// \method deinit()
/// disables the timer
STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in) {
pyb_timer_obj_t *self = self_in;
timer_disable(self);
@@ -395,24 +357,6 @@ STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit);
/// \method channel(channel, *, freq, period, polarity, duty_cycle)
/// Initialise the timer channel. Initialization requires at least a frequency param. With no
/// extra params given besides the channel id, the channel is returned with the previous configuration
/// os 'None', if it hasn't been initialized before.
///
/// tim1.channel(Timer.A, freq=1000) # set channel A frequency to 1KHz
/// tim2.channel(Timer.AB, freq=10) # both channels (because it's a 32 bit timer) combined to create a 10Hz timer
///
/// when initialiazing the channel of a 32-bit timer, channel ID MUST be = Timer.AB
///
/// Keyword arguments:
///
/// - `freq` - specifies the frequency in Hz.
/// - `period` - specifies the period in microseconds.
/// - `polarity` - in PWM specifies the polarity of the pulse. In capture mode specifies the edge to capture.
/// in order to capture on both negative and positive edges, make it = Timer.POSITIVE | Timer.NEGATIVE.
/// - `duty_cycle` - sets the duty cycle value
///
STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
@@ -474,12 +418,21 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
ch->frequency = args[0].u_int;
ch->period = args[1].u_int;
ch->polarity = args[2].u_int;
ch->duty_cycle = MIN(100, MAX(0, args[3].u_int));
ch->duty_cycle = MIN(10000, MAX(0, args[3].u_int));
timer_channel_init(ch);
// register it with the sleep module
pyb_sleep_add ((const mp_obj_t)ch, (WakeUpCB_t)timer_channel_init);
// assign the pin
if ((ch->timer->config & 0x0F) == TIMER_CFG_A_PWM) {
uint32_t ch_idx = (ch->channel == TIMER_A) ? 0 : 1;
// use the default pin if available
mp_obj_t pin_o = (mp_obj_t)pyb_timer_pwm_pin[(ch->timer->id * 2) + ch_idx];
if (pin_o != MP_OBJ_NULL) {
pin_obj_t *pin = pin_find(pin_o);
pin_config (pin, pin_find_af_index(pin, PIN_FN_TIM, ch->timer->id, PIN_TYPE_TIM_PWM),
0, PIN_TYPE_STD, -1, PIN_STRENGTH_4MA);
}
}
// add the timer to the list
pyb_timer_channel_add(ch);
@@ -500,13 +453,13 @@ STATIC const mp_map_elem_t pyb_timer_locals_dict_table[] = {
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_A), MP_OBJ_NEW_SMALL_INT(TIMER_A) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_B), MP_OBJ_NEW_SMALL_INT(TIMER_B) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ONE_SHOT), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_ONE_SHOT) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PERIODIC), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_PERIODIC) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_EDGE_COUNT), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_CAP_COUNT) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_EDGE_TIME), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_CAP_TIME) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ONE_SHOT), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_ONE_SHOT_UP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PERIODIC), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_PERIODIC_UP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PWM), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_PWM) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_POSITIVE), MP_OBJ_NEW_SMALL_INT(PYBTIMER_POLARITY_POS) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_NEGATIVE), MP_OBJ_NEW_SMALL_INT(PYBTIMER_POLARITY_NEG) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_TIMEOUT), MP_OBJ_NEW_SMALL_INT(PYBTIMER_TIMEOUT_TRIGGER) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MATCH), MP_OBJ_NEW_SMALL_INT(PYBTIMER_MATCH_TRIGGER) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table);
@@ -528,7 +481,6 @@ STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods = {
STATIC void TIMERGenericIntHandler(uint32_t timer, uint16_t channel) {
pyb_timer_channel_obj_t *self;
uint32_t status;
if ((self = pyb_timer_channel_find(timer, channel))) {
status = MAP_TimerIntStatus(self->timer->timer, true) & self->channel;
MAP_TimerIntClear(self->timer->timer, status);
@@ -574,16 +526,14 @@ STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, m
// timer channel
if (ch->channel == TIMER_A) {
ch_id = "A";
}
else if (ch->channel == TIMER_B) {
} else if (ch->channel == TIMER_B) {
ch_id = "B";
}
mp_printf(print, "<%q %s, timer=%u, %q=%u", MP_QSTR_TimerChannel,
ch_id, (ch->timer->id + 1), MP_QSTR_freq, ch->frequency);
mp_printf(print, "timer.channel(Timer.%s, %q=%u", ch_id, MP_QSTR_freq, ch->frequency);
uint32_t mode = ch->timer->config & 0xFF;
if (mode == TIMER_CFG_A_CAP_COUNT || mode == TIMER_CFG_A_CAP_TIME || mode == TIMER_CFG_A_PWM) {
if (mode == TIMER_CFG_A_PWM) {
mp_printf(print, ", %q=Timer.", MP_QSTR_polarity);
switch (ch->polarity) {
case PYBTIMER_POLARITY_POS:
@@ -596,15 +546,11 @@ STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, m
mp_printf(print, "BOTH");
break;
}
if (mode == TIMER_CFG_A_PWM) {
mp_printf(print, ", %q=%u", MP_QSTR_duty_cycle, ch->duty_cycle);
}
mp_printf(print, ", %q=%u.%02u", MP_QSTR_duty_cycle, ch->duty_cycle / 100, ch->duty_cycle % 100);
}
mp_printf(print, ">");
mp_printf(print, ")");
}
/// \method freq([value])
/// get or set the frequency of the timer channel
STATIC mp_obj_t pyb_timer_channel_freq(mp_uint_t n_args, const mp_obj_t *args) {
pyb_timer_channel_obj_t *ch = args[0];
if (n_args == 1) {
@@ -624,8 +570,6 @@ STATIC mp_obj_t pyb_timer_channel_freq(mp_uint_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_freq_obj, 1, 2, pyb_timer_channel_freq);
/// \method period([value])
/// get or set the period of the timer channel in microseconds
STATIC mp_obj_t pyb_timer_channel_period(mp_uint_t n_args, const mp_obj_t *args) {
pyb_timer_channel_obj_t *ch = args[0];
if (n_args == 1) {
@@ -645,74 +589,17 @@ STATIC mp_obj_t pyb_timer_channel_period(mp_uint_t n_args, const mp_obj_t *args)
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_period_obj, 1, 2, pyb_timer_channel_period);
/// \method time([value])
/// get or set the value of the timer channel in microseconds
STATIC mp_obj_t pyb_timer_channel_time(mp_uint_t n_args, const mp_obj_t *args) {
pyb_timer_channel_obj_t *ch = args[0];
uint32_t value;
// calculate the period, the prescaler and the match value
uint32_t period_c;
uint32_t match;
(void)compute_prescaler_period_and_match_value(ch, &period_c, &match);
if (n_args == 1) {
// get
value = (ch->channel == TIMER_B) ? HWREG(ch->timer->timer + TIMER_O_TBV) : HWREG(ch->timer->timer + TIMER_O_TAV);
// return the current timer value in microseconds
// substract value to period since we are always operating in count-down mode
uint32_t time_t = (1000 * (period_c - value)) / period_c;
return mp_obj_new_int((time_t * 1000) / ch->frequency);
}
else {
// set
value = (mp_obj_get_int(args[1]) * ((ch->frequency * period_c) / 1000)) / 1000;
if ((value > 0xFFFF) && (ch->timer->config & TIMER_CFG_SPLIT_PAIR)) {
// this exceeds the maximum value of a 16-bit timer
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
// write period minus value since we are always operating in count-down mode
TimerValueSet (ch->timer->timer, ch->channel, (period_c - value));
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_time_obj, 1, 2, pyb_timer_channel_time);
/// \method event_count()
/// get the number of events triggered by the configured edge
STATIC mp_obj_t pyb_timer_channel_event_count(mp_obj_t self_in) {
pyb_timer_channel_obj_t *ch = self_in;
return mp_obj_new_int(MAP_TimerValueGet(ch->timer->timer, ch->channel == (TIMER_A | TIMER_B) ? TIMER_A : ch->channel));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_channel_event_count_obj, pyb_timer_channel_event_count);
/// \method event_time()
/// get the time at which the last event was triggered
STATIC mp_obj_t pyb_timer_channel_event_time(mp_obj_t self_in) {
pyb_timer_channel_obj_t *ch = self_in;
// calculate the period, the prescaler and the match value
uint32_t period_c;
uint32_t match;
(void)compute_prescaler_period_and_match_value(ch, &period_c, &match);
uint32_t value = MAP_TimerValueGet(ch->timer->timer, ch->channel == (TIMER_A | TIMER_B) ? TIMER_A : ch->channel);
// substract value to period since we are always operating in count-down mode
uint32_t time_t = (1000 * (period_c - value)) / period_c;
return mp_obj_new_int((time_t * 1000) / ch->frequency);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_channel_event_time_obj, pyb_timer_channel_event_time);
/// \method duty_cycle()
/// get or set the duty cycle when in PWM mode
STATIC mp_obj_t pyb_timer_channel_duty_cycle(mp_uint_t n_args, const mp_obj_t *args) {
pyb_timer_channel_obj_t *ch = args[0];
if (n_args == 1) {
// get
return mp_obj_new_int(ch->duty_cycle);
}
else {
} else {
// duty cycle must be converted from percentage to ticks
// calculate the period, the prescaler and the match value
uint32_t period_c;
uint32_t match;
ch->duty_cycle = MIN(100, MAX(0, mp_obj_get_int(args[1])));
ch->duty_cycle = MIN(10000, MAX(0, mp_obj_get_int(args[1])));
compute_prescaler_period_and_match_value(ch, &period_c, &match);
if (n_args == 3) {
// set the new polarity if requested
@@ -720,13 +607,12 @@ STATIC mp_obj_t pyb_timer_channel_duty_cycle(mp_uint_t n_args, const mp_obj_t *a
MAP_TimerControlLevel(ch->timer->timer, ch->channel, (ch->polarity == PYBTIMER_POLARITY_NEG) ? true : false);
}
MAP_TimerMatchSet(ch->timer->timer, ch->channel, match);
MAP_TimerPrescaleMatchSet(ch->timer->timer, ch->channel, match >> 16);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_duty_cycle_obj, 1, 3, pyb_timer_channel_duty_cycle);
/// \method irq(trigger, priority, handler, wake)
/// FIXME triggers!!
STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_arg_val_t args[mp_irq_INIT_NUM_ARGS];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args);
@@ -741,25 +627,28 @@ STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_t n_args, const mp_obj_t *pos_arg
goto invalid_args;
}
// get the trigger
uint trigger = mp_obj_get_int(args[0].u_obj);
// disable the callback first
pyb_timer_channel_irq_disable(ch);
uint8_t shift = (ch->channel == TIMER_B) ? 8 : 0;
uint32_t _config = (ch->channel == TIMER_B) ? ((ch->timer->config & TIMER_B) >> 8) : (ch->timer->config & TIMER_A);
switch (_config) {
case TIMER_CFG_A_ONE_SHOT:
case TIMER_CFG_A_PERIODIC:
case TIMER_CFG_A_ONE_SHOT_UP:
case TIMER_CFG_A_PERIODIC_UP:
ch->timer->irq_trigger |= TIMER_TIMA_TIMEOUT << shift;
break;
case TIMER_CFG_A_CAP_COUNT:
ch->timer->irq_trigger |= TIMER_CAPA_MATCH << shift;
break;
case TIMER_CFG_A_CAP_TIME:
ch->timer->irq_trigger |= TIMER_CAPA_EVENT << shift;
if (trigger != PYBTIMER_TIMEOUT_TRIGGER) {
goto invalid_args;
}
break;
case TIMER_CFG_A_PWM:
// special case for the PWM match interrupt
ch->timer->irq_trigger |= ((ch->channel & TIMER_A) == TIMER_A) ? TIMER_TIMA_MATCH : TIMER_TIMB_MATCH;
if (trigger != PYBTIMER_MATCH_TRIGGER) {
goto invalid_args;
}
break;
default:
break;
@@ -831,9 +720,6 @@ STATIC const mp_map_elem_t pyb_timer_channel_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&pyb_timer_channel_freq_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_period), (mp_obj_t)&pyb_timer_channel_period_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&pyb_timer_channel_time_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_event_count), (mp_obj_t)&pyb_timer_channel_event_count_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_event_time), (mp_obj_t)&pyb_timer_channel_event_time_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_duty_cycle), (mp_obj_t)&pyb_timer_channel_duty_cycle_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_timer_channel_irq_obj },
};

View File

@@ -443,7 +443,7 @@ STATIC const mp_arg_t pyb_uart_init_args[] = {
{ MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);

View File

@@ -92,7 +92,7 @@ STATIC const mp_arg_t pyb_wdt_init_args[] = {
{ MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_timeout, MP_ARG_INT, {.u_int = 5000} }, // 5 s
};
STATIC mp_obj_t pyb_wdt_make_new (mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
STATIC mp_obj_t pyb_wdt_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
// check the arguments
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);

View File

@@ -70,6 +70,7 @@
#define MICROPY_FATFS_REENTRANT (1)
#define MICROPY_FATFS_TIMEOUT (2500)
#define MICROPY_FATFS_SYNC_T SemaphoreHandle_t
#define MICROPY_FSUSERMOUNT_ADHOC (1)
#define MICROPY_STREAMS_NON_BLOCK (1)
#define MICROPY_MODULE_WEAK_LINKS (1)
@@ -134,7 +135,7 @@ extern const struct _mp_obj_module_t mp_module_ubinascii;
extern const struct _mp_obj_module_t mp_module_ussl;
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&machine_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_umachine), (mp_obj_t)&machine_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_wipy), (mp_obj_t)&wipy_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&mp_module_uos }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&mp_module_utime }, \
@@ -154,10 +155,11 @@ extern const struct _mp_obj_module_t mp_module_ussl;
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&mp_module_usocket }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_binascii), (mp_obj_t)&mp_module_ubinascii }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_ssl), (mp_obj_t)&mp_module_ussl }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&machine_module }, \
// extra constants
#define MICROPY_PORT_CONSTANTS \
{ MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&machine_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_umachine), (mp_obj_t)&machine_module }, \
// vm state and root pointers for the gc
#define MP_STATE_PORT MP_STATE_VM

View File

@@ -26,7 +26,7 @@
*/
// for machine module
Q(machine)
Q(umachine)
#ifdef DEBUG
Q(info)
#endif
@@ -279,7 +279,7 @@ Q(CERT_REQUIRED)
// for network class
Q(network)
Q(server)
Q(Server)
Q(init)
Q(deinit)
Q(login)
@@ -365,18 +365,15 @@ Q(width)
Q(channel)
Q(polarity)
Q(duty_cycle)
Q(time)
Q(event_count)
Q(event_time)
Q(A)
Q(B)
Q(ONE_SHOT)
Q(PERIODIC)
Q(EDGE_COUNT)
Q(EDGE_TIME)
Q(PWM)
Q(POSITIVE)
Q(NEGATIVE)
Q(TIMEOUT)
Q(MATCH)
// for uhashlib module
//Q(uhashlib)

View File

@@ -39,7 +39,8 @@
#include "pybwdt.h"
#include "modusocket.h"
#include "mpexception.h"
#include "modnetwork.h"
#include "modwlan.h"
/******************************************************************************
DEFINE PRIVATE TYPES
@@ -50,13 +51,13 @@ typedef struct {
bool do_disable;
bool do_enable;
bool do_reset;
bool do_wlan_cycle_power;
} servers_data_t;
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
static servers_data_t servers_data = {.timeout = SERVERS_DEF_TIMEOUT_MS, .enabled = false, .do_disable = false,
.do_enable = false, .do_reset = false};
static servers_data_t servers_data = {.timeout = SERVERS_DEF_TIMEOUT_MS};
static volatile bool sleep_sockets = false;
/******************************************************************************
@@ -120,10 +121,16 @@ void TASK_Servers (void *pvParameters) {
}
if (sleep_sockets) {
sleep_sockets = false;
pybwdt_srv_sleeping(true);
modusocket_enter_sleep();
pybwdt_srv_sleeping(false);
mp_hal_delay_ms(SERVERS_CYCLE_TIME_MS * 2);
if (servers_data.do_wlan_cycle_power) {
servers_data.do_wlan_cycle_power = false;
wlan_off_on();
}
sleep_sockets = false;
}
// set the alive flag for the wdt
@@ -152,6 +159,10 @@ void servers_reset (void) {
servers_data.do_reset = true;
}
void servers_wlan_cycle_power (void) {
servers_data.do_wlan_cycle_power = true;
}
bool servers_are_enabled (void) {
return servers_data.enabled;
}

View File

@@ -62,6 +62,7 @@ extern void TASK_Servers (void *pvParameters);
extern void servers_start (void);
extern void servers_stop (void);
extern void servers_reset (void);
extern void servers_wlan_cycle_power (void);
extern bool servers_are_enabled (void);
extern void servers_close_socket (int16_t *sd);
extern void servers_set_login (char *user, char *pass);

View File

@@ -27,6 +27,6 @@
#ifndef VERSION_H_
#define VERSION_H_
#define WIPY_SW_VERSION_NUMBER "1.1.1"
#define WIPY_SW_VERSION_NUMBER "1.2.0"
#endif /* VERSION_H_ */

View File

@@ -21,6 +21,40 @@ import os
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# Work out the port to generate the docs for
from collections import OrderedDict
micropy_port = os.getenv('MICROPY_PORT') or 'pyboard'
tags.add('port_' + micropy_port)
ports = OrderedDict((
('unix', ('unix', 'unix')),
('pyboard', ('pyboard', 'the pyboard')),
('wipy', ('WiPy', 'the WiPy')),
('esp8266', ('ESP8266', 'the ESP8266')),
))
# The members of the html_context dict are available inside topindex.html
micropy_version = os.getenv('MICROPY_VERSION') or 'latest'
micropy_all_versions = (os.getenv('MICROPY_ALL_VERSIONS') or 'latest').split(',')
url_pattern = '%s/en/%%s/%%s' % (os.getenv('MICROPY_URL_PREFIX') or '/',)
html_context = {
'port':micropy_port,
'port_short_name':ports[micropy_port][0],
'port_name':ports[micropy_port][1],
'port_version':micropy_version,
'all_ports':[
(port_name[0], url_pattern % (micropy_version, port_id))
for port_id, port_name in ports.items()
],
'all_versions':[
(ver, url_pattern % (ver, micropy_port))
for ver in micropy_all_versions
],
}
# Specify a custom master document based on the port name
master_doc = micropy_port + '_' + 'index'
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
@@ -51,16 +85,16 @@ source_suffix = '.rst'
# General information about the project.
project = 'MicroPython'
copyright = '2014, Damien P. George'
copyright = '2014-2016, Damien P. George and contributors'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '1.5'
version = '1.7'
# The full version, including alpha/beta/rc tags.
release = '1.5.1'
release = '1.7'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -213,8 +247,8 @@ latex_elements = {
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
('index', 'MicroPython.tex', 'MicroPython Documentation',
'Damien P. George', 'manual'),
(master_doc, 'MicroPython.tex', 'MicroPython Documentation',
'Damien P. George and contributors', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
@@ -244,7 +278,7 @@ latex_documents = [
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'micropython', 'MicroPython Documentation',
['Damien P. George'], 1),
['Damien P. George and contributors'], 1),
]
# If true, show URL addresses after external links.
@@ -257,8 +291,8 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'MicroPython', 'MicroPython Documentation',
'Damien P. George', 'MicroPython', 'One line description of project.',
(master_doc, 'MicroPython', 'MicroPython Documentation',
'Damien P. George and contributors', 'MicroPython', 'One line description of project.',
'Miscellaneous'),
]
@@ -278,33 +312,8 @@ texinfo_documents = [
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'http://docs.python.org/': None}
# Work out the port to generate the docs for
from collections import OrderedDict
micropy_port = os.getenv('MICROPY_PORT') or 'pyboard'
tags.add('port_' + micropy_port)
ports = OrderedDict((
("unix", "unix"),
("pyboard", "the pyboard"),
("wipy", "the WiPy"),
("esp8266", "esp8266"),
))
# The members of the html_context dict are available inside topindex.html
url_prefix = os.getenv('MICROPY_URL_PREFIX') or '/'
html_context = {
'port':micropy_port,
'port_name':ports[micropy_port],
'all_ports':[(n, url_prefix + p) for p, n in ports.items()],
}
# Append the other ports' specific folders/files to the exclude pattern
exclude_patterns.extend([port + '*' for port in ports if port != micropy_port])
# Exclude pyb module if the port is the WiPy
if micropy_port == 'wipy':
exclude_patterns.append('library/pyb*')
else: # exclude machine
exclude_patterns.append('library/machine*')
# Specify a custom master document based on the port name
master_doc = micropy_port + '_' + 'index'

254
docs/esp8266/quickref.rst Normal file
View File

@@ -0,0 +1,254 @@
.. _quickref:
Quick reference for the ESP8266
===============================
.. image:: https://learn.adafruit.com/system/assets/assets/000/028/689/medium640/adafruit_products_pinoutstop.jpg
:alt: Adafruit Feather HUZZAH board
:width: 640px
The Adafruit Feather HUZZAH board (image attribution: Adafruit).
General board control
---------------------
The MicroPython REPL is on UART0 (GPIO1=TX, GPIO3=RX) at baudrate 115200.
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::
import machine
machine.freq() # get the current frequency of the CPU
machine.freq(160000000) # set the CPU frequency to 160 MHz
The ``esp`` module::
import esp
esp.osdebug(None) # turn off vendor O/S debugging messages
esp.osdebug(0) # redirect vendor O/S debugging messages to UART(0)
Networking
----------
The ``network`` module::
import network
wlan = network.WLAN(network.STA_IF) # create station interface
wlan.active(True) # activate the interface
wlan.scan() # scan for access points
wlan.isconnected() # check if the station is connected to an AP
wlan.connect('essid', 'password') # connect to an AP
wlan.mac() # get the interface's MAC adddress
wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses
ap = network.WLAN(network.AP_IF) # create access-point interface
ap.active(True) # activate the interface
ap.config(essid='ESP-AP') # set the ESSID of the access point
A useful function for connecting to your local WiFi network is::
def do_connect():
import network
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print('connecting to network...')
wlan.connect('essid', 'password')
while not wlan.isconnected():
pass
print('network config:', wlan.ifconfig())
Once the network is established the ``socket`` module can be used
to create and use TCP/UDP sockets as usual.
Delay and timing
----------------
Use the ``time`` 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 millisecond counter
delta = time.ticks_diff(start, time.ticks_ms()) # compute time difference
Timers
------
Virtual (RTOS-based) timers are supported. Use the ``machine.Timer`` class
with timer ID of -1::
from machine import Timer
tim = Timer(-1)
tim.init(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(1))
tim.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(2))
The period is in milliseconds.
Pins and GPIO
-------------
Use the ``machine.Pin`` class::
from machine import Pin
p0 = Pin(0, Pin.OUT) # create output pin on GPIO0
p0.high() # set pin to high
p0.low() # set pin to low
p0.value(1) # set pin to high
p2 = Pin(2, Pin.IN) # create input pin on GPIO2
print(p2.value()) # get value, 0 or 1
p4 = Pin(4, Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
p5 = Pin(5, Pin.OUT, value=1) # set pin high on creation
Available pins are: 0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16, which correspond
to the actual GPIO pin numbers of ESP8266 chip. Note that many end-user
boards use their own adhoc pin numbering (marked e.g. D0, D1, ...). As
MicroPython supports different boards and modules, physical pin numbering
was chosen as the lowest common denominator. For mapping between board
logical pins and physical chip pins, consult your board documentation.
Note that Pin(1) and Pin(3) are REPL UART TX and RX respectively.
Also note that Pin(16) is a special pin (used for wakeup from deepsleep
mode) and may be not available for use with higher-level classes like
``Neopixel``.
PWM (pulse width modulation)
----------------------------
PWM can be enabled on all pins except Pin(16). There is a single frequency
for all channels, with range between 1 and 1000 (measured in Hz). The duty
cycle is between 0 and 1023 inclusive.
Use the ``machine.PWM`` class::
from machine import Pin, PWM
pwm0 = PWM(Pin(0)) # create PWM object from a pin
pwm0.freq() # get current frequency
pwm0.freq(1000) # set frequency
pwm0.duty() # get current duty cycle
pwm0.duty(200) # set duty cycle
pwm0.deinit() # turn off PWM on the pin
pwm2 = PWM(Pin(2), freq=500, duty=512) # create and configure in one go
ADC (analog to digital conversion)
----------------------------------
ADC is available on a dedicated pin.
Note that input voltages on the ADC pin must be between 0v and 1.0v.
Use the ``machine.ADC`` class::
from machine import ADC
adc = ADC(0) # create ADC object on ADC pin
adc.read() # read value, 0-1024
SPI bus
-------
The SPI driver is implemented in software 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.init(baudrate=200000) # set the baudrate
spi.read(10) # read 10 bytes on MISO
spi.read(10, 0xff) # read 10 bytes while outputing 0xff on MOSI
buf = bytearray(50) # create a buffer
spi.readinto(buf) # read into the given buffer (reads 50 bytes in this case)
spi.readinto(buf, 0xff) # read into the given buffer and output 0xff on MOSI
spi.write(b'12345') # write 5 bytes on MOSI
buf = bytearray(4) # create a buffer
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
I2C bus
-------
The I2C driver is implemented in software and works on all pins::
from machine import Pin, I2C
# construct an I2C bus
i2c = I2C(scl=Pin(5), sda=Pin(4), freq=100000)
i2c.readfrom(0x3a, 4) # read 4 bytes from slave device with address 0x3a
i2c.writeto(0x3a, '12') # write '12' to slave device with address 0x3a
buf = bytearray(10) # create a buffer with 10 bytes
i2c.writeto(0x3a, buf) # write the given buffer to the slave
i2c.readfrom(0x3a, 4, stop=False) # don't send a stop bit after reading
i2c.writeto(0x3a, buf, stop=False) # don't send a stop bit after writing
OneWire driver
--------------
The OneWire driver is implemented in software and works on all pins::
from machine import Pin
import onewire
ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12
ow.scan() # return a list of devices on the bus
ow.reset() # reset the bus
ow.read_byte() # read a byte
ow.read_bytes(5) # read 5 bytes
ow.write_byte(0x12) # write a byte on the bus
ow.write_bytes('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::
import time
ds = onewire.DS18B20(ow)
roms = ds.scan()
ds.start_measure()
time.sleep_ms(750)
for rom in roms:
print(ds.get_temp(rom))
Be sure to put a 4.7k pull-up resistor on the data line.
NeoPixel driver
---------------
Use the ``neopixel`` module::
from machine import Pin
from neopixel import NeoPixel
pin = Pin(0, Pin.OUT) # set GPIO0 to output to drive NeoPixels
np = NeoPixel(pin, 8) # create NeoPixel driver on GPIO0 for 8 pixels
np[0] = (255, 255, 255) # set the first pixel to white
np.write() # write data to all pixels
r, g, b = np[0] # get first pixel colour
import neopixel
neopixel.demo(np) # run a demo
For low-level driving of a NeoPixel::
import esp
esp.neopixel_write(pin, grb_buf, is800khz)

View File

@@ -3,6 +3,7 @@ MicroPython documentation contents
.. toctree::
esp8266/quickref.rst
library/index.rst
reference/index.rst
license.rst

View File

@@ -3,6 +3,7 @@ MicroPython documentation and references
.. toctree::
esp8266/quickref.rst
library/index.rst
license.rst
esp8266_contents.rst

View File

@@ -10,46 +10,6 @@ The ``esp`` module contains specific functions related to the ESP8266 module.
Functions
---------
.. function:: mac([address])
Get or set the network interface's MAC address.
If the ``address`` parameter is provided, sets the address to its value. If
the function is called wihout parameters, returns the current address.
.. function:: getaddrinfo((hostname, port, lambda))
Initiate resolving of the given hostname.
When the hostname is resolved, the provided ``lambda`` callback will be
called with two arguments, first being the hostname being resolved,
second a tuple with information about that hostname.
.. function:: wifi_mode([mode])
Get or set the wireless network operating mode.
If the ``mode`` parameter is provided, sets the mode to its value. If
the function is called wihout parameters, returns the current mode.
The possible modes are defined as constants:
* ``STA_MODE`` -- station mode,
* ``AP_MODE`` -- software access point mode,
* ``STA_AP_MODE`` -- mixed station and software access point mode.
.. function:: phy_mode([mode])
Get or set the network interface mode.
If the ``mode`` parameter is provided, sets the mode to its value. If
the function is called wihout parameters, returns the current mode.
The possible modes are defined as constants:
* ``MODE_11B`` -- IEEE 802.11b,
* ``MODE_11G`` -- IEEE 802.11g,
* ``MODE_11N`` -- IEEE 802.11n.
.. function:: sleep_type([sleep_type])
Get or set the sleep type.
@@ -79,11 +39,3 @@ Functions
.. function:: flash_id()
Read the device ID of the flash memory.
Classes
-------
.. toctree::
:maxdepth: 1
esp.socket.rst

View File

@@ -55,6 +55,17 @@ For additional libraries, please download them from the `micropython-lib reposit
sys.rst
time.rst
.. only:: port_esp8266
.. toctree::
:maxdepth: 1
gc.rst
math.rst
struct.rst
sys.rst
time.rst
Python micro-libraries
----------------------
@@ -85,6 +96,19 @@ library.
usocket.rst
uzlib.rst
.. only:: port_esp8266
.. toctree::
:maxdepth: 1
ubinascii.rst
uctypes.rst
uhashlib.rst
uheapq.rst
ujson.rst
ure.rst
uzlib.rst
.. only:: port_pyboard
Libraries specific to the pyboard
@@ -134,6 +158,6 @@ library.
.. toctree::
:maxdepth: 2
pyb.rst
esp.rst
network.rst
esp.rst
machine.rst

View File

@@ -24,7 +24,7 @@ Usage Model:
print(pin.id())
pin_int = Pin('GP10', mode=Pin.IN, pull=Pin.PULL_DOWN)
pin_int.irq(mode=Pin.IRQ_RISING, handler=pincb)
pin_int.irq(trigger=Pin.IRQ_RISING, handler=pincb)
# the callback can be triggered manually
pin_int.irq()()
# to disable the callback

View File

@@ -5,55 +5,49 @@ class Timer -- control internal timers
.. only:: port_wipy
.. note::
Contrary with the rest of the API, timer IDs start at 1, not a t zero. This is because
the ``Timer`` API is still provisional. A new MicroPython wide API will come soon.
Timers can be used for a great variety of tasks, calling a function periodically,
counting events, and generating a PWM signal are among the most common use cases.
Each timer consists of 2 16-bit channels and this channels can be tied together to
form 1 32-bit timer. The operating mode needs to be configured per timer, but then
Each timer consists of two 16-bit channels and this channels can be tied together to
form one 32-bit timer. The operating mode needs to be configured per timer, but then
the period (or the frequency) can be independently configured on each channel.
By using the callback method, the timer event can call a Python function.
Example usage to toggle an LED at a fixed frequency::
from machine import Timer
tim = Timer(4) # create a timer object using timer 4
from machine import Pin
led = Pin('GP16', mode=Pin.OUT) # enable GP16 as output to drive the LED
tim = Timer(3) # create a timer object using timer 3
tim.init(mode=Timer.PERIODIC) # initialize it in periodic mode
tim_ch = tim.channel(Timer.A, freq=2) # configure channel A at a frequency of 2Hz
tim_ch.callback(handler=lambda t:led.toggle()) # toggle a LED on every cycle of the timer
tim_ch = tim.channel(Timer.A, freq=5) # configure channel A at a frequency of 5Hz
tim_ch.irq(handler=lambda t:led.toggle(), trigger=Timer.TIMEOUT) # toggle a LED on every cycle of the timer
Example using named function for the callback::
from machine import Timer
tim = Timer(1, mode=Timer.PERIODIC)
tim_a = tim.channel(Timer.A, freq=1000)
from machine import Pin
tim = Timer(1, mode=Timer.PERIODIC, width=32)
tim_a = tim.channel(Timer.A | Timer.B, freq=1) # 1 Hz frequency requires a 32 bit timer
led = Pin('GPIO2', mode=Pin.OUT)
led = Pin('GP16', mode=Pin.OUT) # enable GP16 as output to drive the LED
def tick(timer): # we will receive the timer object when being called
print(timer.time()) # show current timer's time value (is microseconds)
global led
led.toggle() # toggle the LED
tim_a.callback(handler=tick)
tim_a.irq(handler=tick, trigger=Timer.TIMEOUT) # create the interrupt
Further examples::
from machine import Timer
tim1 = Timer(2, mode=Timer.EVENT_COUNT) # initialize it capture mode
tim2 = Timer(1, mode=Timer.PWM) # initialize it in PWM mode
tim_ch = tim1.channel(Timer.A, freq=1, polarity=Timer.POSITIVE) # start the event counter with a frequency of 1Hz and triggered by positive edges
tim_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=50) # start the PWM on channel B with a 50% duty cycle
tim_ch.time() # get the current time in usec (can also be set)
tim_ch.freq(20) # set the frequency (can also get)
tim_ch.duty_cycle(30) # set the duty cycle to 30% (can also get)
tim_ch.duty_cycle(30, Timer.NEGATIVE) # set the duty cycle to 30% and change the polarity to negative
tim_ch.event_count() # get the number of captured events
tim_ch.event_time() # get the the time of the last captured event
tim_ch.period(2000000) # change the period to 2 seconds
tim1 = Timer(1, mode=Timer.ONE_SHOT) # initialize it in one shot mode
tim2 = Timer(2, mode=Timer.PWM) # initialize it in PWM mode
tim1_ch = tim1.channel(Timer.A, freq=10, polarity=Timer.POSITIVE) # start the event counter with a frequency of 10Hz and triggered by positive edges
tim2_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=5000) # start the PWM on channel B with a 50% duty cycle
tim2_ch.freq(20) # set the frequency (can also get)
tim2_ch.duty_cycle(3010) # set the duty cycle to 30.1% (can also get)
tim2_ch.duty_cycle(3020, Timer.NEGATIVE) # set the duty cycle to 30.2% and change the polarity to negative
tim2_ch.period(2000000) # change the period to 2 seconds
.. note::
@@ -69,9 +63,7 @@ Constructors
.. only:: port_wipy
Construct a new timer object of the given id. If additional
arguments are given, then the timer is initialised by ``init(...)``.
``id`` can be 1 to 4.
Construct a new timer object of the given id. ``id`` can take values from 0 to 3.
Methods
@@ -94,10 +86,9 @@ Methods
period of the channel expires.
- ``Timer.PERIODIC`` - The timer runs periodically at the configured
frequency of the channel.
- ``Timer.EDGE_TIME`` - Meaure the time pin level changes.
- ``Timer.EDGE_COUNT`` - Count the number of pin level changes.
- ``Timer.PWM`` - Output a PWM signal on a pin.
- ``width`` must be either 16 or 32 (bits). For really low frequencies <= ~1Hz
- ``width`` must be either 16 or 32 (bits). For really low frequencies < 5Hz
(or large periods), 32-bit timers should be used. 32-bit mode is only available
for ``ONE_SHOT`` AND ``PERIODIC`` modes.
@@ -112,7 +103,7 @@ Methods
If only a channel identifier passed, then a previously initialized channel
object is returned (or ``None`` if there is no previous channel).
Othwerwise, a TimerChannel object is initialized and returned.
The operating mode is is the one configured to the Timer object that was used to
@@ -130,12 +121,22 @@ Methods
Either ``freq`` or ``period`` must be given, never both.
- ``polarity`` this is applicable for:
- ``PWM``, defines the polarity of the duty cycle
- ``EDGE_TIME`` and ``EDGE_COUNT``, defines the polarity of the pin level change to detect.
To detect both rising and falling edges, make ``polarity=Timer.POSITIVE | Timer.NEGATIVE``.
- ``duty_cycle`` only applicable to ``PWM``. It's a percentage (0-100)
- ``polarity`` this is applicable for ``PWM``, and defines the polarity of the duty cycle
- ``duty_cycle`` only applicable to ``PWM``. It's a percentage (0.00-100.00). Since the WiPy
doesn't support floating point numbers the duty cycle must be specified in the range 0-10000,
where 10000 would represent 100.00, 5050 represents 50.50, and so on.
.. note::
When the channel is in PWM mode, the corresponding pin is assigned automatically, therefore
there's no need to assign the alternate function of the pin via the ``Pin`` class. The pins which
support PWM functionality are the following:
- ``GP24`` on Timer 0 channel A.
- ``GP25`` on Timer 1 channel A.
- ``GP9`` on Timer 2 channel B.
- ``GP10`` on Timer 3 channel A.
- ``GP11`` on Timer 3 channel B.
class TimerChannel --- setup a channel for a timer
==================================================
@@ -166,31 +167,49 @@ Methods
- ``priority`` level of the interrupt. Can take values in the range 1-7.
Higher values represent higher priorities.
- ``handler`` is an optional function to be called when the interrupt is triggered.
- ``trigger`` must be ``Timer.TIMEOUT`` when the operating mode is either ``Timer.PERIODIC`` or
``Timer.ONE_SHOT``. In the case that mode is ``Timer.PWM`` then trigger must be equal to
``Timer.MATCH``.
Returns a callback object.
.. only:: port_wipy
.. method:: timerchannel.freq([value])
Get or set the timer channel frequency (in Hz).
.. method:: timerchannel.period([value])
Get or set the timer channel period (in microseconds).
.. method:: timerchannel.time([value])
Get or set the timer channel current **time** value (in microseconds).
.. method:: timerchannel.event_count()
Get the number of edge events counted.
.. method:: timerchannel.event_time()
Get the time of ocurrance of the last event.
.. method:: timerchannel.duty_cycle([value])
Get or set the duty cycle of the PWM signal (in the range of 0-100).
Get or set the duty cycle of the PWM signal. It's a percentage (0.00-100.00). Since the WiPy
doesn't support floating point numbers the duty cycle must be specified in the range 0-10000,
where 10000 would represent 100.00, 5050 represents 50.50, and so on.
Constants
---------
.. data:: Timer.ONE_SHOT
.. data:: Timer.PERIODIC
.. data:: Timer.PWM
Selects the timer operating mode.
.. data:: Timer.A
.. data:: Timer.B
Selects the timer channel. Must be ORed (``Timer.A`` | ``Timer.B``) when
using a 32-bit timer.
.. data:: Timer.POSITIVE
.. data:: Timer.NEGATIVE
Timer channel polarity selection (only relevant in PWM mode).
.. data:: Timer.TIMEOUT
.. data:: Timer.MATCH
Timer channel IRQ triggers.

View File

@@ -11,7 +11,7 @@ Reset related functions
.. function:: reset()
Resets the WiPy in a manner similar to pushing the external RESET
Resets the device in a manner similar to pushing the external RESET
button.
.. function:: reset_cause()
@@ -87,7 +87,7 @@ Miscellaneous functions
.. function:: unique_id()
Returns a string of 6 bytes (48 bits), which is the unique ID of the MCU.
This also corresponds to the ``MAC address`` of the WiPy.
This also corresponds to the network ``MAC address``.
.. _machine_constants:

View File

@@ -8,7 +8,8 @@
This module provides network drivers and routing configuration. Network
drivers for specific hardware are available within this module and are
used to configure a hardware network interface. Configured interfaces
are then available for use via the :mod:`socket` module.
are then available for use via the :mod:`socket` module. To use this module
the network build of firmware must be installed.
For example::
@@ -29,19 +30,27 @@ For example::
.. only:: port_wipy
.. _network.server:
.. _network.Server:
class server
class Server
============
The server class controls the behaviour and the configuration of the FTP and telnet
The ``Server`` class controls the behaviour and the configuration of the FTP and telnet
services running on the WiPy. Any changes performed using this class' methods will
affect both.
Example::
import network
server = network.Server()
server.deinit() # disable the server
# enable the server again with new settings
server.init(login=('user', 'password'), timeout=600)
Constructors
------------
.. class:: network.server(id, ...)
.. class:: network.Server(id, ...)
Create a server instance, see ``init`` for parameters of initialization.
@@ -220,26 +229,52 @@ For example::
.. only:: port_esp8266
Functions
=========
.. function:: phy_mode([mode])
Get or set the PHY mode.
If the ``mode`` parameter is provided, sets the mode to its value. If
the function is called wihout parameters, returns the current mode.
The possible modes are defined as constants:
* ``MODE_11B`` -- IEEE 802.11b,
* ``MODE_11G`` -- IEEE 802.11g,
* ``MODE_11N`` -- IEEE 802.11n.
class WLAN
==========
This class provides a driver for WiFi network processor in the ESP8266. Example usage::
import network
# setup as a station
nic = network.WLAN()
# enable station interface and connect to WiFi access point
nic = network.WLAN(network.STA_IF)
nic.active(True)
nic.connect('your-ssid', 'your-password')
# now use socket as usual
# now use sockets as usual
Constructors
------------
.. class:: WLAN()
.. class:: WLAN(interface_id)
Create a WLAN driver object.
Create a WLAN network interface object. Supported interfaces are
``network.STA_IF`` (station aka client, connects to upstream WiFi access
points) and ``network.AP_IF`` (access point, allows other WiFi clients to
connect). Availability of the methods below depends on interface type.
For example, only STA interface may ``connect()`` to an access point.
Methods
-------
.. method:: wlan.active([is_active])
Activate ("up") or deactivate ("down") network interface, if boolean
argument is passed. Otherwise, query current state if no argument is
provided. Most other methods require active interface.
.. method:: wlan.connect(ssid, password)
Connect to the specified wireless network, using the specified password.
@@ -248,16 +283,20 @@ For example::
Disconnect from the currently connected wireless network.
.. method:: wlan.scan(cb)
.. method:: wlan.mac([address])
Initiate scanning for the available wireless networks.
Get or set the network interface MAC address.
Scanning is only possible if the radio is in station or station+AP mode; if
called while in AP only mode, an OSError exception will be raised.
If the ``address`` parameter is provided, sets the address to its
value, which should be bytes object of length 6. If the function
is called wihout parameters, returns the current address.
Once the scanning is complete, the provided callback function ``cb`` will
be called once for each network found, and passed a tuple with information
about that network:
.. method:: wlan.scan()
Scan for the available wireless networks.
Scanning is only possible on STA interface. Returns list of tuples with
the information about WiFi access points:
(ssid, bssid, channel, RSSI, authmode, hidden)
@@ -274,7 +313,7 @@ For example::
* 0 -- visible
* 1 -- hidden
.. method:: status()
.. method:: wlan.status()
Return the current status of the wireless connection.

View File

@@ -4,12 +4,13 @@
.. module:: os
:synopsis: basic "operating system" services
The ``os`` module contains functions for filesystem access and ``urandom``.
The ``os`` module contains functions for filesystem access and ``urandom``
function.
Pyboard specifics
-----------------
Port specifics
--------------
The filesystem on the pyboard has ``/`` as the root directory and the
The filesystem has ``/`` as the root directory and the
available physical drives are accessible from here. They are currently:
``/flash`` -- the internal flash filesystem

View File

@@ -18,6 +18,7 @@ class ADC -- analog to digital conversion
val = adc.read_core_vbat() # read MCU VBAT
val = adc.read_core_vref() # read MCU VREF
Constructors
------------
@@ -74,3 +75,68 @@ Methods
This function does not allocate any memory.
The ADCAll Object
-----------------
.. only:: port_pyboard
Instantiating this changes all ADC pins to analog inputs. The raw MCU temperature,
VREF and VBAT data can be accessed on ADC channels 16, 17 and 18 respectively.
Appropriate scaling will need to be applied. The temperature sensor on the chip
has poor absolute accuracy and is suitable only for detecting temperature changes.
The ``ADCAll`` ``read_core_vbat()`` and ``read_core_vref()`` methods read
the backup battery voltage and the (1.21V nominal) reference voltage using the
3.3V supply as a reference. Assuming the ``ADCAll`` object has been Instantiated with
``adc = pyb.ADCAll(12)`` the 3.3V supply voltage may be calculated:
``v33 = 3.3 * 1.21 / adc.read_core_vref()``
If the 3.3V supply is correct the value of ``adc.read_core_vbat()`` will be
valid. If the supply voltage can drop below 3.3V, for example in in battery
powered systems with a discharging battery, the regulator will fail to preserve
the 3.3V supply resulting in an incorrect reading. To produce a value which will
remain valid under these circumstances use the following:
``vback = adc.read_core_vbat() * 1.21 / adc.read_core_vref()``
It is possible to access these values without incurring the side effects of ``ADCAll``::
def adcread(chan): # 16 temp 17 vbat 18 vref
assert chan >= 16 and chan <= 18, 'Invalid ADC channel'
start = pyb.millis()
timeout = 100
stm.mem32[stm.RCC + stm.RCC_APB2ENR] |= 0x100 # enable ADC1 clock.0x4100
stm.mem32[stm.ADC1 + stm.ADC_CR2] = 1 # Turn on ADC
stm.mem32[stm.ADC1 + stm.ADC_CR1] = 0 # 12 bit
if chan == 17:
stm.mem32[stm.ADC1 + stm.ADC_SMPR1] = 0x200000 # 15 cycles
stm.mem32[stm.ADC + 4] = 1 << 23
elif chan == 18:
stm.mem32[stm.ADC1 + stm.ADC_SMPR1] = 0x1000000
stm.mem32[stm.ADC + 4] = 0xc00000
else:
stm.mem32[stm.ADC1 + stm.ADC_SMPR1] = 0x40000
stm.mem32[stm.ADC + 4] = 1 << 23
stm.mem32[stm.ADC1 + stm.ADC_SQR3] = chan
stm.mem32[stm.ADC1 + stm.ADC_CR2] = 1 | (1 << 30) | (1 << 10) # start conversion
while not stm.mem32[stm.ADC1 + stm.ADC_SR] & 2: # wait for EOC
if pyb.elapsed_millis(start) > timeout:
raise OSError('ADC timout')
data = stm.mem32[stm.ADC1 + stm.ADC_DR] # clear down EOC
stm.mem32[stm.ADC1 + stm.ADC_CR2] = 0 # Turn off ADC
return data
def v33():
return 4096 * 1.21 / adcread(17)
def vbat():
return 1.21 * 2 * adcread(18) / adcread(17) # 2:1 divider on Vbat channel
def vref():
return 3.3 * adcread(17) / 4096
def temperature():
return 25 + 400 * (3.3 * adcread(16) / 4096 - 0.76)

View File

@@ -63,16 +63,24 @@ Constructors
.. class:: pyb.I2C(bus, ...)
Construct an I2C object on the given bus. ``bus`` can be 1 or 2.
With no additional parameters, the I2C object is created but not
Construct an I2C object on the given bus. ``bus`` can be 1 or 2, 'X' or
'Y'. With no additional parameters, the I2C object is created but not
initialised (it has the settings from the last initialisation of
the bus, if any). If extra arguments are given, the bus is initialised.
See ``init`` for parameters of initialisation.
The physical pins of the I2C busses are:
The physical pins of the I2C busses on Pyboards V1.0 and V1.1 are:
- ``I2C(1)`` is on the X position: ``(SCL, SDA) = (X9, X10) = (PB6, PB7)``
- ``I2C(2)`` is on the Y position: ``(SCL, SDA) = (Y9, Y10) = (PB10, PB11)``
On the Pyboard Lite:
- ``I2C(1)`` is on the X position: ``(SCL, SDA) = (X9, X10) = (PB6, PB7)``
- ``I2C(3)`` is on the Y position: ``(SCL, SDA) = (Y9, Y10) = (PA8, PB8)``
Calling the constructor with 'X' or 'Y' enables portability between Pyboard
types.
Methods
-------

View File

@@ -25,6 +25,12 @@ Methods
If no argument is given, return the LED intensity.
If an argument is given, set the LED intensity and return ``None``.
*Note:* Only LED(3) and LED(4) can have a smoothly varying intensity, and
they use timer PWM to implement it. LED(3) uses Timer(2) and LED(4) uses
Timer(3). These timers are only configured for PWM if the intensity of the
relevant LED is set to a value between 1 and 254. Otherwise the timers are
free for general purpose use.
.. method:: led.off()
Turn the LED off.

View File

@@ -33,9 +33,9 @@ Constructors
.. class:: pyb.SPI(bus, ...)
Construct an SPI object on the given bus. ``bus`` can be 1 or 2.
With no additional parameters, the SPI object is created but not
initialised (it has the settings from the last initialisation of
Construct an SPI object on the given bus. ``bus`` can be 1 or 2, or
'X' or 'Y'. With no additional parameters, the SPI object is created but
not initialised (it has the settings from the last initialisation of
the bus, if any). If extra arguments are given, the bus is initialised.
See ``init`` for parameters of initialisation.

View File

@@ -37,9 +37,13 @@ class Timer -- control internal timers
tim.callback(lambda t: ...) # set callback for update interrupt (t=tim instance)
tim.callback(None) # clear callback
*Note:* Timer 3 is reserved for internal use. Timer 5 controls
the servo driver, and Timer 6 is used for timed ADC/DAC reading/writing.
It is recommended to use the other timers in your programs.
*Note:* Timer(2) and Timer(3) are used for PWM to set the intensity of LED(3)
and LED(4) respectively. But these timers are only configured for PWM if
the intensity of the relevant LED is set to a value between 1 and 254. If
the intensity feature of the LEDs is not used then these timers are free for
general purpose use. Similarly, Timer(5) controls the servo driver, and
Timer(6) is used for timed ADC/DAC reading/writing. It is recommended to
use the other timers in your programs.
*Note:* Memory can't be allocated during a callback (an interrupt) and so
exceptions raised within a callback don't give much information. See
@@ -56,7 +60,7 @@ Constructors
Construct a new timer object of the given id. If additional
arguments are given, then the timer is initialised by ``init(...)``.
``id`` can be 1 to 14, excluding 3.
``id`` can be 1 to 14.
Methods
-------

View File

@@ -103,7 +103,7 @@ Methods
.. method:: uart.any()
Return ``True`` if any characters waiting, else ``False``.
Returns the number of characters waiting (may be 0).
.. method:: uart.writechar(char)

View File

@@ -25,6 +25,10 @@ Time related functions
after 2^30 milliseconds (about 12.4 days) this will start to return
negative numbers.
Note that if :meth:`pyb.stop()` is issued the hardware counter supporting this
function will pause for the duration of the "sleeping" state. This
will affect the outcome of :meth:`pyb.elapsed_millis()`.
.. function:: micros()
Returns the number of microseconds since the board was last reset.
@@ -33,6 +37,10 @@ Time related functions
after 2^30 microseconds (about 17.8 minutes) this will start to return
negative numbers.
Note that if :meth:`pyb.stop()` is issued the hardware counter supporting this
function will pause for the duration of the "sleeping" state. This
will affect the outcome of :meth:`pyb.elapsed_micros()`.
.. function:: elapsed_millis(start)
Returns the number of milliseconds which have elapsed since ``start``.

View File

@@ -44,7 +44,7 @@ Functions
Sleep for the given number of seconds.
.. only:: port_wipy
.. only:: port_wipy or port_pyboard
.. function:: sleep_ms(ms)

View File

@@ -10,11 +10,25 @@ encodings of it in ASCII form (in both directions).
Functions
---------
.. function:: hexlify(data)
.. function:: hexlify(data, [sep])
Convert binary data to hexadecimal representation. Return bytes string.
.. admonition:: Difference to CPython
:class: attention
If additional argument, `sep` is supplied, it is used as a seperator
between hexadecimal values.
.. function:: unhexlify(data)
Convert hexadecimal data to binary representation. Return bytes string.
(i.e. inverse of hexlify)
.. function:: a2b_base64(data)
Convert Base64-encoded data to binary representation. Return bytes string.
.. function:: b2a_base64(data)
Encode binary data in Base64 format. Return string.

View File

@@ -6,7 +6,7 @@
This module implements "foreign data interface" for MicroPython. The idea
behind it is similar to CPython's ``ctypes`` modules, but actual API is
different, steamlined and optimized for small size.
different, streamlined and optimized for small size.
Defining structure layout
-------------------------

View File

@@ -64,8 +64,8 @@ This code uses a few new concepts:
Accepting arguments
-------------------
Inline assembler functions can accept up to 3 arguments. If they are
used, they must be named ``r0``, ``r1`` and ``r2`` to reflect the registers
Inline assembler functions can accept up to 4 arguments. If they are
used, they must be named ``r0``, ``r1``, ``r2`` and ``r3`` to reflect the registers
and the calling conventions.
Here is a function that adds its arguments::

View File

@@ -99,3 +99,9 @@ The above sequence of events gets a bit more complicated when multiple
interrupts occur at the same time. In that case, the interrupt with the
highest priority goes first, then the others in order of their priority.
The switch interrupt is set at the lowest priority.
Further reading
---------------
For further information about using hardware interrupts see
:ref:`writing interrupt handlers <isr_rules>`.

View File

@@ -78,11 +78,23 @@ three arguments, which must (if used) be named ``r0``, ``r1`` and ``r2``. When
the code executes the registers will be initialised to those values.
The data types which can be passed in this way are integers and memory
addresses. Further, integers are restricted in that the top two bits
must be identical, limiting the range to -2**30 to 2**30 -1. Return
values are similarly limited. These limitations can be overcome by means
of the ``array`` module to allow any number of values of any type to
be accessed.
addresses. With current firmware all possible 32 bit values may be passed and
returned. If the return value may have the most significant bit set a Python
type hint should be employed to enable MicroPython to determine whether the
value should be interpreted as a signed or unsigned integer: types are
``int`` or ``uint``.
::
@micropython.asm_thumb
def uadd(r0, r1) -> uint:
add(r0, r0, r1)
``hex(uadd(0x40000000,0x40000000))`` will return 0x80000000, demonstrating the
passing and return of integers where bits 30 and 31 differ.
The limitations on the number of arguments and return values can be overcome by means
of the ``array`` module which enables any number of values of any type to be accessed.
Multiple arguments
~~~~~~~~~~~~~~~~~~

View File

@@ -5,6 +5,9 @@ Miscellaneous instructions
* wfi() Suspend execution in a low power state until an interrupt occurs.
* cpsid(flags) set the Priority Mask Register - disable interrupts.
* cpsie(flags) clear the Priority Mask Register - enable interrupts.
* mrs(Rd, special_reg) ``Rd = special_reg`` copy a special register to a general register. The special register
may be IPSR (Interrupt Status Register) or BASEPRI (Base Priority Register). The IPSR provides a means of determining
the exception number of an interrupt being processed. It contains zero if no interrupt is being processed.
Currently the ``cpsie()`` and ``cpsid()`` functions are partially implemented.
They require but ignore the flags argument and serve as a means of enabling and disabling interrupts.

View File

@@ -21,8 +21,7 @@ Where immediate values are used, these are zero-extended to 32 bits. Thus
movt writes an immediate value to the top halfword of the destination register.
It does not affect the contents of the bottom halfword.
* movwt(Rd, imm30) ``Rd = imm30``
* movwt(Rd, imm32) ``Rd = imm32``
movwt is a pseudo-instruction: the MicroPython assembler emits a ``movw`` and a ``movt``
to move a zero extended 30 bit value into Rd. Where the full 32 bits are required a
workround is to use the movw and movt operations.
movwt is a pseudo-instruction: the MicroPython assembler emits a ``movw`` followed
by a ``movt`` to move a 32-bit value into Rd.

View File

@@ -13,6 +13,8 @@ MicroPython are described in the sections here.
:maxdepth: 1
repl.rst
isr_rules.rst
speed_python.rst
.. only:: port_pyboard

View File

@@ -0,0 +1,302 @@
.. _isr_rules:
Writing interrupt handlers
==========================
On suitable hardware MicroPython offers the ability to write interrupt handlers in Python. Interrupt handlers
- also known as interrupt service routines (ISR's) - are defined as callback functions. These are executed
in response to an event such as a timer trigger or a voltage change on a pin. Such events can occur at any point
in the execution of the program code. This carries significant consequences, some specific to the MicroPython
language. Others are common to all systems capable of responding to real time events. This document covers
the language specific issues first, followed by a brief introduction to real time programming for those new to it.
This introduction uses vague terms like "slow" or "as fast as possible". This is deliberate, as speeds are
application dependent. Acceptable durations for an ISR are dependent on the rate at which interrupts occur,
the nature of the main program, and the presence of other concurrent events.
Tips and recommended practices
------------------------------
This summarises the points detailed below and lists the principal recommendations for interrupt handler code.
* Keep the code as short and simple as possible.
* Avoid memory allocation: no appending to lists or insertion into dictionaries, no floating point.
* Where an ISR returns multiple bytes use a pre-allocated ``bytearray``. If multiple integers are to be
shared between an ISR and the main program consider an array (``array.array``).
* Where data is shared between the main program and an ISR, consider disabling interrupts prior to accessing
the data in the main program and re-enabling them immediately afterwards (see Critcal Sections).
* Allocate an emergency exception buffer (see below).
MicroPython Issues
------------------
The emergency exception buffer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If an error occurs in an ISR, MicroPython is unable to produce an error report unless a special buffer is created
for the purpose. Debugging is simplified if the following code is included in any program using interrupts.
.. code:: python
import micropython
micropython.alloc_emergency_exception_buf(100)
Simplicity
~~~~~~~~~~
For a variety of reasons it is important to keep ISR code as short and simple as possible. It should do only what
has to be done immediately after the event which caused it: operations which can be deferred should be delegated
to the main program loop. Typically an ISR will deal with the hardware device which caused the interrupt, making
it ready for the next interrupt to occur. It will communicate with the main loop by updating shared data to indicate
that the interrupt has occurred, and it will return. An ISR should return control to the main loop as quickly
as possible. This is not a specific MicroPython issue so is covered in more detail :ref:`below <ISR>`.
Communication between an ISR and the main program
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Normally an ISR needs to communicate with the main program. The simplest means of doing this is via one or more
shared data objects, either declared as global or shared via a class (see below). There are various restrictions
and hazards around doing this, which are covered in more detail below. Integers, ``bytes`` and ``bytearray`` objects
are commonly used for this purpose along with arrays (from the array module) which can store various data types.
The use of object methods as callbacks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MicroPython supports this powerful technique which enables an ISR to share instance variables with the underlying
code. It also enables a class implementing a device driver to support multiple device instances. The following
example causes two LED's to flash at different rates.
.. code:: python
import pyb, micropython
micropython.alloc_emergency_exception_buf(100)
class Foo(object):
def __init__(self, timer, led):
self.led = led
timer.callback(self.cb)
def cb(self, tim):
self.led.toggle()
red = Foo(pyb.Timer(4, freq=1), pyb.LED(1))
greeen = Foo(pyb.Timer(2, freq=0.8), pyb.LED(2))
In this example the ``red`` instance associates timer 4 with LED 1: when a timer 4 interrupt occurs ``red.cb()``
is called causing LED 1 to change state. The ``green`` instance operates similarly: a timer 2 interrupt
results in the execution of ``green.cb()`` and toggles LED 2. The use of instance methods confers two
benefits. Firstly a single class enables code to be shared between multiple hardware instances. Secondly, as
a bound method the callback function's first argument is ``self``. This enables the callback to access instance
data and to save state between successive calls. For example, if the class above had a variable ``self.count``
set to zero in the constructor, ``cb()`` could increment the counter. The ``red`` and ``green`` instances would
then maintain independent counts of the number of times each LED had changed state.
Creation of Python objects
~~~~~~~~~~~~~~~~~~~~~~~~~~
ISR's cannot create instances of Python objects. This is because MicroPython needs to allocate memory for the
object from a store of free memory block called the heap. This is not permitted in an interrupt handler because
heap allocation is not re-entrant. In other words the interrupt might occur when the main program is part way
through performing an allocation - to maintain the integrity of the heap the interpreter disallows memory
allocations in ISR code.
A consequence of this is that ISR's can't use floating point arithmetic; this is because floats are Python objects. Similarly
an ISR can't append an item to a list. In practice it can be hard to determine exactly which code constructs will
attempt to perform memory allocation and provoke an error message: another reason for keeping ISR code short and simple.
One way to avoid this issue is for the ISR to use pre-allocated buffers. For example a class constructor
creates a ``bytearray`` instance and a boolean flag. The ISR method assigns data to locations in the buffer and sets
the flag. The memory allocation occurs in the main program code when the object is instantiated rather than in the ISR.
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.
Use of Python objects
~~~~~~~~~~~~~~~~~~~~~
A further restriction on objects arises because of the way Python works. When an ``import`` statement is executed the
Python code is compiled to bytecode, with one line of code typically mapping to multiple bytecodes. When the code
runs the interpreter reads each bytecode and executes it as a series of machine code instructions. Given that an
interrupt can occur at any time between machine code instructions, the original line of Python code may be only
partially executed. Consequently a Python object such as a set, list or dictionary modified in the main loop
may lack internal consistency at the moment the interrupt occurs.
A typical outcome is as follows. On rare occasions the ISR will run at the precise moment in time when the object
is partially updated. When the ISR tries to read the object, a crash results. Because such problems typically occur
on rare, random occasions they can be hard to diagnose. There are ways to circumvent this issue, described in
:ref:`Critical Sections <Critical>` below.
It is important to be clear about what constitutes the modification of an object. An alteration to a built-in type
such as a dictionary is problematic. Altering the contents of an array or bytearray is not. This is because bytes
or words are written as a single machine code instruction which is not interruptible: in the parlance of real time
programming the write is atomic. A user defined object might instantiate an integer, array or bytearray. It is valid
for both the main loop and the ISR to alter the contents of these.
MicroPython supports integers of arbitrary precision. Values between 2**30 -1 and -2**30 will be stored in
a single machine word. Larger values are stored as Python objects. Consequently changes to long integers cannot
be considered atomic. The use of long integers in ISR's is unsafe because memory allocation may be
attempted as the variable's value changes.
Overcoming the float limitation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In general it is best to avoid using floats in ISR code: hardware devices normally handle integers and conversion
to floats is normally done in the main loop. However there are a few DSP algorithms which require floating point.
On platforms with hardware floating point (such as the Pyboard) the inline ARM Thumb assembler can be used to work
round this limitation. This is because the processor stores float values in a machine word; values can be shared
between the ISR and main program code via an array of floats.
Exceptions
----------
If an ISR raises an exception it will not propagate to the main loop. The interrupt will be disabled unless the
exception is handled by the ISR code.
General Issues
--------------
This is merely a brief introduction to the subject of real time programming. Beginners should note
that design errors in real time programs can lead to faults which are particularly hard to diagnose. This is because
they can occur rarely and at intervals which are essentially random. It is crucial to get the initial design right and
to anticipate issues before they arise. Both interrupt handlers and the main program need to be designed
with an appreciation of the following issues.
.. _ISR:
Interrupt Handler Design
~~~~~~~~~~~~~~~~~~~~~~~~
As mentioned above, ISR's should be designed to be as simple as possible. They should always return in a short,
predictable period of time. This is important because when the ISR is running, the main loop is not: inevitably
the main loop experiences pauses in its execution at random points in the code. Such pauses can be a source of hard
to diagnose bugs particularly if their duration is long or variable. In order to understand the implications of
ISR run time, a basic grasp of interrupt priorities is required.
Interrupts are organised according to a priority scheme. ISR code may itself be interrupted by a higher priority
interrupt. This has implications if the two interrupts share data (see Critical Sections below). If such an interrupt
occurs it interposes a delay into the ISR code. If a lower priority interrupt occurs while the ISR is running, it
will be delayed until the ISR is complete: if the delay is too long, the lower priority interrupt may fail. A
further issue with slow ISR's is the case where a second interrupt of the same type occurs during its execution.
The second interrupt will be handled on termination of the first. However if the rate of incoming interrupts
consistently exceeds the capacity of the ISR to service them the outcome will not be a happy one.
Consequently looping constructs should be avoided or minimised. I/O to devices other than to the interrupting device
should normally be avoided: I/O such as disk access, ``print`` statements and UART access is relatively slow, and
its duration may vary. A further issue here is that filesystem functions are not reentrant: using filesystem I/O
in an ISR and the main program would be hazardous. Crucially ISR code should not wait on an event. I/O is acceptable
if the code can be guaranteed to return in a predictable period, for example toggling a pin or LED. Accessing the
interrupting device via I2C or SPI may be necessary but the time taken for such accesses should be calculated or
measured and its impact on the application assessed.
There is usually a need to share data between the ISR and the main loop. This may be done either through global
variables or via class or instance variables. Variables are typically integer or boolean types, or integer or byte
arrays (a pre-allocated integer array offers faster access than a list). Where multiple values are modified by
the ISR it is necessary to consider the case where the interrupt occurs at a time when the main program has
accessed some, but not all, of the values. This can lead to inconsistencies.
Consider the following design. An ISR stores incoming data in a bytearray, then adds the number of bytes
received to an integer representing total bytes ready for processing. The main program reads the number of bytes,
processes the bytes, then clears down the number of bytes ready. This will work until an interrupt occurs just
after the main program has read the number of bytes. The ISR puts the added data into the buffer and updates
the number received, but the main program has already read the number, so processes the data originally received.
The newly arrived bytes are lost.
There are various ways of avoiding this hazard, the simplest being to use a circular buffer. If it is not possible
to use a structure with inherent thread safety other ways are described below.
Reentrancy
~~~~~~~~~~
A potential hazard may occur if a function or method is shared between the main program and one or more ISR's or
between multiple ISR's. The issue here is that the function may itself be interrupted and a further instance of
that function run. If this is to occur, the function must be designed to be reentrant. How this is done is an
advanced topic beyond the scope of this tutorial.
.. _Critical:
Critical Sections
~~~~~~~~~~~~~~~~~
An example of a critical section of code is one which accesses more than one variable which can be affected by an ISR. If
the interrupt happens to occur between accesses to the individual variables, their values will be inconsistent. This is
an instance of a hazard known as a race condition: the ISR and the main program loop race to alter the variables. To
avoid inconsistency a means must be employed to ensure that the ISR does not alter the values for the duration of
the critical section. One way to achieve this is to issue ``pyb.disable_irq()`` before the start of the section, and
``pyb.enable_irq()`` at the end. Here is an example of this approach:
.. code:: python
import pyb, micropython, array
micropython.alloc_emergency_exception_buf(100)
class BoundsException(Exception):
pass
ARRAYSIZE = const(20)
index = 0
data = array.array('i', 0 for x in range(ARRAYSIZE))
def callback1(t):
global data, index
for x in range(5):
data[index] = pyb.rng() # simulate input
index += 1
if index >= ARRAYSIZE:
raise BoundsException('Array bounds exceeded')
tim4 = pyb.Timer(4, freq=100, callback=callback1)
for loop in range(1000):
if index > 0:
irq_state = pyb.disable_irq() # Start of critical section
for x in range(index):
print(data[x])
index = 0
pyb.enable_irq(irq_state) # End of critical section
print('loop {}'.format(loop))
pyb.delay(1)
tim4.callback(None)
A critical section can comprise a single line of code and a single variable. Consider the following code fragment.
.. code:: python
count = 0
def cb(): # An interrupt callback
count +=1
def main():
# Code to set up the interrupt callback omitted
while True:
count += 1
This example illustrates a subtle source of bugs. The line ``count += 1`` in the main loop carries a specific race
condition hazard known as a read-modify-write. This is a classic cause of bugs in real time systems. In the main loop
MicroPython reads the value of ``t.counter``, adds 1 to it, and writes it back. On rare occasions the interrupt occurs
after the read and before the write. The interrupt modifies ``t.counter`` but its change is overwritten by the main
loop when the ISR returns. In a real system this could lead to rare, unpredictable failures.
As mentioned above, care should be taken if an instance of a Python built in type is modified in the main code and
that instance is accessed in an ISR. The code performing the modification should be regarded as a critical
section to ensure that the instance is in a valid state when the ISR runs.
Particular care needs to be taken if a dataset is shared between different ISR's. The hazard here is that the higher
priority interrupt may occur when the lower priority one has partially updated the shared data. Dealing with this
situation is an advanced topic beyond the scope of this introduction other than to note that mutex objects described
below can sometimes be used.
Disabling interrupts for the duration of a critical section is the usual and simplest way to proceed, but it disables
all interrupts rather than merely the one with the potential to cause problems. It is generally undesirable to disable
an interrupt for long. In the case of timer interrupts it introduces variability to the time when a callback occurs.
In the case of device interrupts, it can lead to the device being serviced too late with possible loss of data or
overrun errors in the device hardware. Like ISR's, a critical section in the main code should have a short, predictable
duration.
An approach to dealing with critical sections which radically reduces the time for which interrupts are disabled is to
use an object termed a mutex (name derived from the notion of mutual exclusion). The main program locks the mutex
before running the critical section and unlocks it at the end. The ISR tests whether the mutex is locked. If it is,
it avoids the critical section and returns. The design challenge is defining what the ISR should do in the event
that access to the critical variables is denied. A simple example of a mutex may be found
`here <https://github.com/peterhinch/micropython-samples.git>`_. Note that the mutex code does disable interrupts,
but only for the duration of eight machine instructions: the benefit of this approach is that other interrupts are
virtually unaffected.

View File

@@ -0,0 +1,318 @@
Maximising Python Speed
=======================
This tutorial describes ways of improving the performance of MicroPython code.
Optimisations involving other languages are covered elsewhere, namely the use
of modules written in C and the MicroPython inline ARM Thumb-2 assembler.
The process of developing high performance code comprises the following stages
which should be performed in the order listed.
* Design for speed.
* Code and debug.
Optimisation steps:
* Identify the slowest section of code.
* Improve the efficiency of the Python code.
* Use the native code emitter.
* Use the viper code emitter.
Designing for speed
-------------------
Performance issues should be considered at the outset. This involves taking a view
on the sections of code which are most performance critical and devoting particular
attention to their design. The process of optimisation begins when the code has
been tested: if the design is correct at the outset optimisation will be
straightforward and may actually be unnecessary.
Algorithms
~~~~~~~~~~
The most important aspect of designing any routine for performance is ensuring that
the best algorithm is employed. This is a topic for textbooks rather than for a
MicroPython guide but spectacular performance gains can sometimes be achieved
by adopting algorithms known for their efficiency.
RAM Allocation
~~~~~~~~~~~~~~
To design efficient MicroPython code it is necessary to have an understanding of the
way the interpreter allocates RAM. When an object is created or grows in size
(for example where an item is appended to a list) the necessary RAM is allocated
from a block known as the heap. This takes a significant amount of time;
further it will on occasion trigger a process known as garbage collection which
can take several milliseconds.
Consequently the performance of a function or method can be improved if an object is created
once only and not permitted to grow in size. This implies that the object persists
for the duration of its use: typically it will be instantiated in a class constructor
and used in various methods.
This is covered in further detail :ref:`Controlling garbage collection <gc>` below.
Buffers
~~~~~~~
An example of the above is the common case where a buffer is required, such as one
used for communication with a device. A typical driver will create the buffer in the
constructor and use it in its I/O methods which will be called repeatedly.
The MicroPython libraries typically provide optional support for pre-allocated buffers.
For example the ``uart.readinto()`` method allows two options for its argument, an integer
or a buffer. If an integer is supplied it will read up to that number of bytes and
return the outcome: this implies that a buffer is created with a corresponding
memory allocation. Providing a pre-allocated buffer as the argument avoids this. See
the code fragment in :ref:`Caching object references <Caching>` below.
Floating Point
~~~~~~~~~~~~~~
For the most speed critical sections of code it is worth noting that performing
any kind of floating point operation involves heap allocation. Where possible use
integer operations and restrict the use of floating point to sections of the code
where performance is not paramount.
Arrays
~~~~~~
Consider the use of the various types of array classes as an alternative to lists.
The ``array`` module supports various element types with 8-bit elements supported
by Python's built in ``bytes`` and ``bytearray`` classes. These data structures all store
elements in contiguous memory locations. Once again to avoid memory allocation in critical
code these should be pre-allocated and passed as arguments or as bound objects.
When passing slices of objects such as ``bytearray`` instances, Python creates
a copy which involves allocation. This can be avoided using a ``memoryview``
object:
.. code:: python
ba = bytearray(100)
func(ba[3:10]) # a copy is passed
mv = memoryview(ba)
func(mv[3:10]) # a pointer to memory is passed
A ``memoryview`` can only be applied to objects supporting the buffer protocol - this
includes arrays but not lists.
Identifying the slowest section of code
---------------------------------------
This is a process known as profiling and is covered in textbooks and
(for standard Python) supported by various software tools. For the type of
smaller embedded application likely to be running on MicroPython platforms
the slowest function or method can usually be established by judicious use
of the timing ``ticks`` group of functions documented
`here <http://docs.micropython.org/en/latest/pyboard/library/time.html>`_.
Code execution time can be measured in ms, us, or CPU cycles.
The following enables any function or method to be timed by adding an
``@timed_function`` decorator:
.. code:: python
def timed_function(f, *args, **kwargs):
myname = str(f).split(' ')[1]
def new_func(*args, **kwargs):
t = time.ticks_us()
result = f(*args, **kwargs)
delta = time.ticks_diff(t, time.ticks_us())
print('Function {} Time = {:6.3f}ms'.format(myname, delta/1000))
return result
return new_func
MicroPython code improvements
-----------------------------
The const() declaration
~~~~~~~~~~~~~~~~~~~~~~~
MicroPython provides a ``const()`` declaration. This works in a similar way
to ``#define`` in C in that when the code is compiled to bytecode the compiler
substitutes the numeric value for the identifier. This avoids a dictionary
lookup at runtime. The argument to ``const()`` may be anything which, at
compile time, evaluates to an integer e.g. ``0x100`` or ``1 << 8``.
.. _Caching:
Caching object references
~~~~~~~~~~~~~~~~~~~~~~~~~~
Where a function or method repeatedly accesses objects performance is improved
by caching the object in a local variable:
.. code:: python
class foo(object):
def __init__(self):
ba = bytearray(100)
def bar(self, obj_display):
ba_ref = self.ba
fb = obj_display.framebuffer
# iterative code using these two objects
This avoids the need repeatedly to look up ``self.ba`` and ``obj_display.framebuffer``
in the body of the method ``bar()``.
.. _gc:
Controlling garbage collection
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When memory allocation is required, MicroPython attempts to locate an adequately
sized block on the heap. This may fail, usually because the heap is cluttered
with objects which are no longer referenced by code. If a failure occurs, the
process known as garbage collection reclaims the memory used by these redundant
objects and the allocation is then tried again - a process which can take several
milliseconds.
There are benefits in pre-empting this by periodically issuing ``gc.collect()``.
Firstly doing a collection before it is actually required is quicker - typically on the
order of 1ms if done frequently. Secondly you can determine the point in code
where this time is used rather than have a longer delay occur at random points,
possibly in a speed critical section. Finally performing collections regularly
can reduce fragmentation in the heap. Severe fragmentation can lead to
non-recoverable allocation failures.
Accessing hardware directly
~~~~~~~~~~~~~~~~~~~~~~~~~~~
This comes into the category of more advanced programming and involves some knowledge
of the target MCU. Consider the example of toggling an output pin on the Pyboard. The
standard approach would be to write
.. code:: python
mypin.value(mypin.value() ^ 1) # mypin was instantiated as an output pin
This involves the overhead of two calls to the ``Pin`` instance's ``value()``
method. This overhead can be eliminated by performing a read/write to the relevant bit
of the chip's GPIO port output data register (odr). To facilitate this the ``stm``
module provides a set of constants providing the addresses of the relevant registers.
A fast toggle of pin ``P4`` (CPU pin ``A14``) - corresponding to the green LED -
can be performed as follows:
.. code:: python
BIT14 = const(1 << 14)
stm.mem16[stm.GPIOA + stm.GPIO_ODR] ^= BIT14
The Native code emitter
-----------------------
This causes the MicroPython compiler to emit ARM native opcodes rather than
bytecode. It covers the bulk of the Python language so most functions will require
no adaptation (but see below). It is invoked by means of a function decorator:
.. code:: python
@micropython.native
def foo(self, arg):
buf = self.linebuf # Cached object
# code
There are certain limitations in the current implementation of the native code emitter.
* Context managers are not supported (the ``with`` statement).
* Generators are not supported.
* If ``raise`` is used an argument must be supplied.
The trade-off for the improved performance (roughly twices as fast as bytecode) is an
increase in compiled code size.
The Viper code emitter
----------------------
The optimisations discussed above involve standards-compliant Python code. The
Viper code emitter is not fully compliant. It supports special Viper native data types
in pursuit of performance. Integer processing is non-compliant because it uses machine
words: arithmetic on 32 bit hardware is performed modulo 2**32.
Like the Native emitter Viper produces machine instructions but further optimisations
are performed, substantially increasing performance especially for integer arithmetic and
bit manipulations. It is invoked using a decorator:
.. code:: python
@micropython.viper
def foo(self, arg: int) -> int:
# code
As the above fragment illustrates it is beneficial to use Python type hints to assist the Viper optimiser.
Type hints provide information on the data types of arguments and of the return value; these
are a standard Python language feature formally defined here `PEP0484 <https://www.python.org/dev/peps/pep-0484/>`_.
Viper supports its own set of types namely ``int``, ``uint`` (unsigned integer), ``ptr``, ``ptr8``,
``ptr16`` and ``ptr32``. The ``ptrX`` types are discussed below. Currently the ``uint`` type serves
a single purpose: as a type hint for a function return value. If such a function returns ``0xffffffff``
Python will interpret the result as 2**32 -1 rather than as -1.
In addition to the restrictions imposed by the native emitter the following constraints apply:
* Functions may have up to four arguments.
* Default argument values are not permitted.
* Floating point may be used but is not optimised.
Viper provides pointer types to assist the optimiser. These comprise
* ``ptr`` Pointer to an object.
* ``ptr8`` Points to a byte.
* ``ptr16`` Points to a 16 bit half-word.
* ``ptr32`` Points to a 32 bit machine word.
The concept of a pointer may be unfamiliar to Python programmers. It has similarities
to a Python ``memoryview`` object in that it provides direct access to data stored in memory.
Items are accessed using subscript notation, but slices are not supported: a pointer can return
a single item only. Its purpose is to provide fast random access to data stored in contiguous
memory locations - such as data stored in objects which support the buffer protocol, and
memory-mapped peripheral registers in a microcontroller. It should be noted that programming
using pointers is hazardous: bounds checking is not performed and the compiler does nothing to
prevent buffer overrun errors.
Typical usage is to cache variables:
.. code:: python
@micropython.viper
def foo(self, arg: int) -> int:
buf = ptr8(self.linebuf) # self.linebuf is a bytearray or bytes object
for x in range(20, 30):
bar = buf[x] # Access a data item through the pointer
# code omitted
In this instance the compiler "knows" that ``buf`` is the address of an array of bytes;
it can emit code to rapidly compute the address of ``buf[x]`` at runtime. Where casts are
used to convert objects to Viper native types these should be performed at the start of
the function rather than in critical timing loops as the cast operation can take several
microseconds. The rules for casting are as follows:
* Casting operators are currently: ``int``, ``bool``, ``uint``, ``ptr``, ``ptr8``, ``ptr16`` and ``ptr32``.
* The result of a cast will be a native Viper variable.
* Arguments to a cast can be a Python object or a native Viper variable.
* If argument is a native Viper variable, then cast is a no-op (i.e. costs nothing at runtime)
that just changes the type (e.g. from ``uint`` to ``ptr8``) so that you can then store/load
using this pointer.
* If the argument is a Python object and the cast is ``int`` or ``uint``, then the Python object
must be of integral type and the value of that integral object is returned.
* The argument to a bool cast must be integral type (boolean or integer); when used as a return
type the viper function will return True or False objects.
* If the argument is a Python object and the cast is ``ptr``, ``ptr``, ``ptr16`` or ``ptr32``,
then the Python object must either have the buffer protocol with read-write capabilities
(in which case a pointer to the start of the buffer is returned) or it must be of integral
type (in which case the value of that integral object is returned).
The following example illustrates the use of a ``ptr16`` cast to toggle pin X1 ``n`` times:
.. code:: python
BIT0 = const(1)
@micropython.viper
def toggle_n(n: int):
odr = ptr16(stm.GPIOA + stm.GPIO_ODR)
for _ in range(n):
odr[0] ^= BIT0
A detailed technical description of the three code emitters may be found
on Kickstarter here `Note 1 <https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers/posts/664832>`_
and here `Note 2 <https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers/posts/665145>`_

39
docs/templates/versions.html vendored Normal file
View File

@@ -0,0 +1,39 @@
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
<span class="rst-current-version" data-toggle="rst-current-version">
<span class="fa fa-book"> Ports and Versions</span>
{{ port_short_name }} ({{ port_version }})
<span class="fa fa-caret-down"></span>
</span>
<div class="rst-other-versions">
<dl>
<dt>Ports</dt>
{% for slug, url in all_ports %}
<dd><a href="{{ url }}">{{ slug }}</a></dd>
{% endfor %}
</dl>
<dl>
<dt>Versions</dt>
{% for slug, url in all_versions %}
<dd><a href="{{ url }}">{{ slug }}</a></dd>
{% endfor %}
</dl>
<!--
<dl>
<dt>Downloads</dt>
{% for type, url in downloads %}
<dd><a href="{{ url }}">{{ type }}</a></dd>
{% endfor %}
</dl>
-->
<hr/>
<dl>
<dt>External links</dt>
<dd>
<a href="http://www.micropython.org">micropython.org</a>
</dd>
<dd>
<a href="https://github.com/micropython/micropython">GitHub</a>
</dd>
</dl>
</div>
</div>

View File

@@ -41,10 +41,10 @@
{% endif %}
<p class="biglink">
<a class="biglink" href="{{ pathto("library/index") }}">Library Reference</a><br/>
{% if port == "wipy" %}
<span class="linkdescr">MicroPython libraries, including the <a href="{{ pathto("library/machine") }}">machine module</a></span>
{% else %}
{% if port == "pyboard" %}
<span class="linkdescr">MicroPython libraries, including the <a href="{{ pathto("library/pyb") }}">pyb module</a></span>
{% else %}
<span class="linkdescr">MicroPython libraries, including the <a href="{{ pathto("library/machine") }}">machine module</a></span>
{% endif %}
</p>
</td>

View File

@@ -49,10 +49,10 @@ See :ref:`machine.Timer <machine.Timer>` and :ref:`machine.Pin <machine.Pin>`. :
from machine import Timer
from machine import Pin
tim = Timer(1, mode=Timer.PERIODIC)
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(1) # 1 Hz
tim_a.freq(5) # 5 Hz
p_out = Pin('GP2', mode=Pin.OUT)
tim_a.irq(handler=lambda t: p_out.toggle())
@@ -63,16 +63,12 @@ PWM (pulse width modulation)
See :ref:`machine.Pin <machine.Pin>` and :ref:`machine.Timer <machine.Timer>`. ::
from machine import Timer
from machine import Pin
# assign GP25 to alternate function 9 (PWM)
p_out = Pin('GP25', mode=Pin.AF, alt=9)
# timer 2 in PWM mode and width must be 16 buts
tim = Timer(2, mode=Timer.PWM, width=16)
# timer 1 in PWM mode and width must be 16 buts
tim = Timer(1, mode=Timer.PWM, width=16)
# enable channel A @1KHz with a 50% duty cycle
tim_a = tim.channel(Timer.A, freq=1000, duty_cycle=50)
# enable channel A @1KHz with a 50.55% duty cycle
tim_a = tim.channel(Timer.A, freq=1000, duty_cycle=5055)
ADC (analog to digital conversion)
----------------------------------
@@ -201,12 +197,12 @@ See :ref:`network.WLAN <network.WLAN>` and :mod:`machine`. ::
Telnet and FTP server
---------------------
See :ref:`network.server <network.server>` ::
See :ref:`network.Server <network.Server>` ::
from network import server
from network import Server
# init with new user, password and seconds timeout
server = server.init(login=('user', 'password'), timeout=60)
server = Server(login=('user', 'password'), timeout=60)
server.timeout(300) # change the timeout
server.timeout() # get the timeout
server.isrunning() # check wether the server is running or not

View File

@@ -25,6 +25,9 @@ class SDCard:
#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
@@ -136,6 +139,18 @@ class SDCard:
self.spi.send(0xff)
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.cs.high()
self.spi.send(0xff)
return 0 # OK
self.cs.high()
self.spi.send(0xff)
return 1 # timeout
def readinto(self, buf):
self.cs.low()
@@ -154,11 +169,11 @@ class SDCard:
self.cs.high()
self.spi.send(0xff)
def write(self, buf):
def write(self, token, buf):
self.cs.low()
# send: start of block, data, checksum
self.spi.send(0xfe)
self.spi.send(token)
self.spi.send(buf)
self.spi.send(0xff)
self.spi.send(0xff)
@@ -176,29 +191,62 @@ class SDCard:
self.cs.high()
self.spi.send(0xff)
def write_token(self, token):
self.cs.low()
self.spi.send(token)
self.spi.send(0xff)
# wait for write to finish
while self.spi.send_recv(0xff)[0] == 0:
pass
self.cs.high()
self.spi.send(0xff)
def count(self):
return self.sectors
def readblocks(self, block_num, buf):
# TODO support multiple block reads
assert len(buf) == 512
# CMD17: set read address for single block
if self.cmd(17, block_num * self.cdv, 0) != 0:
return 1
# receive the data
self.readinto(buf)
nblocks, err = divmod(len(buf), 512)
assert nblocks and not err, 'Buffer length is invalid'
if nblocks == 1:
# CMD17: set read address for single block
if self.cmd(17, block_num * self.cdv, 0) != 0:
return 1
# receive the data
self.readinto(buf)
else:
# CMD18: set read address for multiple blocks
if self.cmd(18, block_num * self.cdv, 0) != 0:
return 1
offset = 0
mv = memoryview(buf)
while nblocks:
self.readinto(mv[offset : offset + 512])
offset += 512
nblocks -= 1
return self.cmd_nodata(12)
return 0
def writeblocks(self, block_num, buf):
# TODO support multiple block writes
assert len(buf) == 512
nblocks, err = divmod(len(buf), 512)
assert nblocks and not err, 'Buffer length is invalid'
if nblocks == 1:
# CMD24: set write address for single block
if self.cmd(24, block_num * self.cdv, 0) != 0:
return 1
# CMD24: set write address for single block
if self.cmd(24, block_num * self.cdv, 0) != 0:
return 1
# send the data
self.write(buf)
# send the data
self.write(TOKEN_DATA, buf)
else:
# CMD25: set write address for first block
if self.cmd(25, block_num * self.cdv, 0) != 0:
return 1
# send the data
offset = 0
mv = memoryview(buf)
while nblocks:
self.write(TOKEN_CMD25, mv[offset : offset + 512])
offset += 512
nblocks -= 1
self.write_token(TOKEN_STOP_TRAN)
return 0

57
drivers/sdcard/sdtest.py Normal file
View File

@@ -0,0 +1,57 @@
# Test for sdcard block protocol
# Peter hinch 30th Jan 2016
import os, sdcard, pyb
def sdtest():
sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X21) # Compatible with PCB
pyb.mount(sd, '/fc')
print('Filesystem check')
print(os.listdir('/fc'))
line = 'abcdefghijklmnopqrstuvwxyz\n'
lines = line * 200 # 5400 chars
short = '1234567890\n'
fn = '/fc/rats.txt'
print()
print('Multiple block read/write')
with open(fn,'w') as f:
n = f.write(lines)
print(n, 'bytes written')
n = f.write(short)
print(n, 'bytes written')
n = f.write(lines)
print(n, 'bytes written')
with open(fn,'r') as f:
result1 = f.read()
print(len(result1), 'bytes read')
fn = '/fc/rats1.txt'
print()
print('Single block read/write')
with open(fn,'w') as f:
n = f.write(short) # one block
print(n, 'bytes written')
with open(fn,'r') as f:
result2 = f.read()
print(len(result2), 'bytes read')
pyb.mount(None, '/fc')
print()
print('Verifying data read back')
success = True
if result1 == ''.join((lines, short, lines)):
print('Large file Pass')
else:
print('Large file Fail')
success = False
if result2 == short:
print('Small file Pass')
else:
print('Small file Fail')
success = False
print()
print('Tests', 'passed' if success else 'failed')

View File

@@ -9,8 +9,8 @@ include ../py/py.mk
MAKE_FROZEN = ../tools/make-frozen.py
SCRIPTDIR = scripts
PORT = /dev/ttyACM0
BAUD = 115200
PORT ?= /dev/ttyACM0
BAUD ?= 115200
CROSS_COMPILE = xtensa-lx106-elf-
ESP_SDK = $(shell $(CC) -print-sysroot)/usr
@@ -23,18 +23,21 @@ INC += -I../lib/timeutils
INC += -I$(BUILD)
INC += -I$(ESP_SDK)/include
UART_OS = 1
# UART for "os" messages. 0 is normal UART as used by MicroPython REPL,
# 1 is debug UART (tx only).
UART_OS = 0
CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \
-D__ets__ -DICACHE_FLASH \
-fno-inline-functions \
-Wl,-EL -mlongcalls -mtext-section-literals \
-DLWIP_OPEN_SRC
CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
$(CFLAGS_XTENSA) $(COPT)
$(CFLAGS_XTENSA) $(COPT) $(CFLAGS_EXTRA)
LDFLAGS = -nostdlib -T esp8266.ld -Map=$(@:.elf=.map) --cref
LIBS = -L$(ESP_SDK)/lib -lmain -ljson -llwip -lpp -lnet80211 -lwpa -lphy -lnet80211
LIBS = -L$(ESP_SDK)/lib -lmain -ljson -lssl -llwip_open -lpp -lnet80211 -lwpa -lphy -lnet80211
LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc
@@ -45,7 +48,7 @@ CFLAGS += -g
COPT = -O0
else
CFLAGS += -fdata-sections -ffunction-sections
COPT += -Os -DNDEBUG
COPT += -Os -mforce-l32 -DNDEBUG
LDFLAGS += --gc-sections
endif
@@ -54,29 +57,64 @@ SRC_C = \
main.c \
esp_mphal.c \
gccollect.c \
lexerstr32.c \
uart.c \
esppwm.c \
espneopixel.c \
modpyb.c \
modpybpin.c \
modpybpwm.c \
modpybrtc.c \
modpybadc.c \
modpybuart.c \
modpybi2c.c \
modpybspi.c \
modesp.c \
modnetwork.c \
modutime.c \
moduos.c \
modmachine.c \
modonewire.c \
utils.c \
ets_alt_task.c \
$(BUILD)/frozen.c \
fatfs_port.o \
STM_SRC_C = $(addprefix stmhal/,\
pybstdio.c \
)
EXTMOD_SRC_C = $(addprefix extmod/,\
modlwip.o \
)
LIB_SRC_C = $(addprefix lib/,\
libc/string0.c \
libm/math.c \
libm/fmodf.c \
libm/roundf.c \
libm/ef_sqrt.c \
libm/kf_rem_pio2.c \
libm/kf_sin.c \
libm/kf_cos.c \
libm/kf_tan.c \
libm/ef_rem_pio2.c \
libm/sf_sin.c \
libm/sf_cos.c \
libm/sf_tan.c \
libm/sf_frexp.c \
libm/sf_modf.c \
libm/sf_ldexp.c \
libm/asinfacosf.c \
libm/atanf.c \
libm/atan2f.c \
mp-readline/readline.c \
netutils/netutils.c \
timeutils/timeutils.c \
utils/pyexec.c \
utils/printf.c \
fatfs/ff.c \
fatfs/option/ccsbcs.c \
)
SRC_S = \
@@ -87,6 +125,7 @@ OBJ += $(PY_O)
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
#OBJ += $(BUILD)/pins_$(BOARD).o
@@ -111,8 +150,8 @@ $(BUILD)/frozen.c: $(wildcard $(SCRIPTDIR)/*) $(CONFVARS_FILE)
deploy: $(BUILD)/firmware-combined.bin
$(ECHO) "Writing $< to the board"
#$(Q)esptool.py --port $(PORT) write_flash 0 $<
$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash 0 $(BUILD)/firmware.elf-0x00000.bin 0x10000 $(BUILD)/firmware.elf-0x10000.bin
$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --flash_size=8m 0 $<
#$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --flash_size=8m 0 $(BUILD)/firmware.elf-0x00000.bin 0x9000 $(BUILD)/firmware.elf-0x0[1-f]000.bin
reset:
echo -e "\r\nimport pyb; pyb.hard_reset()\r\n" >$(PORT)
@@ -120,7 +159,7 @@ reset:
$(BUILD)/firmware-combined.bin: $(BUILD)/firmware.elf
$(ECHO) "Create $@"
$(Q)esptool.py elf2image $^
$(Q)$(PYTHON) makeimg.py $(BUILD)/firmware.elf-0x00000.bin $(BUILD)/firmware.elf-0x10000.bin $@
$(Q)$(PYTHON) makeimg.py $(BUILD)/firmware.elf-0x00000.bin $(BUILD)/firmware.elf-0x0[1-f]000.bin $@
$(BUILD)/firmware.elf: $(OBJ)
$(ECHO) "LINK $@"

View File

@@ -8,49 +8,81 @@ WARNING: The port is highly experimental and any APIs are subject to change.
Currently implemented features include:
- REPL (Python prompt) over UART0.
- 24k heap RAM available for Python code.
- Garbage collector, exceptions.
- Unicode support.
- Builtin modules: gc, array, collections, io, struct, sys, esp, network.
- C long-long type used as bignum implementation (gives 64 bit signed ints).
- Rudimentary WiFi support in station mode.
- Sockets with callbacks.
- Basic GPIO support.
Note that floating-point numbers are not supported.
- Builtin modules: gc, array, collections, io, struct, sys, esp, network,
many more.
- Arbitrary-precision long integers and 30-bit precision floats.
- Basic WiFi support.
- Sockets using modlwip.
- GPIO and bit-banging I2C, SPI support.
- 1-Wire and WS2812 (aka Neopixel) protocols support.
On the TODO list:
- Full wifi support.
- Internal filesystem using the flash.
- ...
Work-in-progress documentation is available at
http://docs.micropython.org/en/latest/esp8266/ .
Build instructions
------------------
The tool chain required for the build is the OpenSource ESP SDK, which can be
found at <https://github.com/pfalcon/esp-open-sdk>. Clone this repository and
run `make` in its directory to build and install the SDK locally.
run `make` in its directory to build and install the SDK locally. Make sure
to add toolchain bin directory to your PATH. Read esp-open-sdk's README for
additional important information on toolchain setup.
Add the external dependencies to the MicroPython repository checkout:
```bash
$ git submodule update --init
```
See the README in the repository root for more information about external
dependencies.
Then, to build MicroPython for the ESP8266, just run:
```bash
$ cd esp8266
$ make
```
This should produce binary images in the `build/` subdirectory. To flash them
to your ESP8266, use:
This will produce binary images in the `build/` subdirectory. If you install
MicroPython to your module for the first time, or after installing any other
firmware, you should erase flash completely:
```
esptool.py --port /dev//ttyXXX erase_flash
```
Erase flash also as a troubleshooting measure, if a module doesn't behave as
expected.
To flash MicroPython image to your ESP8266, use:
```bash
$ make deploy
```
This will use the `esptool.py` script to download the images. You must have
your ESP module in the bootloader, and connected to a serial port on your PC.
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:
```bash
$ make PORT=/dev/ttyUSB0 deploy
```
The images that are built are:
- `firmware.elf-0x00000.bin`: to be flashed at 0x00000
- `firmware.elf-0x10000.bin`: to be flashed at 0x10000
The image produced is `firmware-combined.bin`, to be flashed at 0x00000.
There is also a combined image, made up of the above 2 binary files with the
appropriate padding:
- `firmware-combined.bin`: to be flashed at 0x00000
Troubleshooting
---------------
While the port is still in alpha, it's known to be generally stable. If you
experience strange bootloops, crashes, lockups, here's a list to check against:
- You didn't erase flash before programming MicroPython firmware.
- Firmware can be occasionally flashed incorrectly. Just retry. Recent
esptool.py versions have --verify option.
- Power supply you use doesn't provide enough power for ESP8266 or isn't
stable enough.
- A module/flash may be defective (not unheard of for cheap modules).
Please consult dedicated ESP8266 forums/resources for hardware-related
problems.

View File

@@ -132,12 +132,12 @@ PROVIDE ( ets_memcmp = 0x400018d4 );
PROVIDE ( ets_memcpy = 0x400018b4 );
PROVIDE ( ets_memmove = 0x400018c4 );
PROVIDE ( ets_memset = 0x400018a4 );
PROVIDE ( ets_post = 0x40000e24 );
PROVIDE ( _ets_post = 0x40000e24 );
PROVIDE ( ets_printf = 0x400024cc );
PROVIDE ( ets_putc = 0x40002be8 );
PROVIDE ( ets_rtc_int_register = 0x40002a40 );
PROVIDE ( ets_run = 0x40000e04 );
PROVIDE ( ets_set_idle_cb = 0x40000dc0 );
PROVIDE ( _ets_run = 0x40000e04 );
PROVIDE ( _ets_set_idle_cb = 0x40000dc0 );
PROVIDE ( ets_set_user_start = 0x40000fbc );
PROVIDE ( ets_str2macaddr = 0x40002af8 );
PROVIDE ( ets_strcmp = 0x40002aa8 );
@@ -146,12 +146,12 @@ PROVIDE ( ets_strlen = 0x40002ac8 );
PROVIDE ( ets_strncmp = 0x40002ab8 );
PROVIDE ( ets_strncpy = 0x40002a98 );
PROVIDE ( ets_strstr = 0x40002ad8 );
PROVIDE ( ets_task = 0x40000dd0 );
PROVIDE ( _ets_task = 0x40000dd0 );
PROVIDE ( ets_timer_arm = 0x40002cc4 );
PROVIDE ( ets_timer_disarm = 0x40002d40 );
PROVIDE ( ets_timer_done = 0x40002d80 );
PROVIDE ( ets_timer_handler_isr = 0x40002da8 );
PROVIDE ( ets_timer_init = 0x40002e68 );
PROVIDE ( _ets_timer_init = 0x40002e68 );
PROVIDE ( ets_timer_setfn = 0x40002c48 );
PROVIDE ( ets_uart_printf = 0x40002544 );
PROVIDE ( ets_update_cpu_frequency = 0x40002f04 );
@@ -343,5 +343,8 @@ PROVIDE ( xthal_window_spill = 0x4000e324 );
PROVIDE ( xthal_window_spill_nw = 0x4000e320 );
PROVIDE ( Te0 = 0x3fffccf0 );
PROVIDE ( Td0 = 0x3fffd100 );
PROVIDE ( Td4s = 0x3fffd500);
PROVIDE ( rcons = 0x3fffd0f0);
PROVIDE ( UartDev = 0x3fffde10 );
PROVIDE ( flashchip = 0x3fffc714);

View File

@@ -5,7 +5,7 @@ MEMORY
dport0_0_seg : org = 0x3ff00000, len = 0x10
dram0_0_seg : org = 0x3ffe8000, len = 0x14000
iram1_0_seg : org = 0x40100000, len = 0x8000
irom0_0_seg : org = 0x40210000, len = 0x5A000
irom0_0_seg : org = 0x40209000, len = 0x80000
}
/* define the top of RAM */
@@ -80,26 +80,84 @@ SECTIONS
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
/* we put some specific text in this section */
*py/*.o*(.literal* .text*)
*pyexec.o(.literal*, .text*)
*readline.o(.literal*, .text*)
*pybstdio.o(.literal*, .text*)
*py/argcheck.o*(.literal* .text*)
*py/asm*.o*(.literal* .text*)
*py/bc.o*(.literal* .text*)
*py/binary.o*(.literal* .text*)
*py/builtin*.o*(.literal* .text*)
*py/compile.o*(.literal* .text*)
*py/emit*.o*(.literal* .text*)
*py/formatfloat.o*(.literal* .text*)
*py/frozenmod.o*(.literal* .text*)
*py/gc.o*(.literal* .text*)
*py/lexer*.o*(.literal* .text*)
*py/malloc*.o*(.literal* .text*)
*py/map*.o*(.literal* .text*)
*py/mod*.o*(.literal* .text*)
*py/mpprint.o*(.literal* .text*)
*py/mpstate.o*(.literal* .text*)
*py/mpz.o*(.literal* .text*)
*py/native*.o*(.literal* .text*)
*py/nlr*.o*(.literal* .text*)
*py/obj*.o*(.literal* .text*)
*py/opmethods.o*(.literal* .text*)
*py/parse*.o*(.literal* .text*)
*py/qstr.o*(.literal* .text*)
*py/repl.o*(.literal* .text*)
*py/runtime.o*(.literal* .text*)
*py/scope.o*(.literal* .text*)
*py/sequence.o*(.literal* .text*)
*py/showbc.o*(.literal* .text*)
*py/smallint.o*(.literal* .text*)
*py/stackctrl.o*(.literal* .text*)
*py/stream.o*(.literal* .text*)
*py/unicode.o*(.literal* .text*)
*py/vm.o*(.literal* .text*)
*py/vstr.o*(.literal* .text*)
*py/warning.o*(.literal* .text*)
*extmod/*.o*(.literal* .text*)
*lib/fatfs/*.o*(.literal*, .text*)
*lib/libm/*.o*(.literal*, .text*)
*lib/mp-readline/*.o(.literal*, .text*)
*lib/netutils/*.o*(.literal*, .text*)
*lib/timeutils/*.o*(.literal*, .text*)
*lib/utils/*.o*(.literal*, .text*)
*stmhal/pybstdio.o(.literal*, .text*)
*gccollect.o(.literal* .text*)
*gchelper.o(.literal* .text*)
*lexerstr32.o(.literal* .text*)
*utils.o(.literal* .text*)
*modpyb.o(.literal*, .text*)
*modpybpin.o(.literal*, .text*)
*modpybpwm.o(.literal*, .text*)
*modpybrtc.o(.literal*, .text*)
*modpybadc.o(.literal*, .text*)
*modpybuart.o(.literal*, .text*)
*modpybi2c.o(.literal*, .text*)
*modpybspi.o(.literal*, .text*)
*modesp.o(.literal* .text*)
*modnetwork.o(.literal* .text*)
*moduos.o(.literal* .text*)
*modutime.o(.literal* .text*)
*modlwip.o(.literal* .text*)
*modsocket.o(.literal* .text*)
/* we put as much rodata as possible in this section */
/* note that only rodata accessed as a machine word is allowed here */
*py/qstr.o(.rodata.const_pool)
*py/*.o(.rodata.mp_type_*) /* catches type: mp_obj_type_t */
*py/*.o(.rodata.*_locals_dict*) /* catches types: mp_obj_dict_t, mp_map_elem_t */
*py/*.o(.rodata.mp_module_*) /* catches types: mp_obj_module_t, mp_obj_dict_t, mp_map_elem_t */
*.o(.rodata.mp_type_*) /* catches type: mp_obj_type_t */
*.o(.rodata.*_locals_dict*) /* catches types: mp_obj_dict_t, mp_map_elem_t */
*.o(.rodata.mp_module_*) /* catches types: mp_obj_module_t, mp_obj_dict_t, mp_map_elem_t */
*/frozen.o(.rodata.mp_frozen_sizes) /* frozen modules */
*/frozen.o(.rodata.mp_frozen_content) /* frozen modules */
/* for -mforce-l32 */
build/*.o(.rodata*)
_irom0_text_end = ABSOLUTE(.);
} >irom0_0_seg :irom0_0_phdr
@@ -172,6 +230,7 @@ SECTIONS
.rodata : ALIGN(4)
{
_rodata_start = ABSOLUTE(.);
*(.sdk.version)
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)

View File

@@ -30,13 +30,24 @@
#include "uart.h"
#include "esp_mphal.h"
#include "user_interface.h"
#include "ets_alt_task.h"
#include "py/obj.h"
#include "py/mpstate.h"
#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
mp_hal_rtc_init();
uart_init(UART_BIT_RATE_115200, UART_BIT_RATE_115200);
}
@@ -47,12 +58,15 @@ void mp_hal_feed_watchdog(void) {
}
void mp_hal_delay_us(uint32_t us) {
ets_delay_us(us);
uint32_t start = system_get_time();
while (system_get_time() - start < us) {
ets_event_poll();
}
}
int mp_hal_stdin_rx_chr(void) {
for (;;) {
int c = uart0_rx();
int c = ringbuf_get(&input_buf);
if (c != -1) {
return c;
}
@@ -61,19 +75,43 @@ int mp_hal_stdin_rx_chr(void) {
}
}
void mp_hal_stdout_tx_str(const char *str) {
void mp_hal_stdout_tx_char(char c) {
uart_tx_one_char(UART0, c);
mp_uos_dupterm_tx_strn(&c, 1);
}
#if 0
void mp_hal_debug_str(const char *str) {
while (*str) {
uart_tx_one_char(UART0, *str++);
}
uart_flush(UART0);
}
#endif
void mp_hal_stdout_tx_str(const char *str) {
while (*str) {
mp_hal_stdout_tx_char(*str++);
}
}
void mp_hal_stdout_tx_strn(const char *str, uint32_t len) {
while (len--) {
uart_tx_one_char(UART0, *str++);
mp_hal_stdout_tx_char(*str++);
}
}
void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len) {
while (len--) {
if (*str == '\n') {
mp_hal_stdout_tx_char('\r');
}
mp_hal_stdout_tx_char(*str++);
}
}
void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len) {
(void)env;
while (len--) {
if (*str == '\n') {
uart_tx_one_char(UART0, '\r');
@@ -86,10 +124,95 @@ uint32_t mp_hal_ticks_ms(void) {
return system_get_time() / 1000;
}
uint32_t mp_hal_ticks_us(void) {
return system_get_time();
}
void mp_hal_delay_ms(uint32_t delay) {
mp_hal_delay_us(delay * 1000);
}
void mp_hal_set_interrupt_char(int c) {
// TODO
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) {
mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
nlr_raise(obj);
}
}
void __assert_func(const char *file, int line, const char *func, const char *expr) {
printf("assert:%s:%d:%s: %s\n", file, line, func, expr);
nlr_raise(mp_obj_new_exception_msg(&mp_type_AssertionError,
"C-level assert"));
}
void mp_hal_signal_input(void) {
#if MICROPY_REPL_EVENT_DRIVEN
system_os_post(UART_TASK_ID, 0, 0);
#endif
}
static int call_dupterm_read(void) {
if (MP_STATE_PORT(term_obj) == NULL) {
return -1;
}
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_obj_t read_m[3];
mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_read, read_m);
read_m[2] = MP_OBJ_NEW_SMALL_INT(1);
mp_obj_t res = mp_call_method_n_kw(1, 0, read_m);
if (res == mp_const_none) {
return -2;
}
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ);
if (bufinfo.len == 0) {
mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n");
MP_STATE_PORT(term_obj) = NULL;
return -1;
}
nlr_pop();
return *(byte*)bufinfo.buf;
} else {
// Temporarily disable dupterm to avoid infinite recursion
mp_obj_t save_term = MP_STATE_PORT(term_obj);
MP_STATE_PORT(term_obj) = NULL;
mp_printf(&mp_plat_print, "dupterm: ");
mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
MP_STATE_PORT(term_obj) = save_term;
}
return -1;
}
STATIC void dupterm_task_handler(os_event_t *evt) {
while (1) {
int c = call_dupterm_read();
if (c < 0) {
break;
}
ringbuf_put(&input_buf, c);
}
mp_hal_signal_input();
}
STATIC os_event_t dupterm_evt_queue[4];
void dupterm_task_init() {
system_os_task(dupterm_task_handler, DUPTERM_TASK_ID, dupterm_evt_queue, MP_ARRAY_SIZE(dupterm_evt_queue));
}
void mp_hal_signal_dupterm_input(void) {
system_os_post(DUPTERM_TASK_ID, 0, 0);
}

View File

@@ -27,18 +27,33 @@
#ifndef _INCLUDED_MPHAL_H_
#define _INCLUDED_MPHAL_H_
// SDK functions not declared in SDK itself
void ets_isr_mask(unsigned);
#include "py/ringbuf.h"
struct _mp_print_t;
// Structure for UART-only output via mp_printf()
extern const struct _mp_print_t mp_debug_print;
extern ringbuf_t input_buf;
// Call this after putting data to input_buf
void mp_hal_signal_input(void);
// Call this when data is available in dupterm object
void mp_hal_signal_dupterm_input(void);
void mp_hal_init(void);
void mp_hal_rtc_init(void);
void mp_hal_feed_watchdog(void);
uint32_t mp_hal_ticks_us(void);
void mp_hal_delay_us(uint32_t);
void mp_hal_set_interrupt_char(int c);
uint32_t mp_hal_get_cpu_freq(void);
#define UART_TASK_ID 0
#define DUPTERM_TASK_ID 1
void uart_task_init();
void dupterm_task_init();
void ets_event_poll(void);
#define ETS_POLL_WHILE(cond) { while (cond) ets_event_poll(); }
#endif // _INCLUDED_MPHAL_H_

64
esp8266/espneopixel.c Normal file
View File

@@ -0,0 +1,64 @@
// Original version from https://github.com/adafruit/Adafruit_NeoPixel
// Modifications by dpgeorge to support auto-CPU-frequency detection
// This is a mash-up of the Due show() code + insights from Michael Miller's
// ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus
// Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution.
#include "c_types.h"
#include "eagle_soc.h"
#include "user_interface.h"
#include "espneopixel.h"
#define NEO_KHZ400 (1)
static uint32_t _getCycleCount(void) __attribute__((always_inline));
static inline uint32_t _getCycleCount(void) {
uint32_t ccount;
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
return ccount;
}
void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz) {
uint8_t *p, *end, pix, mask;
uint32_t t, time0, time1, period, c, startTime, pinMask;
pinMask = 1 << pin;
p = pixels;
end = p + numBytes;
pix = *p++;
mask = 0x80;
startTime = 0;
uint32_t fcpu = system_get_cpu_freq() * 1000000;
#ifdef NEO_KHZ400
if(is800KHz) {
#endif
time0 = fcpu / 2500000; // 0.4us
time1 = fcpu / 1250000; // 0.8us
period = fcpu / 800000; // 1.25us per bit
#ifdef NEO_KHZ400
} else { // 400 KHz bitstream
time0 = fcpu / 2000000; // 0.5uS
time1 = fcpu / 833333; // 1.2us
period = fcpu / 400000; // 2.5us per bit
}
#endif
for(t = time0;; t = time0) {
if(pix & mask) t = time1; // Bit high duration
while(((c = _getCycleCount()) - startTime) < period); // Wait for bit start
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high
startTime = c; // Save start time
while(((c = _getCycleCount()) - startTime) < t); // Wait high duration
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low
if(!(mask >>= 1)) { // Next bit/byte
if(p >= end) break;
pix = *p++;
mask = 0x80;
}
}
while((_getCycleCount() - startTime) < period); // Wait for last bit
}

1
esp8266/espneopixel.h Normal file
View File

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

428
esp8266/esppwm.c Normal file
View File

@@ -0,0 +1,428 @@
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: pwm.c
*
* Description: pwm driver
*
* Modification history:
* 2014/5/1, v1.0 create this file.
* 2016/3/2: Modifications by dpgeorge to suit MicroPython
*******************************************************************************/
#include <stdio.h>
#include <string.h>
#include "etshal.h"
#include "os_type.h"
#include "gpio.h"
#include "esppwm.h"
#include "py/mpprint.h"
#define PWM_DBG(...)
//#define PWM_DBG(...) mp_printf(&mp_plat_print, __VA_ARGS__)
#define ICACHE_RAM_ATTR // __attribute__((section(".text")))
#define PWM_CHANNEL 8
#define PWM_DEPTH 1023
#define PWM_FREQ_MAX 1000
#define PWM_1S 1000000
struct pwm_single_param {
uint16_t gpio_set;
uint16_t gpio_clear;
uint32_t h_time;
};
struct pwm_param {
uint32_t period;
uint16_t freq;
uint16_t duty[PWM_CHANNEL];
};
STATIC const uint8_t pin_num[PWM_CHANNEL] = {0, 2, 4, 5, 12, 13, 14, 15};
STATIC struct pwm_single_param pwm_single_toggle[2][PWM_CHANNEL + 1];
STATIC struct pwm_single_param *pwm_single;
STATIC struct pwm_param pwm;
STATIC int8_t pwm_out_io_num[PWM_CHANNEL] = {-1, -1, -1, -1, -1, -1, -1, -1};
STATIC uint8_t pwm_channel_toggle[2];
STATIC uint8_t *pwm_channel;
STATIC uint8_t pwm_toggle = 1;
STATIC uint8_t pwm_timer_down = 1;
STATIC uint8_t pwm_current_channel = 0;
STATIC uint16_t pwm_gpio = 0;
STATIC uint8_t pwm_channel_num = 0;
//XXX: 0xffffffff/(80000000/16)=35A
#define US_TO_RTC_TIMER_TICKS(t) \
((t) ? \
(((t) > 0x35A) ? \
(((t)>>2) * ((APB_CLK_FREQ>>4)/250000) + ((t)&0x3) * ((APB_CLK_FREQ>>4)/1000000)) : \
(((t) *(APB_CLK_FREQ>>4)) / 1000000)) : \
0)
//FRC1
#define FRC1_ENABLE_TIMER BIT7
typedef enum {
DIVDED_BY_1 = 0,
DIVDED_BY_16 = 4,
DIVDED_BY_256 = 8,
} TIMER_PREDIVED_MODE;
typedef enum {
TM_LEVEL_INT = 1,
TM_EDGE_INT = 0,
} TIMER_INT_MODE;
STATIC void ICACHE_FLASH_ATTR
pwm_insert_sort(struct pwm_single_param pwm[], uint8 n)
{
uint8 i;
for (i = 1; i < n; i++) {
if (pwm[i].h_time < pwm[i - 1].h_time) {
int8 j = i - 1;
struct pwm_single_param tmp;
memcpy(&tmp, &pwm[i], sizeof(struct pwm_single_param));
memcpy(&pwm[i], &pwm[i - 1], sizeof(struct pwm_single_param));
while (tmp.h_time < pwm[j].h_time) {
memcpy(&pwm[j + 1], &pwm[j], sizeof(struct pwm_single_param));
j--;
if (j < 0) {
break;
}
}
memcpy(&pwm[j + 1], &tmp, sizeof(struct pwm_single_param));
}
}
}
STATIC volatile uint8 critical = 0;
#define LOCK_PWM(c) do { \
while( (c)==1 ); \
(c) = 1; \
} while (0)
#define UNLOCK_PWM(c) do { \
(c) = 0; \
} while (0)
void ICACHE_FLASH_ATTR
pwm_start(void)
{
uint8 i, j;
PWM_DBG("--Function pwm_start() is called\n");
PWM_DBG("pwm_gpio:%x,pwm_channel_num:%d\n",pwm_gpio,pwm_channel_num);
PWM_DBG("pwm_out_io_num[0]:%d,[1]:%d,[2]:%d\n",pwm_out_io_num[0],pwm_out_io_num[1],pwm_out_io_num[2]);
PWM_DBG("pwm.period:%d,pwm.duty[0]:%d,[1]:%d,[2]:%d\n",pwm.period,pwm.duty[0],pwm.duty[1],pwm.duty[2]);
LOCK_PWM(critical); // enter critical
struct pwm_single_param *local_single = pwm_single_toggle[pwm_toggle ^ 0x01];
uint8 *local_channel = &pwm_channel_toggle[pwm_toggle ^ 0x01];
// step 1: init PWM_CHANNEL+1 channels param
for (i = 0; i < pwm_channel_num; i++) {
uint32 us = pwm.period * pwm.duty[i] / PWM_DEPTH;
local_single[i].h_time = US_TO_RTC_TIMER_TICKS(us);
PWM_DBG("i:%d us:%d ht:%d\n",i,us,local_single[i].h_time);
local_single[i].gpio_set = 0;
local_single[i].gpio_clear = 1 << pin_num[pwm_out_io_num[i]];
}
local_single[pwm_channel_num].h_time = US_TO_RTC_TIMER_TICKS(pwm.period);
local_single[pwm_channel_num].gpio_set = pwm_gpio;
local_single[pwm_channel_num].gpio_clear = 0;
PWM_DBG("i:%d period:%d ht:%d\n",pwm_channel_num,pwm.period,local_single[pwm_channel_num].h_time);
// step 2: sort, small to big
pwm_insert_sort(local_single, pwm_channel_num + 1);
*local_channel = pwm_channel_num + 1;
PWM_DBG("1channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d\n",*local_channel,local_single[0].h_time,local_single[1].h_time,local_single[2].h_time,local_single[3].h_time);
// step 3: combine same duty channels
for (i = pwm_channel_num; i > 0; i--) {
if (local_single[i].h_time == local_single[i - 1].h_time) {
local_single[i - 1].gpio_set |= local_single[i].gpio_set;
local_single[i - 1].gpio_clear |= local_single[i].gpio_clear;
for (j = i + 1; j < *local_channel; j++) {
memcpy(&local_single[j - 1], &local_single[j], sizeof(struct pwm_single_param));
}
(*local_channel)--;
}
}
PWM_DBG("2channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d\n",*local_channel,local_single[0].h_time,local_single[1].h_time,local_single[2].h_time,local_single[3].h_time);
// step 4: cacl delt time
for (i = *local_channel - 1; i > 0; i--) {
local_single[i].h_time -= local_single[i - 1].h_time;
}
// step 5: last channel needs to clean
local_single[*local_channel-1].gpio_clear = 0;
// step 6: if first channel duty is 0, remove it
if (local_single[0].h_time == 0) {
local_single[*local_channel - 1].gpio_set &= ~local_single[0].gpio_clear;
local_single[*local_channel - 1].gpio_clear |= local_single[0].gpio_clear;
for (i = 1; i < *local_channel; i++) {
memcpy(&local_single[i - 1], &local_single[i], sizeof(struct pwm_single_param));
}
(*local_channel)--;
}
// if timer is down, need to set gpio and start timer
if (pwm_timer_down == 1) {
pwm_channel = local_channel;
pwm_single = local_single;
// start
gpio_output_set(local_single[0].gpio_set, local_single[0].gpio_clear, pwm_gpio, 0);
// yeah, if all channels' duty is 0 or 255, don't need to start timer, otherwise start...
if (*local_channel != 1) {
pwm_timer_down = 0;
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, local_single[0].h_time);
}
}
if (pwm_toggle == 1) {
pwm_toggle = 0;
} else {
pwm_toggle = 1;
}
UNLOCK_PWM(critical); // leave critical
PWM_DBG("3channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d\n",*local_channel,local_single[0].h_time,local_single[1].h_time,local_single[2].h_time,local_single[3].h_time);
}
/******************************************************************************
* FunctionName : pwm_set_duty
* Description : set each channel's duty params
* Parameters : uint8 duty : 0 ~ PWM_DEPTH
* uint8 channel : channel index
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
pwm_set_duty(uint16 duty, uint8 channel)
{
uint8 i;
for(i=0;i<pwm_channel_num;i++){
if(pwm_out_io_num[i] == channel){
channel = i;
break;
}
}
if(i==pwm_channel_num) // non found
return;
LOCK_PWM(critical); // enter critical
if (duty < 1) {
pwm.duty[channel] = 0;
} else if (duty >= PWM_DEPTH) {
pwm.duty[channel] = PWM_DEPTH;
} else {
pwm.duty[channel] = duty;
}
UNLOCK_PWM(critical); // leave critical
}
/******************************************************************************
* FunctionName : pwm_set_freq
* Description : set pwm frequency
* Parameters : uint16 freq : 100hz typically
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
pwm_set_freq(uint16 freq, uint8 channel)
{
LOCK_PWM(critical); // enter critical
if (freq > PWM_FREQ_MAX) {
pwm.freq = PWM_FREQ_MAX;
} else if (freq < 1) {
pwm.freq = 1;
} else {
pwm.freq = freq;
}
pwm.period = PWM_1S / pwm.freq;
UNLOCK_PWM(critical); // leave critical
}
/******************************************************************************
* FunctionName : pwm_get_duty
* Description : get duty of each channel
* Parameters : uint8 channel : channel index
* Returns : NONE
*******************************************************************************/
uint16 ICACHE_FLASH_ATTR
pwm_get_duty(uint8 channel)
{
uint8 i;
for(i=0;i<pwm_channel_num;i++){
if(pwm_out_io_num[i] == channel){
channel = i;
break;
}
}
if(i==pwm_channel_num) // non found
return 0;
return pwm.duty[channel];
}
/******************************************************************************
* FunctionName : pwm_get_freq
* Description : get pwm frequency
* Parameters : NONE
* Returns : uint16 : pwm frequency
*******************************************************************************/
uint16 ICACHE_FLASH_ATTR
pwm_get_freq(uint8 channel)
{
return pwm.freq;
}
/******************************************************************************
* FunctionName : pwm_period_timer
* Description : pwm period timer function, output high level,
* start each channel's high level timer
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
STATIC void ICACHE_RAM_ATTR
pwm_tim1_intr_handler(void *dummy)
{
(void)dummy;
uint8 local_toggle = pwm_toggle; // pwm_toggle may change outside
RTC_CLR_REG_MASK(FRC1_INT_ADDRESS, FRC1_INT_CLR_MASK);
if (pwm_current_channel >= (*pwm_channel - 1)) { // *pwm_channel may change outside
pwm_single = pwm_single_toggle[local_toggle];
pwm_channel = &pwm_channel_toggle[local_toggle];
gpio_output_set(pwm_single[*pwm_channel - 1].gpio_set,
pwm_single[*pwm_channel - 1].gpio_clear,
pwm_gpio,
0);
pwm_current_channel = 0;
if (*pwm_channel != 1) {
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, pwm_single[pwm_current_channel].h_time);
} else {
pwm_timer_down = 1;
}
} else {
gpio_output_set(pwm_single[pwm_current_channel].gpio_set,
pwm_single[pwm_current_channel].gpio_clear,
pwm_gpio, 0);
pwm_current_channel++;
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, pwm_single[pwm_current_channel].h_time);
}
}
/******************************************************************************
* FunctionName : pwm_init
* Description : pwm gpio, params and timer initialization
* Parameters : uint16 freq : pwm freq param
* uint16 *duty : each channel's duty
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
pwm_init(void)
{
uint8 i;
RTC_REG_WRITE(FRC1_CTRL_ADDRESS, //FRC2_AUTO_RELOAD|
DIVDED_BY_16
| FRC1_ENABLE_TIMER
| TM_EDGE_INT);
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, 0);
for (i = 0; i < PWM_CHANNEL; i++) {
pwm_gpio = 0;
pwm.duty[i] = 0;
}
pwm_set_freq(500, 0);
pwm_start();
ETS_FRC_TIMER1_INTR_ATTACH(pwm_tim1_intr_handler, NULL);
TM1_EDGE_INT_ENABLE();
ETS_FRC1_INTR_ENABLE();
}
int ICACHE_FLASH_ATTR
pwm_add(uint8_t pin_id, uint32_t pin_mux, uint32_t pin_func){
PWM_DBG("--Function pwm_add() is called. channel:%d\n", channel);
PWM_DBG("pwm_gpio:%x,pwm_channel_num:%d\n",pwm_gpio,pwm_channel_num);
PWM_DBG("pwm_out_io_num[0]:%d,[1]:%d,[2]:%d\n",pwm_out_io_num[0],pwm_out_io_num[1],pwm_out_io_num[2]);
PWM_DBG("pwm.duty[0]:%d,[1]:%d,[2]:%d\n",pwm.duty[0],pwm.duty[1],pwm.duty[2]);
int channel = -1;
for (int i = 0; i < PWM_CHANNEL; ++i) {
if (pin_num[i] == pin_id) {
channel = i;
break;
}
}
if (channel == -1) {
return -1;
}
uint8 i;
for(i=0;i<PWM_CHANNEL;i++){
if(pwm_out_io_num[i]==channel) // already exist
return channel;
if(pwm_out_io_num[i] == -1){ // empty exist
LOCK_PWM(critical); // enter critical
pwm_out_io_num[i] = channel;
pwm.duty[i] = 0;
pwm_gpio |= (1 << pin_num[channel]);
PIN_FUNC_SELECT(pin_mux, pin_func);
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[channel])), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[channel]))) & (~ GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE))); //disable open drain;
pwm_channel_num++;
UNLOCK_PWM(critical); // leave critical
return channel;
}
}
return -1;
}
bool ICACHE_FLASH_ATTR
pwm_delete(uint8 channel){
PWM_DBG("--Function pwm_delete() is called. channel:%d\n", channel);
PWM_DBG("pwm_gpio:%x,pwm_channel_num:%d\n",pwm_gpio,pwm_channel_num);
PWM_DBG("pwm_out_io_num[0]:%d,[1]:%d,[2]:%d\n",pwm_out_io_num[0],pwm_out_io_num[1],pwm_out_io_num[2]);
PWM_DBG("pwm.duty[0]:%d,[1]:%d,[2]:%d\n",pwm.duty[0],pwm.duty[1],pwm.duty[2]);
uint8 i,j;
for(i=0;i<pwm_channel_num;i++){
if(pwm_out_io_num[i]==channel){ // exist
LOCK_PWM(critical); // enter critical
pwm_out_io_num[i] = -1;
pwm_gpio &= ~(1 << pin_num[channel]); //clear the bit
for(j=i;j<pwm_channel_num-1;j++){
pwm_out_io_num[j] = pwm_out_io_num[j+1];
pwm.duty[j] = pwm.duty[j+1];
}
pwm_out_io_num[pwm_channel_num-1] = -1;
pwm.duty[pwm_channel_num-1] = 0;
pwm_channel_num--;
UNLOCK_PWM(critical); // leave critical
return true;
}
}
// non found
return true;
}

17
esp8266/esppwm.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef __ESPPWM_H__
#define __ESPPWM_H__
#include <stdbool.h>
#include <stdint.h>
void pwm_init(void);
void pwm_start(void);
void pwm_set_duty(uint16_t duty, uint8_t channel);
uint16_t pwm_get_duty(uint8_t channel);
void pwm_set_freq(uint16_t freq, uint8_t channel);
uint16_t pwm_get_freq(uint8_t channel);
int pwm_add(uint8_t pin_id, uint32_t pin_mux, uint32_t pin_func);
bool pwm_delete(uint8_t channel);
#endif

194
esp8266/ets_alt_task.c Normal file
View File

@@ -0,0 +1,194 @@
#include <stdio.h>
#include "osapi.h"
#include "os_type.h"
#include "ets_sys.h"
#include <esp_sdk_ver.h>
#include "etshal.h"
#include "user_interface.h"
// Use standard ets_task or alternative impl
#define USE_ETS_TASK 0
#define MP_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
struct task_entry {
os_event_t *queue;
os_task_t task;
uint8_t qlen;
uint8_t prio;
int8_t i_get;
int8_t i_put;
};
static void (*idle_cb)(void *);
static void *idle_arg;
#if ESP_SDK_VERSION >= 010500
# define FIRST_PRIO 0
#else
# define FIRST_PRIO 0x14
#endif
#define LAST_PRIO 0x20
#define PRIO2ID(prio) ((prio) - FIRST_PRIO)
volatile struct task_entry emu_tasks[PRIO2ID(LAST_PRIO) + 1];
static inline int prio2id(uint8_t prio) {
int id = PRIO2ID(prio);
if (id < 0 || id >= MP_ARRAY_SIZE(emu_tasks)) {
printf("task prio out of range: %d\n", prio);
while (1);
}
return id;
}
#if DEBUG
void dump_task(int prio, volatile struct task_entry *t) {
printf("q for task %d: queue: %p, get ptr: %d, put ptr: %d, qlen: %d\n",
prio, t->queue, t->i_get, t->i_put, t->qlen);
}
void dump_tasks(void) {
for (int i = 0; i < MP_ARRAY_SIZE(emu_tasks); i++) {
if (emu_tasks[i].qlen) {
dump_task(i + FIRST_PRIO, &emu_tasks[i]);
}
}
printf("====\n");
}
#endif
bool ets_task(os_task_t task, uint8 prio, os_event_t *queue, uint8 qlen) {
static unsigned cnt;
printf("#%d ets_task(%p, %d, %p, %d)\n", cnt++, task, prio, queue, qlen);
#if USE_ETS_TASK
return _ets_task(task, prio, queue, qlen);
#else
int id = prio2id(prio);
emu_tasks[id].task = task;
emu_tasks[id].queue = queue;
emu_tasks[id].qlen = qlen;
emu_tasks[id].i_get = 0;
emu_tasks[id].i_put = 0;
return true;
#endif
}
bool ets_post(uint8 prio, os_signal_t sig, os_param_t param) {
// static unsigned cnt; printf("#%d ets_post(%d, %x, %x)\n", cnt++, prio, sig, param);
#if USE_ETS_TASK
return _ets_post(prio, sig, param);
#else
ets_intr_lock();
const int id = prio2id(prio);
os_event_t *q = emu_tasks[id].queue;
if (emu_tasks[id].i_put == -1) {
// queue is full
printf("ets_post: task %d queue full\n", prio);
return false;
}
q = &q[emu_tasks[id].i_put++];
q->sig = sig;
q->par = param;
if (emu_tasks[id].i_put == emu_tasks[id].qlen) {
emu_tasks[id].i_put = 0;
}
if (emu_tasks[id].i_put == emu_tasks[id].i_get) {
// queue got full
emu_tasks[id].i_put = -1;
}
//printf("after ets_post: "); dump_task(prio, &emu_tasks[id]);
//dump_tasks();
ets_intr_unlock();
return true;
#endif
}
bool ets_loop_iter(void) {
//static unsigned cnt;
bool progress = false;
for (volatile struct task_entry *t = emu_tasks; t < &emu_tasks[MP_ARRAY_SIZE(emu_tasks)]; t++) {
system_soft_wdt_feed();
ets_intr_lock();
//printf("etc_loop_iter: "); dump_task(t - emu_tasks + FIRST_PRIO, t);
if (t->i_get != t->i_put) {
progress = true;
//printf("#%d Calling task %d(%p) (%x, %x)\n", cnt++,
// t - emu_tasks + FIRST_PRIO, t->task, t->queue[t->i_get].sig, t->queue[t->i_get].par);
int idx = t->i_get;
if (t->i_put == -1) {
t->i_put = t->i_get;
}
if (++t->i_get == t->qlen) {
t->i_get = 0;
}
//ets_intr_unlock();
t->task(&t->queue[idx]);
//ets_intr_lock();
//printf("Done calling task %d\n", t - emu_tasks + FIRST_PRIO);
}
ets_intr_unlock();
}
return progress;
}
#if SDK_BELOW_1_1_1
void my_timer_isr(void *arg) {
// uart0_write_char('+');
ets_post(0x1f, 0, 0);
}
// Timer init func is in ROM, and calls ets_task by relative addr directly in ROM
// so, we have to re-init task using our handler
void ets_timer_init() {
printf("ets_timer_init\n");
// _ets_timer_init();
ets_isr_attach(10, my_timer_isr, NULL);
SET_PERI_REG_MASK(0x3FF00004, 4);
ETS_INTR_ENABLE(10);
ets_task((os_task_t)0x40002E3C, 0x1f, (os_event_t*)0x3FFFDDC0, 4);
WRITE_PERI_REG(PERIPHS_TIMER_BASEDDR + 0x30, 0);
WRITE_PERI_REG(PERIPHS_TIMER_BASEDDR + 0x28, 0x88);
WRITE_PERI_REG(PERIPHS_TIMER_BASEDDR + 0x30, 0);
printf("Installed timer ISR\n");
}
#endif
bool ets_run(void) {
#if USE_ETS_TASK
#if SDK_BELOW_1_1_1
ets_isr_attach(10, my_timer_isr, NULL);
#endif
_ets_run();
#else
// ets_timer_init();
*(char*)0x3FFFC6FC = 0;
ets_intr_lock();
printf("ets_alt_task: ets_run\n");
#if DEBUG
dump_tasks();
#endif
ets_intr_unlock();
while (1) {
if (!ets_loop_iter()) {
//printf("idle\n");
ets_intr_lock();
if (idle_cb) {
idle_cb(idle_arg);
}
asm("waiti 0");
ets_intr_unlock();
}
}
#endif
}
void ets_set_idle_cb(void (*handler)(void *), void *arg) {
//printf("ets_set_idle_cb(%p, %p)\n", handler, arg);
idle_cb = handler;
idle_arg = arg;
}

1
esp8266/ets_alt_task.h Normal file
View File

@@ -0,0 +1 @@
bool ets_loop_iter(void);

View File

@@ -1,9 +1,23 @@
#ifndef _INCLUDED_ETSHAL_H_
#define _INCLUDED_ETSHAL_H_
void ets_isr_unmask();
#include <os_type.h>
// see http://esp8266-re.foogod.com/wiki/Random_Number_Generator
#define WDEV_HWRNG ((volatile uint32_t*)0x3ff20e44)
void ets_delay_us();
void ets_intr_lock(void);
void ets_intr_unlock(void);
void ets_isr_mask(uint32_t mask);
void ets_isr_unmask(uint32_t mask);
void ets_isr_attach(int irq_no, void (*handler)(void *), void *arg);
void ets_install_putc1();
void ets_isr_attach();
void uart_div_modify();
void ets_set_idle_cb(void (*handler)(void *), void *arg);
void ets_timer_arm_new(os_timer_t *tim, uint32_t millis, bool repeat, bool is_milli_timer);
void ets_timer_setfn(os_timer_t *tim, ETSTimerFunc callback, void *cb_data);
void ets_timer_disarm(os_timer_t *tim);
#endif // _INCLUDED_ETSHAL_H_

6
esp8266/fatfs_port.c Normal file
View File

@@ -0,0 +1,6 @@
#include "lib/fatfs/ff.h"
#include "lib/fatfs/diskio.h"
DWORD get_fattime(void) {
return 0;
}

View File

@@ -39,10 +39,6 @@ void gc_collect(void) {
// start the GC
gc_collect_start();
// We need to scan everything in RAM that can hold a pointer.
// The data segment is used, but should not contain pointers, so we just scan the bss.
gc_collect_root((void**)&_bss_start, ((uint32_t)&_bss_end - (uint32_t)&_bss_start) / sizeof(uint32_t));
// get the registers and the sp
mp_uint_t regs[8];
mp_uint_t sp = gc_helper_get_regs_and_sp(regs);

69
esp8266/lexerstr32.c Normal file
View File

@@ -0,0 +1,69 @@
/*
* 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/lexer.h"
#if MICROPY_ENABLE_COMPILER
typedef struct _mp_lexer_str32_buf_t {
const uint32_t *src_cur;
uint32_t val;
uint8_t byte_off;
} mp_lexer_str32_buf_t;
STATIC mp_uint_t str32_buf_next_byte(mp_lexer_str32_buf_t *sb) {
byte c = sb->val & 0xff;
if (c == 0) {
return MP_LEXER_EOF;
}
if (++sb->byte_off > 3) {
sb->byte_off = 0;
sb->val = *sb->src_cur++;
} else {
sb->val >>= 8;
}
return c;
}
STATIC void str32_buf_free(mp_lexer_str32_buf_t *sb) {
m_del_obj(mp_lexer_str32_buf_t, sb);
}
mp_lexer_t *mp_lexer_new_from_str32(qstr src_name, const char *str, mp_uint_t len, mp_uint_t free_len) {
mp_lexer_str32_buf_t *sb = m_new_obj_maybe(mp_lexer_str32_buf_t);
if (sb == NULL) {
return NULL;
}
sb->byte_off = (uint32_t)str & 3;
sb->src_cur = (uint32_t*)(str - sb->byte_off);
sb->val = *sb->src_cur++ >> sb->byte_off * 8;
return mp_lexer_new(src_name, sb, (mp_lexer_stream_next_byte_t)str32_buf_next_byte, (mp_lexer_stream_close_t)str32_buf_free);
}
#endif // MICROPY_ENABLE_COMPILER

View File

@@ -32,59 +32,112 @@
#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/stackctrl.h"
#include "py/frozenmod.h"
#include "py/mphal.h"
#include "py/gc.h"
#include "lib/utils/pyexec.h"
#include "gccollect.h"
#include "user_interface.h"
STATIC char heap[16384];
STATIC char heap[24 * 1024];
STATIC void mp_reset(void) {
mp_stack_set_limit(10240);
mp_stack_set_top((void*)0x40000000);
mp_stack_set_limit(8192);
mp_hal_init();
gc_init(heap, heap + sizeof(heap));
mp_init();
mp_obj_list_init(mp_sys_path, 0);
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)));
#endif
MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
#if MICROPY_MODULE_FROZEN
mp_lexer_t *lex = mp_find_frozen_module("main", 4);
mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mp_globals_get(), mp_locals_get());
pyexec_frozen_module("_boot");
pyexec_file("boot.py");
pyexec_file("main.py");
#endif
}
void soft_reset(void) {
mp_hal_stdout_tx_str("PYB: soft reset\r\n");
mp_hal_stdout_tx_str("PYB: soft reboot\r\n");
mp_hal_delay_us(10000); // allow UART to flush output
mp_reset();
#if MICROPY_REPL_EVENT_DRIVEN
pyexec_event_repl_init();
#endif
}
void init_done(void) {
#if MICROPY_REPL_EVENT_DRIVEN
uart_task_init();
#endif
mp_reset();
mp_hal_stdout_tx_str("\r\n");
#if MICROPY_REPL_EVENT_DRIVEN
pyexec_event_repl_init();
uart_task_init();
#endif
dupterm_task_init();
#if !MICROPY_REPL_EVENT_DRIVEN
soft_reset:
for (;;) {
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
if (pyexec_raw_repl() != 0) {
break;
}
} else {
if (pyexec_friendly_repl() != 0) {
break;
}
}
}
soft_reset();
goto soft_reset;
#endif
}
void user_init(void) {
system_init_done_cb(init_done);
}
mp_lexer_t *fat_vfs_lexer_new_from_file(const char *filename);
mp_import_stat_t fat_vfs_import_stat(const char *path);
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
#if MICROPY_VFS_FAT
return fat_vfs_lexer_new_from_file(filename);
#else
(void)filename;
return NULL;
#endif
}
mp_import_stat_t mp_import_stat(const char *path) {
#if MICROPY_VFS_FAT
return fat_vfs_import_stat(path);
#else
(void)path;
return MP_IMPORT_STAT_NO_EXIST;
#endif
}
mp_obj_t vfs_proxy_call(qstr method_name, mp_uint_t n_args, const mp_obj_t *args);
mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) {
#if MICROPY_VFS_FAT
// TODO: Handle kwargs!
return vfs_proxy_call(MP_QSTR_open, n_args, args);
#else
return mp_const_none;
#endif
}
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

@@ -1,5 +1,7 @@
import sys
SEGS_MAX_SIZE = 0x9000
assert len(sys.argv) == 4
with open(sys.argv[3], 'wb') as fout:
@@ -9,7 +11,7 @@ with open(sys.argv[3], 'wb') as fout:
fout.write(data_flash)
print('flash ', len(data_flash))
pad = b'\xff' * (0x10000 - len(data_flash))
pad = b'\xff' * (SEGS_MAX_SIZE - len(data_flash))
fout.write(pad)
print('padding ', len(pad))
@@ -18,4 +20,4 @@ with open(sys.argv[3], 'wb') as fout:
fout.write(data_rom)
print('irom0text', len(data_rom))
print('total ', 0x10000 + len(data_rom))
print('total ', SEGS_MAX_SIZE + len(data_rom))

View File

@@ -27,6 +27,7 @@
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include "py/nlr.h"
#include "py/obj.h"
@@ -34,12 +35,18 @@
#include "py/runtime.h"
#include "netutils.h"
#include "queue.h"
#include "ets_sys.h"
#include "uart.h"
#include "user_interface.h"
#include "espconn.h"
#include "ip_addr.h"
#include "spi_flash.h"
#include "utils.h"
#include "espneopixel.h"
#include "modpyb.h"
#define MODESP_ESPCONN (0)
#if MODESP_ESPCONN
STATIC const mp_obj_type_t esp_socket_type;
typedef struct _esp_socket_obj_t {
@@ -79,7 +86,7 @@ STATIC mp_obj_t esp_socket_make_new_base() {
// constructor esp_socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None)
// Arguments ignored as we do not support UDP (yet)
STATIC mp_obj_t esp_socket_make_new(mp_obj_t type_in, mp_uint_t n_args,
STATIC mp_obj_t esp_socket_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, 4, false);
@@ -499,6 +506,7 @@ STATIC const mp_obj_type_t esp_socket_type = {
.make_new = esp_socket_make_new,
.locals_dict = (mp_obj_t)&esp_socket_locals_dict,
};
#endif
#define MODESP_INCLUDE_CONSTANTS (1)
@@ -508,25 +516,15 @@ void error_check(bool status, const char *msg) {
}
}
STATIC mp_obj_t esp_wifi_mode(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
return mp_obj_new_int(wifi_get_opmode());
STATIC mp_obj_t esp_osdebug(mp_obj_t val) {
if (val == mp_const_none) {
uart_os_config(-1);
} else {
wifi_set_opmode(mp_obj_get_int(args[0]));
return mp_const_none;
uart_os_config(mp_obj_get_int(val));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_wifi_mode_obj, 0, 1, esp_wifi_mode);
STATIC mp_obj_t esp_phy_mode(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
return mp_obj_new_int(wifi_get_phy_mode());
} else {
wifi_set_phy_mode(mp_obj_get_int(args[0]));
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_phy_mode_obj, 0, 1, esp_phy_mode);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_osdebug_obj, esp_osdebug);
STATIC mp_obj_t esp_sleep_type(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
@@ -538,26 +536,6 @@ STATIC mp_obj_t esp_sleep_type(mp_uint_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_sleep_type_obj, 0, 1, esp_sleep_type);
STATIC mp_obj_t esp_mac(mp_uint_t n_args, const mp_obj_t *args) {
uint8_t mac[6];
if (n_args == 0) {
wifi_get_macaddr(STATION_IF, mac);
return mp_obj_new_bytes(mac, sizeof(mac));
} else {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
if (bufinfo.len != 6) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"invalid buffer length"));
}
wifi_set_macaddr(STATION_IF, bufinfo.buf);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_mac_obj, 0, 1, esp_mac);
STATIC mp_obj_t esp_deepsleep(mp_uint_t n_args, const mp_obj_t *args) {
system_deep_sleep(n_args > 0 ? mp_obj_get_int(args[0]) : 0);
return mp_const_none;
@@ -569,26 +547,106 @@ STATIC mp_obj_t esp_flash_id() {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_id_obj, esp_flash_id);
STATIC mp_obj_t esp_flash_read(mp_obj_t offset_in, mp_obj_t len_or_buf_in) {
mp_int_t offset = mp_obj_get_int(offset_in);
mp_int_t len;
byte *buf;
bool alloc_buf = MP_OBJ_IS_INT(len_or_buf_in);
if (alloc_buf) {
len = mp_obj_get_int(len_or_buf_in);
buf = m_new(byte, len);
} else {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(len_or_buf_in, &bufinfo, MP_BUFFER_WRITE);
len = bufinfo.len;
buf = bufinfo.buf;
}
// We know that allocation will be 4-byte aligned for sure
SpiFlashOpResult res = spi_flash_read(offset, (uint32_t*)buf, len);
if (res == SPI_FLASH_RESULT_OK) {
if (alloc_buf) {
return mp_obj_new_bytes(buf, len);
}
return mp_const_none;
}
if (alloc_buf) {
m_del(byte, buf, len);
}
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? ETIMEDOUT : EIO)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_read_obj, esp_flash_read);
STATIC mp_obj_t esp_flash_write(mp_obj_t offset_in, const mp_obj_t buf_in) {
mp_int_t offset = mp_obj_get_int(offset_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
if (bufinfo.len & 0x3) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "len must be multiple of 4"));
}
SpiFlashOpResult res = spi_flash_write(offset, bufinfo.buf, bufinfo.len);
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 ? ETIMEDOUT : EIO)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_write_obj, esp_flash_write);
STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) {
mp_int_t sector = mp_obj_get_int(sector_in);
SpiFlashOpResult res = spi_flash_erase_sector(sector);
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 ? ETIMEDOUT : EIO)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_flash_erase_obj, esp_flash_erase);
STATIC mp_obj_t esp_neopixel_write_(mp_obj_t pin, mp_obj_t buf, mp_obj_t is800k) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
esp_neopixel_write(mp_obj_get_pin_obj(pin)->phys_port,
(uint8_t*)bufinfo.buf, bufinfo.len, mp_obj_is_true(is800k));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_neopixel_write_obj, esp_neopixel_write_);
STATIC mp_obj_t esp_freemem() {
return MP_OBJ_NEW_SMALL_INT(system_get_free_heap_size());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_freemem_obj, esp_freemem);
STATIC mp_obj_t esp_meminfo() {
system_print_meminfo();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_meminfo_obj, esp_meminfo);
STATIC const mp_map_elem_t esp_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_esp) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mac), (mp_obj_t)&esp_mac_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_getaddrinfo_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wifi_mode), (mp_obj_t)&esp_wifi_mode_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_phy_mode), (mp_obj_t)&esp_phy_mode_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_osdebug), (mp_obj_t)&esp_osdebug_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_type), (mp_obj_t)&esp_sleep_type_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deepsleep), (mp_obj_t)&esp_deepsleep_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_id), (mp_obj_t)&esp_flash_id_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_read), (mp_obj_t)&esp_flash_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_write), (mp_obj_t)&esp_flash_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_erase), (mp_obj_t)&esp_flash_erase_obj },
#if MODESP_ESPCONN
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&esp_socket_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_getaddrinfo_obj },
#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&esp_neopixel_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_freemem), (mp_obj_t)&esp_freemem_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_meminfo), (mp_obj_t)&esp_meminfo_obj },
#if MODESP_INCLUDE_CONSTANTS
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_11B),
MP_OBJ_NEW_SMALL_INT(PHY_MODE_11B) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_11G),
MP_OBJ_NEW_SMALL_INT(PHY_MODE_11G) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_11N),
MP_OBJ_NEW_SMALL_INT(PHY_MODE_11N) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP_NONE),
MP_OBJ_NEW_SMALL_INT(NONE_SLEEP_T) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP_LIGHT),

174
esp8266/modmachine.c Normal file
View File

@@ -0,0 +1,174 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2015 Damien P. George
* Copyright (c) 2016 Paul Sokolovsky
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdint.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "extmod/machine_mem.h"
#include "utils.h"
#include "modpyb.h"
#include "os_type.h"
#include "osapi.h"
#include "etshal.h"
#include "user_interface.h"
#if MICROPY_PY_MACHINE
STATIC mp_obj_t machine_freq(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
// get
return mp_obj_new_int(system_get_cpu_freq() * 1000000);
} else {
// set
mp_int_t freq = mp_obj_get_int(args[0]) / 1000000;
if (freq != 80 && freq != 160) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"frequency can only be either 80Mhz or 160MHz"));
}
system_update_cpu_freq(freq);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq);
STATIC mp_obj_t machine_reset(void) {
system_restart();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
STATIC mp_obj_t machine_unique_id(void) {
uint32_t id = system_get_chip_id();
return mp_obj_new_bytes((byte*)&id, sizeof(id));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id);
typedef struct _esp_timer_obj_t {
mp_obj_base_t base;
os_timer_t timer;
mp_obj_t callback;
} esp_timer_obj_t;
const mp_obj_type_t esp_timer_type;
STATIC void esp_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
esp_timer_obj_t *self = self_in;
mp_printf(print, "Timer(%p)", &self->timer);
}
STATIC mp_obj_t esp_timer_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, 1, false);
esp_timer_obj_t *tim = m_new_obj(esp_timer_obj_t);
tim->base.type = &esp_timer_type;
return tim;
}
STATIC void esp_timer_cb(void *arg) {
esp_timer_obj_t *self = arg;
call_function_1_protected(self->callback, self);
}
STATIC mp_obj_t esp_timer_init_helper(esp_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
// { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0xffffffff} },
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
self->callback = args[2].u_obj;
// Be sure to disarm timer before making any changes
os_timer_disarm(&self->timer);
os_timer_setfn(&self->timer, esp_timer_cb, self);
os_timer_arm(&self->timer, args[0].u_int, args[1].u_int);
return mp_const_none;
}
STATIC mp_obj_t esp_timer_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
return esp_timer_init_helper(args[0], n_args - 1, args + 1, kw_args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_timer_init_obj, 1, esp_timer_init);
STATIC mp_obj_t esp_timer_deinit(mp_obj_t self_in) {
esp_timer_obj_t *self = self_in;
os_timer_disarm(&self->timer);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_timer_deinit_obj, esp_timer_deinit);
STATIC const mp_map_elem_t esp_timer_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&esp_timer_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&esp_timer_init_obj },
// { MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&esp_timer_callback_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ONE_SHOT), MP_OBJ_NEW_SMALL_INT(false) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PERIODIC), MP_OBJ_NEW_SMALL_INT(true) },
};
STATIC MP_DEFINE_CONST_DICT(esp_timer_locals_dict, esp_timer_locals_dict_table);
const mp_obj_type_t esp_timer_type = {
{ &mp_type_type },
.name = MP_QSTR_Timer,
.print = esp_timer_print,
.make_new = esp_timer_make_new,
.locals_dict = (mp_obj_t)&esp_timer_locals_dict,
};
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
{ MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },
{ MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) },
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
{ MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&esp_timer_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(&pyb_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_spi_type) },
};
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
const mp_obj_module_t mp_module_machine = {
.base = { &mp_type_module },
.name = MP_QSTR_umachine,
.globals = (mp_obj_dict_t*)&machine_module_globals,
};
#endif // MICROPY_PY_MACHINE

View File

@@ -32,30 +32,77 @@
#include "py/nlr.h"
#include "py/objlist.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "netutils.h"
#include "queue.h"
#include "user_interface.h"
#include "espconn.h"
#include "ip_addr.h"
#include "spi_flash.h"
#include "utils.h"
#include "ets_alt_task.h"
#define MODNETWORK_INCLUDE_CONSTANTS (1)
typedef struct _wlan_if_obj_t {
mp_obj_base_t base;
int if_id;
} wlan_if_obj_t;
void error_check(bool status, const char *msg);
extern const mp_obj_module_t network_module;
const mp_obj_type_t wlan_if_type;
STATIC mp_obj_t get_module() {
return (mp_obj_t)&network_module;
STATIC const wlan_if_obj_t wlan_objs[] = {
{{&wlan_if_type}, STATION_IF},
{{&wlan_if_type}, SOFTAP_IF},
};
STATIC void require_if(mp_obj_t wlan_if, int if_no) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(wlan_if);
if (self->if_id != if_no) {
error_check(false, if_no == STATION_IF ? "STA required" : "AP required");
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(get_module_obj, get_module);
STATIC mp_obj_t get_wlan(mp_uint_t n_args, const mp_obj_t *args) {
int idx = 0;
if (n_args > 0) {
idx = mp_obj_get_int(args[0]);
}
return MP_OBJ_FROM_PTR(&wlan_objs[idx]);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(get_wlan_obj, 0, 1, get_wlan);
STATIC mp_obj_t esp_active(mp_uint_t n_args, const mp_obj_t *args) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
uint32_t mode = wifi_get_opmode();
if (n_args > 1) {
int mask = self->if_id == STATION_IF ? STATION_MODE : SOFTAP_MODE;
if (mp_obj_get_int(args[1]) != 0) {
mode |= mask;
} else {
mode &= ~mask;
}
error_check(wifi_set_opmode(mode), "Cannot update i/f status");
return mp_const_none;
}
// Get active status
if (self->if_id == STATION_IF) {
return mp_obj_new_bool(mode & STATION_MODE);
} else {
return mp_obj_new_bool(mode & SOFTAP_MODE);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_active_obj, 1, 2, esp_active);
STATIC mp_obj_t esp_connect(mp_uint_t n_args, const mp_obj_t *args) {
require_if(args[0], STATION_IF);
struct station_config config = {{0}};
mp_uint_t len;
const char *p;
p = mp_obj_str_get_data(args[0], &len);
memcpy(config.ssid, p, len);
p = mp_obj_str_get_data(args[1], &len);
memcpy(config.ssid, p, len);
p = mp_obj_str_get_data(args[2], &len);
memcpy(config.password, p, len);
error_check(wifi_station_set_config(&config), "Cannot set STA config");
@@ -63,24 +110,33 @@ STATIC mp_obj_t esp_connect(mp_uint_t n_args, const mp_obj_t *args) {
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_connect_obj, 2, 6, esp_connect);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_connect_obj, 3, 7, esp_connect);
STATIC mp_obj_t esp_disconnect() {
STATIC mp_obj_t esp_disconnect(mp_obj_t self_in) {
require_if(self_in, STATION_IF);
error_check(wifi_station_disconnect(), "Cannot disconnect from AP");
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_disconnect_obj, esp_disconnect);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_disconnect_obj, esp_disconnect);
#define MODNETWORK_INCLUDE_CONSTANTS (1)
STATIC mp_obj_t esp_status() {
return MP_OBJ_NEW_SMALL_INT(wifi_station_get_connect_status());
STATIC mp_obj_t esp_status(mp_obj_t self_in) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->if_id == STATION_IF) {
return MP_OBJ_NEW_SMALL_INT(wifi_station_get_connect_status());
}
return MP_OBJ_NEW_SMALL_INT(-1);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_status_obj, esp_status);
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) {
struct bss_info *bs;
if (si->pbss) {
if (esp_scan_list == NULL) {
// called unexpectedly
return;
}
if (si->pbss && status == 0) {
struct bss_info *bs;
STAILQ_FOREACH(bs, si->pbss, next) {
mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL);
t->items[0] = mp_obj_new_bytes(bs->ssid, strlen((char*)bs->ssid));
@@ -89,48 +145,205 @@ STATIC void esp_scan_cb(scaninfo *si, STATUS status) {
t->items[3] = MP_OBJ_NEW_SMALL_INT(bs->rssi);
t->items[4] = MP_OBJ_NEW_SMALL_INT(bs->authmode);
t->items[5] = MP_OBJ_NEW_SMALL_INT(bs->is_hidden);
call_function_1_protected(MP_STATE_PORT(scan_cb_obj), t);
mp_obj_list_append(*esp_scan_list, MP_OBJ_FROM_PTR(t));
}
} else {
// indicate error
*esp_scan_list = MP_OBJ_NULL;
}
esp_scan_list = NULL;
}
STATIC mp_obj_t esp_scan(mp_obj_t cb_in) {
MP_STATE_PORT(scan_cb_obj) = cb_in;
STATIC mp_obj_t esp_scan(mp_obj_t self_in) {
if (wifi_get_opmode() == SOFTAP_MODE) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
"Scan not supported in AP mode"));
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
"scan unsupported in AP mode"));
}
mp_obj_t list = mp_obj_new_list(0, NULL);
esp_scan_list = &list;
wifi_station_scan(NULL, (scan_done_cb_t)esp_scan_cb);
return mp_const_none;
ETS_POLL_WHILE(esp_scan_list != NULL);
if (list == MP_OBJ_NULL) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "scan failed"));
}
return list;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_scan_obj, esp_scan);
/// \method isconnected()
/// Return True if connected to an AP and an IP address has been assigned,
/// false otherwise.
STATIC mp_obj_t esp_isconnected() {
if (wifi_station_get_connect_status() == STATION_GOT_IP) {
return mp_const_true;
STATIC mp_obj_t esp_isconnected(mp_obj_t self_in) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (self->if_id == STATION_IF) {
if (wifi_station_get_connect_status() == STATION_GOT_IP) {
return mp_const_true;
}
} else {
if (wifi_softap_get_station_num() > 0) {
return mp_const_true;
}
}
return mp_const_false;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_isconnected_obj, esp_isconnected);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_isconnected_obj, esp_isconnected);
STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) },
// MicroPython "network" module interface requires it to contains classes
// to instantiate. But as we have just a static network interace,
// use module as a "class", and just make all methods module-global
// functions.
{ MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&get_module_obj },
STATIC mp_obj_t esp_mac(mp_uint_t n_args, const mp_obj_t *args) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
uint8_t mac[6];
if (n_args == 1) {
wifi_get_macaddr(self->if_id, mac);
return mp_obj_new_bytes(mac, sizeof(mac));
} else {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
if (bufinfo.len != 6) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"invalid buffer length"));
}
wifi_set_macaddr(self->if_id, bufinfo.buf);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_mac_obj, 1, 2, esp_mac);
STATIC mp_obj_t esp_ifconfig(mp_obj_t self_in) {
wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
struct ip_info info;
wifi_get_ip_info(self->if_id, &info);
mp_obj_t ifconfig[4] = {
netutils_format_ipv4_addr((uint8_t*)&info.ip, NETUTILS_BIG),
netutils_format_ipv4_addr((uint8_t*)&info.netmask, NETUTILS_BIG),
netutils_format_ipv4_addr((uint8_t*)&info.gw, NETUTILS_BIG),
MP_OBJ_NEW_QSTR(MP_QSTR_), // no DNS server
};
return mp_obj_new_tuple(4, ifconfig);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_ifconfig_obj, esp_ifconfig);
STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
if (n_args != 1 && kwargs->used != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
"either pos or kw args are allowed"));
}
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
union {
struct station_config sta;
struct softap_config ap;
} cfg;
if (self->if_id == STATION_IF) {
error_check(wifi_station_get_config(&cfg.sta), "can't get STA config");
} else {
error_check(wifi_softap_get_config(&cfg.ap), "can't get AP config");
}
if (kwargs->used != 0) {
for (mp_uint_t i = 0; i < kwargs->alloc; i++) {
if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) {
#define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x)
switch ((uintptr_t)kwargs->table[i].key) {
case QS(MP_QSTR_essid): {
mp_uint_t len;
const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
len = MIN(len, sizeof(cfg.ap.ssid));
memcpy(cfg.ap.ssid, s, len);
cfg.ap.ssid_len = len;
break;
}
default:
goto unknown;
}
#undef QS
}
}
if (self->if_id == STATION_IF) {
error_check(wifi_station_set_config(&cfg.sta), "can't set STA config");
} else {
error_check(wifi_softap_set_config(&cfg.ap), "can't set AP config");
}
return mp_const_none;
}
// Get config
if (n_args != 2) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
"can query only one param"));
}
#define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x)
switch ((uintptr_t)args[1]) {
case QS(MP_QSTR_essid):
return mp_obj_new_str((char*)cfg.ap.ssid, cfg.ap.ssid_len, false);
}
#undef QS
unknown:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"unknown config param"));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_config_obj, 1, esp_config);
STATIC const mp_map_elem_t wlan_if_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_active), (mp_obj_t)&esp_active_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&esp_connect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disconnect), (mp_obj_t)&esp_disconnect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_status), (mp_obj_t)&esp_status_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&esp_scan_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_isconnected), (mp_obj_t)&esp_isconnected_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mac), (mp_obj_t)&esp_mac_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_config), (mp_obj_t)&esp_config_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ifconfig), (mp_obj_t)&esp_ifconfig_obj },
};
STATIC MP_DEFINE_CONST_DICT(wlan_if_locals_dict, wlan_if_locals_dict_table);
const mp_obj_type_t wlan_if_type = {
{ &mp_type_type },
.name = MP_QSTR_WLAN,
.locals_dict = (mp_obj_t)&wlan_if_locals_dict,
};
STATIC mp_obj_t esp_wifi_mode(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
return mp_obj_new_int(wifi_get_opmode());
} else {
wifi_set_opmode(mp_obj_get_int(args[0]));
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_wifi_mode_obj, 0, 1, esp_wifi_mode);
STATIC mp_obj_t esp_phy_mode(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
return mp_obj_new_int(wifi_get_phy_mode());
} else {
wifi_set_phy_mode(mp_obj_get_int(args[0]));
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_phy_mode_obj, 0, 1, esp_phy_mode);
STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&get_wlan_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wifi_mode), (mp_obj_t)&esp_wifi_mode_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_phy_mode), (mp_obj_t)&esp_phy_mode_obj },
#if MODNETWORK_INCLUDE_CONSTANTS
{ MP_OBJ_NEW_QSTR(MP_QSTR_STA_IF),
MP_OBJ_NEW_SMALL_INT(STATION_IF)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_AP_IF),
MP_OBJ_NEW_SMALL_INT(SOFTAP_IF)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_STAT_IDLE),
MP_OBJ_NEW_SMALL_INT(STATION_IDLE)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_STAT_CONNECTING),
@@ -143,6 +356,13 @@ STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
MP_OBJ_NEW_SMALL_INT(STATION_CONNECT_FAIL)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_STAT_GOT_IP),
MP_OBJ_NEW_SMALL_INT(STATION_GOT_IP)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_11B),
MP_OBJ_NEW_SMALL_INT(PHY_MODE_11B) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_11G),
MP_OBJ_NEW_SMALL_INT(PHY_MODE_11G) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_11N),
MP_OBJ_NEW_SMALL_INT(PHY_MODE_11N) },
#endif
};

185
esp8266/modonewire.c Normal file
View File

@@ -0,0 +1,185 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2015 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 "etshal.h"
#include "user_interface.h"
#include "py/obj.h"
#include "py/mphal.h"
#include "modpyb.h"
STATIC uint32_t disable_irq(void) {
ets_intr_lock();
return 0;
}
STATIC void enable_irq(uint32_t i) {
ets_intr_unlock();
}
STATIC void mp_hal_delay_us_no_irq(uint32_t us) {
uint32_t start = system_get_time();
while (system_get_time() - start < us) {
}
}
#define DELAY_US mp_hal_delay_us_no_irq
#define TIMING_RESET1 (0)
#define TIMING_RESET2 (1)
#define TIMING_RESET3 (2)
#define TIMING_READ1 (3)
#define TIMING_READ2 (4)
#define TIMING_READ3 (5)
#define TIMING_WRITE1 (6)
#define TIMING_WRITE2 (7)
#define TIMING_WRITE3 (8)
static int timings[] = {480, 40, 420, 5, 5, 40, 10, 50, 10};
STATIC mp_obj_t onewire_timings(mp_obj_t timings_in) {
mp_obj_t *items;
mp_obj_get_array_fixed_n(timings_in, 9, &items);
for (int i = 0; i < 9; ++i) {
timings[i] = mp_obj_get_int(items[i]);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_timings_obj, onewire_timings);
STATIC mp_obj_t onewire_reset(mp_obj_t pin_in) {
uint pin = mp_obj_get_pin(pin_in);
pin_set(pin, 0);
DELAY_US(timings[TIMING_RESET1]);
uint32_t i = disable_irq();
pin_set(pin, 1);
DELAY_US(timings[TIMING_RESET2]);
int status = !pin_get(pin);
enable_irq(i);
DELAY_US(timings[TIMING_RESET3]);
return mp_obj_new_bool(status);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_reset_obj, onewire_reset);
STATIC int _onewire_readbit(uint pin) {
pin_set(pin, 1);
uint32_t i = disable_irq();
pin_set(pin, 0);
DELAY_US(timings[TIMING_READ1]);
pin_set(pin, 1);
DELAY_US(timings[TIMING_READ2]);
int value = pin_get(pin);
enable_irq(i);
DELAY_US(timings[TIMING_READ3]);
return value;
}
STATIC mp_obj_t onewire_readbit(mp_obj_t pin_in) {
return MP_OBJ_NEW_SMALL_INT(_onewire_readbit(mp_obj_get_pin(pin_in)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_readbit_obj, onewire_readbit);
STATIC mp_obj_t onewire_readbyte(mp_obj_t pin_in) {
uint pin = mp_obj_get_pin(pin_in);
uint8_t value = 0;
for (int i = 0; i < 8; ++i) {
value |= _onewire_readbit(pin) << i;
}
return MP_OBJ_NEW_SMALL_INT(value);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_readbyte_obj, onewire_readbyte);
STATIC void _onewire_writebit(uint pin, int value) {
uint32_t i = disable_irq();
pin_set(pin, 0);
DELAY_US(timings[TIMING_WRITE1]);
pin_set(pin, value);
DELAY_US(timings[TIMING_WRITE2]);
pin_set(pin, 1);
DELAY_US(timings[TIMING_WRITE3]);
enable_irq(i);
}
STATIC mp_obj_t onewire_writebit(mp_obj_t pin_in, mp_obj_t value_in) {
_onewire_writebit(mp_obj_get_pin(pin_in), mp_obj_get_int(value_in));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(onewire_writebit_obj, onewire_writebit);
STATIC mp_obj_t onewire_writebyte(mp_obj_t pin_in, mp_obj_t value_in) {
uint pin = mp_obj_get_pin(pin_in);
int value = mp_obj_get_int(value_in);
for (int i = 0; i < 8; ++i) {
_onewire_writebit(pin, value & 1);
value >>= 1;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(onewire_writebyte_obj, onewire_writebyte);
STATIC mp_obj_t onewire_crc8(mp_obj_t data) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
uint8_t crc = 0;
for (size_t i = 0; i < bufinfo.len; ++i) {
uint8_t byte = ((uint8_t*)bufinfo.buf)[i];
for (int b = 0; b < 8; ++b) {
uint8_t fb_bit = (crc ^ byte) & 0x01;
if (fb_bit == 0x01) {
crc = crc ^ 0x18;
}
crc = (crc >> 1) & 0x7f;
if (fb_bit == 0x01) {
crc = crc | 0x80;
}
byte = byte >> 1;
}
}
return MP_OBJ_NEW_SMALL_INT(crc);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_crc8_obj, onewire_crc8);
STATIC const mp_map_elem_t onewire_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_onewire) },
{ MP_ROM_QSTR(MP_QSTR_timings), MP_ROM_PTR((mp_obj_t)&onewire_timings_obj) },
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR((mp_obj_t)&onewire_reset_obj) },
{ MP_ROM_QSTR(MP_QSTR_readbit), MP_ROM_PTR((mp_obj_t)&onewire_readbit_obj) },
{ MP_ROM_QSTR(MP_QSTR_readbyte), MP_ROM_PTR((mp_obj_t)&onewire_readbyte_obj) },
{ MP_ROM_QSTR(MP_QSTR_writebit), MP_ROM_PTR((mp_obj_t)&onewire_writebit_obj) },
{ MP_ROM_QSTR(MP_QSTR_writebyte), MP_ROM_PTR((mp_obj_t)&onewire_writebyte_obj) },
{ MP_ROM_QSTR(MP_QSTR_crc8), MP_ROM_PTR((mp_obj_t)&onewire_crc8_obj) },
};
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

@@ -77,23 +77,6 @@ STATIC mp_obj_t pyb_info(mp_uint_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj, 0, 1, pyb_info);
STATIC mp_obj_t pyb_freq(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
// get
return mp_obj_new_int(system_get_cpu_freq() * 1000000);
} else {
// set
mp_int_t freq = mp_obj_get_int(args[0]) / 1000000;
if (freq != 80 && freq != 160) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"frequency can only be either 80Mhz or 160MHz"));
}
system_update_cpu_freq(freq);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_freq_obj, 0, 1, pyb_freq);
STATIC mp_obj_t pyb_sync(void) {
//storage_flush();
return mp_const_none;
@@ -142,23 +125,10 @@ STATIC mp_obj_t pyb_udelay(mp_obj_t usec_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_udelay_obj, pyb_udelay);
STATIC mp_obj_t pyb_hard_reset(void) {
system_restart();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_hard_reset_obj, pyb_hard_reset);
STATIC mp_obj_t pyb_unique_id(void) {
uint32_t id = system_get_chip_id();
return mp_obj_new_bytes((byte *)&id, sizeof(id));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_unique_id_obj, pyb_unique_id);
STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_info_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&pyb_freq_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_millis), (mp_obj_t)&pyb_millis_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_millis), (mp_obj_t)&pyb_elapsed_millis_obj },
@@ -167,7 +137,6 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_delay), (mp_obj_t)&pyb_delay_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_udelay), (mp_obj_t)&pyb_udelay_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&pyb_sync_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_hard_reset), (mp_obj_t)&pyb_hard_reset_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pyb_pin_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pyb_adc_type },

View File

@@ -1,3 +1,20 @@
extern const mp_obj_type_t pyb_pin_type;
extern const mp_obj_type_t pyb_pwm_type;
extern const mp_obj_type_t pyb_adc_type;
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;
typedef struct _pyb_pin_obj_t {
mp_obj_base_t base;
uint16_t pin_id;
uint16_t phys_port;
uint32_t periph;
uint16_t func;
} pyb_pin_obj_t;
uint mp_obj_get_pin(mp_obj_t pin_in);
pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in);
int pin_get(uint pin);
void pin_set(uint pin, int value);

View File

@@ -42,7 +42,7 @@ typedef struct _pyb_adc_obj_t {
STATIC pyb_adc_obj_t pyb_adc_vdd3 = {{&pyb_adc_type}, true};
STATIC pyb_adc_obj_t pyb_adc_adc = {{&pyb_adc_type}, false};
STATIC mp_obj_t pyb_adc_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
STATIC mp_obj_t pyb_adc_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, 1, 1, false);

323
esp8266/modpybi2c.c Normal file
View File

@@ -0,0 +1,323 @@
/*
* 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 "osapi.h"
#include "gpio.h"
#include "py/runtime.h"
#include "modpyb.h"
typedef struct _pyb_i2c_obj_t {
mp_obj_base_t base;
pyb_pin_obj_t *scl;
pyb_pin_obj_t *sda;
} pyb_i2c_obj_t;
// these set the frequency of SCL
#define mphal_i2c_wait_a() os_delay_us(2)
#define mphal_i2c_wait_b() os_delay_us(1)
STATIC void mphal_i2c_set_sda(pyb_i2c_obj_t *self, uint8_t sda) {
uint32_t port = self->sda->phys_port;
sda &= 0x01;
gpio_output_set(sda << port, (1 - sda) << port, 1 << port, 0);
}
STATIC void mphal_i2c_set_scl(pyb_i2c_obj_t *self, uint8_t scl) {
uint32_t port = self->scl->phys_port;
scl &= 0x01;
gpio_output_set(scl << port, (1 - scl) << port, 1 << port, 0);
}
STATIC int mphal_i2c_get_sda(pyb_i2c_obj_t *self) {
return GPIO_INPUT_GET(GPIO_ID_PIN(self->sda->phys_port));
}
STATIC void mphal_i2c_start(pyb_i2c_obj_t *self) {
mphal_i2c_set_sda(self, 1);
mphal_i2c_wait_a();
mphal_i2c_set_scl(self, 1);
mphal_i2c_wait_a();
mphal_i2c_set_sda(self, 0);
mphal_i2c_wait_a();
}
STATIC void mphal_i2c_stop(pyb_i2c_obj_t *self) {
mphal_i2c_wait_a();
mphal_i2c_set_sda(self, 0);
mphal_i2c_wait_a();
mphal_i2c_set_scl(self, 1);
mphal_i2c_wait_a();
mphal_i2c_set_sda(self, 1);
mphal_i2c_wait_a();
}
STATIC void mphal_i2c_init(pyb_i2c_obj_t *self, uint32_t freq) {
pyb_pin_obj_t *scl = self->scl;
pyb_pin_obj_t *sda = self->sda;
ETS_GPIO_INTR_DISABLE();
//ETS_INTR_LOCK();
PIN_FUNC_SELECT(sda->periph, sda->func);
PIN_FUNC_SELECT(scl->periph, scl->func);
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(sda->phys_port)),
GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(sda->phys_port)))
| GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); // open drain
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS,
GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << sda->phys_port));
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(scl->phys_port)),
GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(scl->phys_port)))
| GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); // open drain
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS,
GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << scl->phys_port));
mphal_i2c_set_scl(self, 1);
mphal_i2c_set_sda(self, 1);
ETS_GPIO_INTR_ENABLE();
//ETS_INTR_UNLOCK();
mphal_i2c_set_scl(self, 0);
mphal_i2c_wait_a();
// when SCL = 0, toggle SDA to clear up
mphal_i2c_set_sda(self, 0);
mphal_i2c_wait_a();
mphal_i2c_set_sda(self, 1);
mphal_i2c_wait_a();
// set data_cnt to max value
for (uint8_t i = 0; i < 28; i++) {
mphal_i2c_set_scl(self, 0);
mphal_i2c_wait_a();
mphal_i2c_set_scl(self, 1);
mphal_i2c_wait_a();
}
// reset all
mphal_i2c_stop(self);
}
STATIC int mphal_i2c_write_byte(pyb_i2c_obj_t *self, uint8_t val) {
uint8_t dat;
sint8 i;
mphal_i2c_wait_a();
mphal_i2c_set_scl(self, 0);
mphal_i2c_wait_a();
for (i = 7; i >= 0; i--) {
dat = val >> i;
mphal_i2c_set_sda(self, dat);
mphal_i2c_wait_a();
mphal_i2c_set_scl(self, 1);
mphal_i2c_wait_a();
if (i == 0) {
mphal_i2c_wait_b();
}
mphal_i2c_set_scl(self, 0);
mphal_i2c_wait_a();
}
mphal_i2c_set_sda(self, 1);
mphal_i2c_wait_a();
mphal_i2c_set_scl(self, 1);
mphal_i2c_wait_a();
int ret = mphal_i2c_get_sda(self);
mphal_i2c_wait_a();
mphal_i2c_set_scl(self, 0);
mphal_i2c_wait_a();
return !ret;
}
STATIC void mphal_i2c_write(pyb_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len, bool stop) {
mphal_i2c_start(self);
if (!mphal_i2c_write_byte(self, addr << 1)) {
goto er;
}
while (len--) {
if (!mphal_i2c_write_byte(self, *data++)) {
goto er;
}
}
if (stop) {
mphal_i2c_stop(self);
}
return;
er:
mphal_i2c_stop(self);
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
}
STATIC int mphal_i2c_read_byte(pyb_i2c_obj_t *self, uint8_t *val) {
mphal_i2c_wait_a();
mphal_i2c_set_scl(self, 0);
mphal_i2c_wait_a();
uint8_t dat = 0;
for (int i = 7; i >= 0; i--) {
mphal_i2c_set_scl(self, 1);
mphal_i2c_wait_a();
dat = (dat << 1) | mphal_i2c_get_sda(self);
mphal_i2c_wait_a();
mphal_i2c_set_scl(self, 0);
mphal_i2c_wait_a();
}
*val = dat;
mphal_i2c_wait_a();
mphal_i2c_set_scl(self, 1);
mphal_i2c_wait_a();
mphal_i2c_wait_b();
mphal_i2c_set_scl(self, 0);
mphal_i2c_wait_a();
return 1; // success
}
STATIC void mphal_i2c_read(pyb_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len, bool stop) {
mphal_i2c_start(self);
if (!mphal_i2c_write_byte(self, (addr << 1) | 1)) {
goto er;
}
while (len--) {
if (!mphal_i2c_read_byte(self, data++)) {
goto er;
}
}
if (stop) {
mphal_i2c_stop(self);
}
return;
er:
mphal_i2c_stop(self);
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
}
/******************************************************************************/
// MicroPython bindings for I2C
STATIC void pyb_i2c_obj_init_helper(pyb_i2c_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_scl, ARG_sda, ARG_freq };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
};
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);
self->scl = mp_obj_get_pin_obj(args[ARG_scl].u_obj);
self->sda = mp_obj_get_pin_obj(args[ARG_sda].u_obj);
mphal_i2c_init(self, args[ARG_freq].u_int);
}
STATIC mp_obj_t pyb_i2c_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_i2c_obj_t *self = m_new_obj(pyb_i2c_obj_t);
self->base.type = &pyb_i2c_type;
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
pyb_i2c_obj_init_helper(self, n_args, args, &kw_args);
return (mp_obj_t)self;
}
STATIC mp_obj_t pyb_i2c_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_i2c_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_init_obj, 1, pyb_i2c_obj_init);
STATIC mp_obj_t pyb_i2c_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_addr, ARG_n, ARG_stop };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_n, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
};
pyb_i2c_obj_t *self = 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);
// do the I2C transfer
vstr_t vstr;
vstr_init_len(&vstr, args[ARG_n].u_int);
mphal_i2c_read(self, args[ARG_addr].u_int, (uint8_t*)vstr.buf, vstr.len, args[ARG_stop].u_bool);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_obj, 1, pyb_i2c_readfrom);
STATIC mp_obj_t pyb_i2c_writeto(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_addr, ARG_buf, ARG_stop };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_addr, 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_stop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
};
pyb_i2c_obj_t *self = 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);
// get the buffer to write from
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ);
// do the I2C transfer
mphal_i2c_write(self, args[ARG_addr].u_int, bufinfo.buf, bufinfo.len, args[ARG_stop].u_bool);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_writeto_obj, 1, pyb_i2c_writeto);
STATIC const mp_rom_map_elem_t pyb_i2c_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_i2c_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&pyb_i2c_readfrom_obj) },
{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&pyb_i2c_writeto_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);
const mp_obj_type_t pyb_i2c_type = {
{ &mp_type_type },
.name = MP_QSTR_I2C,
.make_new = pyb_i2c_make_new,
.locals_dict = (mp_obj_dict_t*)&pyb_i2c_locals_dict,
};

View File

@@ -38,19 +38,12 @@
#define GPIO_MODE_INPUT (0)
#define GPIO_MODE_OUTPUT (1)
#define GPIO_MODE_OPEN_DRAIN (2) // synthesised
#define GPIO_PULL_NONE (0)
#define GPIO_PULL_UP (1)
// Removed in SDK 1.1.0
//#define GPIO_PULL_DOWN (2)
typedef struct _pyb_pin_obj_t {
mp_obj_base_t base;
uint16_t pin_id;
uint16_t phys_port;
uint32_t periph;
uint16_t func;
} pyb_pin_obj_t;
STATIC const pyb_pin_obj_t pyb_pin_obj[] = {
{{&pyb_pin_type}, 0, 0, PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0},
{{&pyb_pin_type}, 1, 1, PERIPHS_IO_MUX_U0TXD_U, FUNC_GPIO1},
@@ -64,8 +57,75 @@ STATIC const pyb_pin_obj_t pyb_pin_obj[] = {
{{&pyb_pin_type}, 13, 13, PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13},
{{&pyb_pin_type}, 14, 14, PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14},
{{&pyb_pin_type}, 15, 15, PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15},
// GPIO16 is special, belongs to different register set, and
// otherwise handled specially.
{{&pyb_pin_type}, 16, 16, -1, -1},
};
STATIC uint8_t pin_mode[16 + 1];
pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in) {
if (mp_obj_get_type(pin_in) != &pyb_pin_type) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "expecting a pin"));
}
pyb_pin_obj_t *self = pin_in;
return self;
}
uint mp_obj_get_pin(mp_obj_t pin_in) {
return mp_obj_get_pin_obj(pin_in)->phys_port;
}
int pin_get(uint pin) {
if (pin == 16) {
return READ_PERI_REG(RTC_GPIO_IN_DATA) & 1;
}
return GPIO_INPUT_GET(pin);
}
void pin_set(uint pin, int value) {
if (pin == 16) {
int out_en = (pin_mode[pin] == GPIO_MODE_OUTPUT);
WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1);
WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1);
WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | out_en);
WRITE_PERI_REG(RTC_GPIO_OUT, (READ_PERI_REG(RTC_GPIO_OUT) & ~1) | value);
return;
}
uint32_t enable = 0;
uint32_t disable = 0;
switch (pin_mode[pin]) {
case GPIO_MODE_INPUT:
value = -1;
disable = 1;
break;
case GPIO_MODE_OUTPUT:
enable = 1;
break;
case GPIO_MODE_OPEN_DRAIN:
if (value == -1) {
return;
} else if (value == 0) {
enable = 1;
} else {
value = -1;
disable = 1;
}
break;
}
enable <<= pin;
disable <<= pin;
if (value == -1) {
gpio_output_set(0, 0, enable, disable);
} else {
gpio_output_set(value << pin, (1 - value) << pin, enable, disable);
}
}
STATIC void pyb_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_pin_obj_t *self = self_in;
@@ -77,49 +137,65 @@ STATIC void pyb_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_pull, MP_ARG_INT, {.u_int = GPIO_PULL_NONE}},
{ MP_QSTR_pull, MP_ARG_INT, {.u_int = GPIO_PULL_NONE}},
{ MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
};
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
struct {
mp_arg_val_t mode, pull, value;
} args;
mp_arg_parse_all(n_args, pos_args, kw_args,
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
// get io mode
uint mode = args[0].u_int;
uint mode = args.mode.u_int;
// get pull mode
uint pull = args[1].u_int;
uint pull = args.pull.u_int;
// get initial value
int value;
if (args.value.u_obj == MP_OBJ_NULL) {
value = -1;
} else {
value = mp_obj_is_true(args.value.u_obj);
}
// save the mode
pin_mode[self->phys_port] = mode;
// configure the GPIO as requested
PIN_FUNC_SELECT(self->periph, self->func);
#if 0
// Removed in SDK 1.1.0
if ((pull & GPIO_PULL_DOWN) == 0) {
PIN_PULLDWN_DIS(self->periph);
}
#endif
if ((pull & GPIO_PULL_UP) == 0) {
PIN_PULLUP_DIS(self->periph);
}
#if 0
if ((pull & GPIO_PULL_DOWN) != 0) {
PIN_PULLDWN_EN(self->periph);
}
#endif
if ((pull & GPIO_PULL_UP) != 0) {
PIN_PULLUP_EN(self->periph);
if (self->phys_port == 16) {
// TODO: Set pull up/pull down
} else {
PIN_FUNC_SELECT(self->periph, self->func);
#if 0
// Removed in SDK 1.1.0
if ((pull & GPIO_PULL_DOWN) == 0) {
PIN_PULLDWN_DIS(self->periph);
}
#endif
if ((pull & GPIO_PULL_UP) == 0) {
PIN_PULLUP_DIS(self->periph);
}
#if 0
if ((pull & GPIO_PULL_DOWN) != 0) {
PIN_PULLDWN_EN(self->periph);
}
#endif
if ((pull & GPIO_PULL_UP) != 0) {
PIN_PULLUP_EN(self->periph);
}
}
// TODO input mode is not working...
if ((mode & GPIO_MODE_OUTPUT) == 0) {
GPIO_DIS_OUTPUT(self->phys_port);
}
pin_set(self->phys_port, value);
return mp_const_none;
}
// constructor(id, ...)
STATIC mp_obj_t pyb_pin_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
STATIC mp_obj_t pyb_pin_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// Run an argument through the mapper and return the result.
@@ -145,6 +221,20 @@ STATIC mp_obj_t pyb_pin_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n
return (mp_obj_t)pin;
}
// fast method for getting/setting pin value
STATIC mp_obj_t pyb_pin_call(mp_obj_t self_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);
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));
} else {
// set pin
pin_set(self->phys_port, mp_obj_is_true(args[0]));
return mp_const_none;
}
}
// pin.init(mode, pull)
STATIC mp_obj_t pyb_pin_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
return pyb_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
@@ -153,26 +243,14 @@ MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pin_init_obj, 1, pyb_pin_obj_init);
// pin.value([value])
STATIC mp_obj_t pyb_pin_value(mp_uint_t n_args, const mp_obj_t *args) {
pyb_pin_obj_t *self = args[0];
if (n_args == 1) {
// get pin
return MP_OBJ_NEW_SMALL_INT(GPIO_INPUT_GET(self->phys_port));
} else {
// set pin
if (mp_obj_is_true(args[1])) {
GPIO_OUTPUT_SET(self->phys_port, 1);
} else {
GPIO_OUTPUT_SET(self->phys_port, 0);
}
return mp_const_none;
}
return pyb_pin_call(args[0], n_args - 1, 0, args + 1);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pin_value_obj, 1, 2, pyb_pin_value);
// pin.low()
STATIC mp_obj_t pyb_pin_low(mp_obj_t self_in) {
pyb_pin_obj_t *self = self_in;
GPIO_OUTPUT_SET(self->phys_port, 0);
pin_set(self->phys_port, 0);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pin_low_obj, pyb_pin_low);
@@ -180,7 +258,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pin_low_obj, pyb_pin_low);
// pin.high()
STATIC mp_obj_t pyb_pin_high(mp_obj_t self_in) {
pyb_pin_obj_t *self = self_in;
GPIO_OUTPUT_SET(self->phys_port, 1);
pin_set(self->phys_port, 1);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pin_high_obj, pyb_pin_high);
@@ -194,7 +272,8 @@ STATIC const mp_map_elem_t pyb_pin_locals_dict_table[] = {
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_INPUT) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_OUT_PP), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OPEN_DRAIN) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_NONE), MP_OBJ_NEW_SMALL_INT(GPIO_PULL_NONE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(GPIO_PULL_UP) },
//{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PULL_DOWN) },
@@ -207,5 +286,6 @@ const mp_obj_type_t pyb_pin_type = {
.name = MP_QSTR_Pin,
.print = pyb_pin_print,
.make_new = pyb_pin_make_new,
.call = pyb_pin_call,
.locals_dict = (mp_obj_t)&pyb_pin_locals_dict,
};

172
esp8266/modpybpwm.c Normal file
View File

@@ -0,0 +1,172 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
#include "esppwm.h"
#include "py/nlr.h"
#include "py/runtime.h"
#include "modpyb.h"
typedef struct _pyb_pwm_obj_t {
mp_obj_base_t base;
pyb_pin_obj_t *pin;
uint8_t active;
uint8_t channel;
} pyb_pwm_obj_t;
STATIC bool pwm_inited = false;
/******************************************************************************/
// MicroPython bindings for PWM
STATIC void pyb_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "PWM(%u", self->pin->pin_id);
if (self->active) {
mp_printf(print, ", freq=%u, duty=%u",
pwm_get_freq(self->channel), pwm_get_duty(self->channel));
}
mp_printf(print, ")");
}
STATIC void pyb_pwm_init_helper(pyb_pwm_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_freq, ARG_duty };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_freq, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_duty, MP_ARG_INT, {.u_int = -1} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
int channel = pwm_add(self->pin->phys_port, self->pin->periph, self->pin->func);
if (channel == -1) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"PWM not supported on pin %d", self->pin->phys_port));
}
self->channel = channel;
self->active = 1;
if (args[ARG_freq].u_int != -1) {
pwm_set_freq(args[ARG_freq].u_int, self->channel);
}
if (args[ARG_duty].u_int != -1) {
pwm_set_duty(args[ARG_duty].u_int, self->channel);
}
pwm_start();
}
STATIC mp_obj_t pyb_pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
pyb_pin_obj_t *pin = mp_obj_get_pin_obj(args[0]);
// create PWM object from the given pin
pyb_pwm_obj_t *self = m_new_obj(pyb_pwm_obj_t);
self->base.type = &pyb_pwm_type;
self->pin = pin;
self->active = 0;
self->channel = -1;
// start the PWM subsystem if it's not already running
if (!pwm_inited) {
pwm_init();
pwm_inited = true;
}
// start the PWM running for this channel
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
pyb_pwm_init_helper(self, n_args - 1, args + 1, &kw_args);
return MP_OBJ_FROM_PTR(self);
}
STATIC mp_obj_t pyb_pwm_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_pwm_init_helper(args[0], n_args - 1, args + 1, kw_args);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pwm_init_obj, 1, pyb_pwm_init);
STATIC mp_obj_t pyb_pwm_deinit(mp_obj_t self_in) {
pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
pwm_delete(self->channel);
self->active = 0;
pwm_start();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pwm_deinit_obj, pyb_pwm_deinit);
STATIC mp_obj_t pyb_pwm_freq(size_t n_args, const mp_obj_t *args) {
//pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (n_args == 1) {
// get
return MP_OBJ_NEW_SMALL_INT(pwm_get_freq(0));
} else {
// set
pwm_set_freq(mp_obj_get_int(args[1]), 0);
pwm_start();
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pwm_freq_obj, 1, 2, pyb_pwm_freq);
STATIC mp_obj_t pyb_pwm_duty(size_t n_args, const mp_obj_t *args) {
pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]);
if (!self->active) {
pwm_add(self->pin->phys_port, self->pin->periph, self->pin->func);
self->active = 1;
}
if (n_args == 1) {
// get
return MP_OBJ_NEW_SMALL_INT(pwm_get_duty(self->channel));
} else {
// set
pwm_set_duty(mp_obj_get_int(args[1]), self->channel);
pwm_start();
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pwm_duty_obj, 1, 2, pyb_pwm_duty);
STATIC const mp_rom_map_elem_t pyb_pwm_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_pwm_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_pwm_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&pyb_pwm_freq_obj) },
{ MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&pyb_pwm_duty_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_pwm_locals_dict, pyb_pwm_locals_dict_table);
const mp_obj_type_t pyb_pwm_type = {
{ &mp_type_type },
.name = MP_QSTR_PWM,
.print = pyb_pwm_print,
.make_new = pyb_pwm_make_new,
.locals_dict = (mp_obj_dict_t*)&pyb_pwm_locals_dict,
};

View File

@@ -49,7 +49,21 @@ typedef struct _pyb_rtc_obj_t {
// singleton RTC object
STATIC const pyb_rtc_obj_t pyb_rtc_obj = {{&pyb_rtc_type}};
STATIC mp_obj_t pyb_rtc_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
void mp_hal_rtc_init(void) {
uint32_t magic;
system_rtc_mem_read(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic));
if (magic != MEM_MAGIC) {
magic = MEM_MAGIC;
system_rtc_mem_write(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic));
uint32_t cal = system_rtc_clock_cali_proc();
int64_t delta = 0;
system_rtc_mem_write(MEM_CAL_ADDR, &cal, sizeof(cal));
system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta));
}
}
STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 0, 0, false);
@@ -58,7 +72,7 @@ STATIC mp_obj_t pyb_rtc_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n
}
STATIC uint64_t pyb_rtc_raw_us(uint64_t cal) {
return system_get_rtc_time() * ((cal >> 12) * 1000 + (cal & 0xfff) / 4) / 1000;
return (system_get_rtc_time() * cal) >> 12;
};
void pyb_rtc_set_us_since_2000(uint64_t nowus) {
@@ -146,7 +160,7 @@ STATIC mp_obj_t pyb_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) {
}
magic = MEM_MAGIC;
system_rtc_mem_write(MEM_USER_MAGIC_ADDR, &magic, sizeof(len));
system_rtc_mem_write(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic));
len = bufinfo.len;
system_rtc_mem_write(MEM_USER_LEN_ADDR, &len, sizeof(len));

217
esp8266/modpybspi.c Normal file
View File

@@ -0,0 +1,217 @@
/*
* 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 <errno.h>
#include "ets_sys.h"
#include "etshal.h"
#include "ets_alt_task.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "modpyb.h"
typedef struct _pyb_spi_obj_t {
mp_obj_base_t base;
uint32_t baudrate;
uint8_t polarity;
uint8_t phase;
pyb_pin_obj_t *sck;
pyb_pin_obj_t *mosi;
pyb_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) {
pin_set(self->mosi->phys_port, (data_out >> 7) & 1);
if (self->phase == 0) {
ets_delay_us(delay_half);
pin_set(self->sck->phys_port, 1 - self->polarity);
} else {
pin_set(self->sck->phys_port, 1 - self->polarity);
ets_delay_us(delay_half);
}
data_in = (data_in << 1) | pin_get(self->miso->phys_port);
if (self->phase == 0) {
ets_delay_us(delay_half);
pin_set(self->sck->phys_port, self->polarity);
} else {
pin_set(self->sck->phys_port, 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();
}
}
/******************************************************************************/
// 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->phys_port, self->mosi->phys_port, self->miso->phys_port);
}
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) {
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} },
{ MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} },
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
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 (args[ARG_sck].u_obj != MP_OBJ_NULL) {
self->sck = mp_obj_get_pin_obj(args[ARG_sck].u_obj);
}
if (args[ARG_mosi].u_obj != MP_OBJ_NULL) {
self->mosi = mp_obj_get_pin_obj(args[ARG_mosi].u_obj);
}
if (args[ARG_miso].u_obj != MP_OBJ_NULL) {
self->miso = mp_obj_get_pin_obj(args[ARG_miso].u_obj);
}
}
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_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);
self->base.type = &pyb_spi_type;
// set defaults
self->baudrate = 500000;
self->polarity = 0;
self->phase = 0;
self->sck = NULL;
self->mosi = NULL;
self->miso = NULL;
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
pyb_spi_init_helper(self, n_args, args, &kw_args);
return MP_OBJ_FROM_PTR(self);
}
STATIC mp_obj_t pyb_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_spi_init_helper(args[0], n_args - 1, args + 1, kw_args);
return mp_const_none;
}
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) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table);
const mp_obj_type_t pyb_spi_type = {
{ &mp_type_type },
.name = MP_QSTR_SPI,
.print = pyb_spi_print,
.make_new = pyb_spi_make_new,
.locals_dict = (mp_obj_dict_t*)&pyb_spi_locals_dict,
};

157
esp8266/modpybuart.c Normal file
View File

@@ -0,0 +1,157 @@
/*
* 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 <errno.h>
#include "ets_sys.h"
#include "uart.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "modpyb.h"
typedef struct _pyb_uart_obj_t {
mp_obj_base_t base;
uint8_t uart_id;
} pyb_uart_obj_t;
/******************************************************************************/
// MicroPython bindings for UART
STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "UART(%u)", self->uart_id);
}
STATIC void pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
/*
enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 9600} },
{ MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} },
{ MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
*/
// not implemented
}
STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// get uart id
mp_int_t uart_id = mp_obj_get_int(args[0]);
if (uart_id != 0 && uart_id != 1) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) does not exist", uart_id));
}
// create instance
pyb_uart_obj_t *self = m_new_obj(pyb_uart_obj_t);
self->base.type = &pyb_uart_type;
self->uart_id = uart_id;
if (n_args > 1 || n_kw > 0) {
// init the peripheral
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
pyb_uart_init_helper(self, n_args - 1, args + 1, &kw_args);
}
return MP_OBJ_FROM_PTR(self);
}
STATIC mp_obj_t pyb_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
pyb_uart_init_helper(args[0], n_args - 1, args + 1, kw_args);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init);
STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) },
{ 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_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table);
STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
mp_not_implemented("reading from UART");
}
STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
const byte *buf = buf_in;
/* TODO implement non-blocking
// wait to be able to write the first character
if (!uart_tx_wait(self, timeout)) {
*errcode = EAGAIN;
return MP_STREAM_ERROR;
}
*/
// write the data
for (size_t i = 0; i < size; ++i) {
uart_tx_one_char(self->uart_id, *buf++);
}
// return number of bytes written
return size;
}
STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
*errcode = EINVAL;
return MP_STREAM_ERROR;
}
STATIC const mp_stream_p_t uart_stream_p = {
.read = pyb_uart_read,
.write = pyb_uart_write,
.ioctl = pyb_uart_ioctl,
.is_text = false,
};
const mp_obj_type_t pyb_uart_type = {
{ &mp_type_type },
.name = MP_QSTR_UART,
.print = pyb_uart_print,
.make_new = pyb_uart_make_new,
.getiter = mp_identity,
.iternext = mp_stream_unbuffered_iter,
.stream_p = &uart_stream_p,
.locals_dict = (mp_obj_dict_t*)&pyb_uart_locals_dict,
};

View File

@@ -25,15 +25,21 @@
*/
#include <string.h>
#include <errno.h>
#include "py/mpconfig.h"
#include "py/nlr.h"
#include "py/obj.h"
#include "py/objtuple.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "extmod/misc.h"
#include "genhdr/mpversion.h"
#include "etshal.h"
#include "user_interface.h"
extern const mp_obj_type_t mp_fat_vfs_type;
STATIC const qstr os_uname_info_fields[] = {
MP_QSTR_sysname, MP_QSTR_nodename,
MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine
@@ -65,9 +71,52 @@ STATIC mp_obj_t os_uname(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname);
STATIC const mp_map_elem_t os_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uos) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_uname), (mp_obj_t)&os_uname_obj },
#if MICROPY_VFS_FAT
mp_obj_t vfs_proxy_call(qstr method_name, mp_uint_t n_args, const mp_obj_t *args) {
if (MP_STATE_PORT(fs_user_mount)[0] == NULL) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENODEV)));
}
mp_obj_t meth[n_args + 2];
mp_load_method(MP_STATE_PORT(fs_user_mount)[0], method_name, meth);
memcpy(meth + 2, args, n_args * sizeof(*args));
return mp_call_method_n_kw(n_args, 0, meth);
}
STATIC mp_obj_t os_listdir(mp_uint_t n_args, const mp_obj_t *args) {
return vfs_proxy_call(MP_QSTR_listdir, n_args, args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_listdir_obj, 0, 1, os_listdir);
STATIC mp_obj_t os_remove(mp_obj_t path_in) {
return vfs_proxy_call(MP_QSTR_remove, 1, &path_in);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove);
#endif
STATIC mp_obj_t os_urandom(mp_obj_t num) {
mp_int_t n = mp_obj_get_int(num);
vstr_t vstr;
vstr_init_len(&vstr, n);
for (int i = 0; i < n; i++) {
vstr.buf[i] = *WDEV_HWRNG;
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },
{ MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) },
{ MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) },
#if MICROPY_PY_OS_DUPTERM
{ MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) },
#endif
#if MICROPY_VFS_FAT
{ MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&os_listdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&os_remove_obj) },
#endif
};
STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);

View File

@@ -33,6 +33,7 @@
#include "py/gc.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "py/smallint.h"
#include "modpyb.h"
#include "modpybrtc.h"
#include "timeutils.h"
@@ -101,11 +102,51 @@ 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) {
// TODO
return MP_OBJ_NEW_SMALL_INT(0 & 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) {
@@ -120,6 +161,12 @@ 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_time), (mp_obj_t)&time_time_obj },
};

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