Compare commits

..

311 Commits
v1.4.5 ... v1.5

Author SHA1 Message Date
Damien George
fe08e3a54f docs: Bump version to 1.5. 2015-10-21 16:58:52 +01:00
danicampora
8fd8bb36b3 cc3200: Bump version to 1.1.0
Incluides several improvements and a few API changes to comply
with the new hardware API.
2015-10-21 16:42:14 +02:00
danicampora
3b24e83731 docs/wipy: Fix formatting indentation. 2015-10-21 15:43:02 +02:00
danicampora
bb489066e8 docs/wipy: Remove incorrect references to usb configuration. 2015-10-21 15:41:36 +02:00
danicampora
109b363ddc docs/wipy: Add more tutorials and examples. 2015-10-21 15:30:57 +02:00
danicampora
075ca64521 cc3200: Fix UART tests after correcting uart.read() behaviour. 2015-10-21 15:30:57 +02:00
danicampora
be2879ce89 cc3200: Enable "all special methods" configuration option. 2015-10-21 15:30:57 +02:00
danicampora
ee0058d174 docs: Remove remaining references to 'af', which is now 'alt'. 2015-10-21 15:30:57 +02:00
danicampora
1f2daf4304 cc3200: Correct ticks_cpu and ticks_us functions in time module. 2015-10-21 15:30:57 +02:00
danicampora
1c7f9b16f0 cc3200: Remove UART info on README.md.
The UART REPL it's not enabled by default anymore.
2015-10-21 15:30:56 +02:00
danicampora
ceb169008d docs: Several corrections to the classes in the machine module. 2015-10-21 15:30:56 +02:00
danicampora
04db848dc7 docs: Add usocket and ussl modules' documentation. 2015-10-21 15:30:56 +02:00
danicampora
4b630c452d cc3200: Make socket.listen([backlog]) compliant with Python 3.5. 2015-10-21 15:30:56 +02:00
danicampora
719dca2515 cc3200: Clean-up socket constants. 2015-10-21 15:30:56 +02:00
danicampora
d67ea6b29f cc3200: Add comment about micropython extensions to standard modules. 2015-10-21 15:30:56 +02:00
danicampora
7ff585333e cc3200: uart.read() returns EGAIN if no chars available. 2015-10-21 15:30:56 +02:00
danicampora
9a507c67ad cc3200: Enable REPL autoindent. 2015-10-21 15:30:56 +02:00
Paul Sokolovsky
9d7ef05caf README: Document how to enable/build external dependencies. 2015-10-21 02:56:42 +03:00
Damien George
e693e52442 tests: Disable some tests for pyboard that do not run correctly. 2015-10-20 23:55:50 +01:00
Damien George
9d0192de4a stmhal: Enable "all special methods" configuration option. 2015-10-20 23:55:27 +01:00
Damien George
f09f8097d5 esp8266: Put more code in irom0 section, to get it building again. 2015-10-20 22:59:31 +01:00
Paul Sokolovsky
d19e4f0ba4 extmod/modussl: Remove unused header. 2015-10-20 17:41:59 +03:00
Damien George
f961456b29 lib/mp-readline: Add n_chars argument to mp_hal_erase_line_from_cursor.
If VT100 support is not available then a given implementation of
mp_hal_erase_line_from_cursor might need to know the number of characters
to erase.

This patch does not change generated code when VT100 is supported, since
compiler can optimise away the argument.
2015-10-20 13:27:14 +01:00
Damien George
22521ea9e2 py/nlrthumb: Make compatible with Cortex-M0 (ARMv6M instr set). 2015-10-20 13:26:34 +01:00
Damien George
04353cc85e py: With obj repr "C", change raw str accessor from macro to function.
This saves around 1000 bytes (Thumb2 arch) because in repr "C" it is
costly to check and extract a qstr.  So making such check/extract a
function instead of a macro saves lots of code space.
2015-10-20 12:38:54 +01:00
Damien George
183edefddd py: Add object repr "C", where 30-bit floats are stuffed in obj word.
This new object representation puts floats into the object word instead
of on the heap, at the expense of reducing their precision to 30 bits.
It only makes sense when the word size is 32-bits.
2015-10-20 12:38:54 +01:00
Damien George
aedb859177 py: Make float representation configurable with object representation. 2015-10-20 12:35:40 +01:00
Damien George
7e359c648b py: Move float e/pi consts to objfloat and make mp_obj_float_t private. 2015-10-20 12:35:17 +01:00
Damien George
aaef1851a7 py: Add mp_obj_is_float function (macro) and use it where appropriate. 2015-10-20 12:35:17 +01:00
Damien George
60401d461a stmhal/rtc: Fix indentation to use spaces rather than tabs. 2015-10-20 12:05:27 +01:00
Peter Hinch
b106532b32 stmhal/rtc: Init uses YMD rather than backup register to detect powerup. 2015-10-20 12:05:16 +01:00
Paul Sokolovsky
8e6e9eaea5 unix: Use "Ctrl" as a name of the key, not "CTRL". 2015-10-20 12:30:36 +03:00
Paul Sokolovsky
acea9352a9 tests/extmod: Add tests for sleep_ms/us(), ticks_ms/us/diff().
Simple smoke tests, mostly for coverage. Added to extmod based on the fact
that they're extensions to standard modules.
2015-10-20 01:54:20 +03:00
Paul Sokolovsky
9058a7031f travis: Build "deplibs" in unix port. 2015-10-20 01:50:27 +03:00
Tom Soulanille
a787467569 tools/pyboard: Add -c argument to run a program passed as a string. 2015-10-19 23:20:59 +01:00
Damien George
4078336d38 teensy: Update to compile with latest changes to stmhal Pin class. 2015-10-19 23:11:48 +01:00
Damien George
2f96b1982a stmhal: Bring Pin class close to new machine module specification.
Looks like we can use the same Pin class for legacy pyb module and new
machine module.
2015-10-19 22:50:59 +01:00
Paul Sokolovsky
bedab235f9 stmhal/uart: If char is not received within timeout, return EAGAIN error.
Instead of return 0, which means EOF. There's no good way to detect EOF on
continuously active bus like UART, and treat timeout as just temporary
unvailability of data. .read() method of UART object will return None in
this case (instead of 0, which again measn EOF). This is fully compliant
with unix port.
2015-10-20 00:27:07 +03:00
Damien George
83158e0e7f stmhal: Implement os.dupterm (was pyb.repl_uart).
pyb.repl_uart still exists but points to os.dupterm.
2015-10-19 21:57:41 +01:00
Damien George
d8066e999d stmhal: Add sleep_{ms,us} and ticks_{ms,us,cpu,diff} to time module.
pyb module still has pyb.delay and pyb.udelay, but these now point to
time.sleep_ms and time.sleep_us respectively.
2015-10-19 21:45:51 +01:00
Dave Hylands
504420c51d stmhal: Early version of machine module for stmhal. 2015-10-19 21:12:42 +01:00
Paul Sokolovsky
2c040edef8 libffi: Skip building docs.
This requires makeinfo installed and wastes time (especially in CI).
2015-10-19 22:30:03 +03:00
danicampora
9c72c71c05 cc3200: WLAN class can retrieve the existing instance. 2015-10-19 21:17:15 +02:00
danicampora
f4c50f1cfc tests/wipy: Make WLAN test more stable. 2015-10-19 21:17:15 +02:00
danicampora
ae70e98ed4 cc3200: Fix time.ticks_* functions. 2015-10-19 21:17:15 +02:00
danicampora
8faf2dc75b docs/wipy: Add wipy tutorials section. 2015-10-19 21:17:15 +02:00
danicampora
36ae417c9f docs: Add wipy and network.server documentation. 2015-10-19 21:17:15 +02:00
danicampora
2e0cd20a1d cc3200: Refactor network module to make the server a propper object. 2015-10-19 21:17:15 +02:00
danicampora
65f6324573 cc3200: Increase stack sizes a bit. 2015-10-19 21:17:15 +02:00
danicampora
d8137178bb cc3200: Create wipy module, remove HeartBeat class.
The heartbeat is now controllable via a single function within the
wipy module.
2015-10-19 21:17:15 +02:00
Paul Sokolovsky
39a380b621 unix/modos: Android Bionic lacks statvfs(), has BSD statfs(). 2015-10-19 21:43:20 +03:00
Paul Sokolovsky
e0f5df579b all: Make netutils.h available to all ports by default.
Generally, ports should inherit INC from py.mk, append to it, not
overwrite it. TODO: Likely should do the same for other vars too.
2015-10-19 18:32:42 +03:00
Paul Sokolovsky
8ee153f234 unix/modtime: Implement ticks_ms(), ticks_us() and ticks_diff().
All of these functions return positive small int, thus range is 2 bits less
than word size (30 bit on 32-bit systems, 62 bit on 64-bit systems).
2015-10-19 17:48:27 +03:00
Paul Sokolovsky
fd379db286 unix/modtime: Implement sleep_ms(), sleep_us(). 2015-10-19 17:48:27 +03:00
Damien George
096d1e4512 py: Add lsl/lsr/asr opcode support to inline Thumb2 assembler. 2015-10-19 14:26:19 +01:00
Paul Sokolovsky
949c5c9180 unix/unix_mphal: Implement HAL_Delay() and HAL_GetTick(). 2015-10-19 00:31:37 +03:00
Paul Sokolovsky
7799410950 py/stream: Allow to reuse is_nonblocking_error(). 2015-10-18 15:39:33 +03:00
Paul Sokolovsky
2ca7b05552 unix/modos: Checking config macros requires mpconfig.h. 2015-10-18 03:05:47 +03:00
Paul Sokolovsky
f8e9ef5cd0 unix/modos: Guard sys/statvfs.h include with MICROPY_PY_OS_STATVFS check.
E.g. Windows lacks this header.
2015-10-18 02:54:20 +03:00
danicampora
020386b61c docs: In top index fix machine module link for the WiPy. 2015-10-18 00:31:12 +02:00
Paul Sokolovsky
c3000b6f69 unix/modos: Add statvfs() function.
Another function (like stat) which is problematic to deal with on ABI level
(FFI), as struct statvfs layout may differ unpredictably between OSes and
even different versions of a same OS. So, implement it in C, returning a
10-element tuple of f_bsize, f_frsize, f_blocks, f_bfree, f_bavail, f_files,
f_ffree, f_favail, f_flag, f_namemax. This is exactly the order described
in Python3 docs, https://docs.python.org/3/library/os.html#os.statvfs
(but note that os.statvfs() should make these values available as
attributes).
2015-10-18 01:21:23 +03:00
Paul Sokolovsky
6ec6f51326 unix: Build libffi in a directory which is gitgnored.
To avoid "-dirty" version previous and spurious "modified" output from
git status, etc.
2015-10-18 00:44:45 +03:00
danicampora
4542643025 docs: Update all WiPy docs to reflect the new API. 2015-10-17 23:29:04 +02:00
danicampora
fca3308cc3 cc3200: Improvements to terminal duplication. 2015-10-17 23:21:44 +02:00
danicampora
e19dfe1c32 cc3200: In scan results rename 'auth' field to 'sec'.
As defined by the new API, since 'auth' is actually a  tuple
composed by the security type and the key.
2015-10-17 23:21:44 +02:00
Dave Hylands
affcbe4139 stmhal: Make USB serial number actually be unique. 2015-10-17 22:02:57 +01:00
Paul Sokolovsky
6a515b95a8 tools/upip: Update to 0.5.9.
MICROPYPATH environment variable is now honored, package are installed to
first path specified in it.
2015-10-17 20:16:41 +03:00
Paul Sokolovsky
c13be69a8e lib/libffi: Add libffi as a submodule.
This allows to build libffi from source together with micropython, and is
useful for cross-compilation. Support for this was already merged
previously, to use:

make libffi
make MICROPY_STANDALONE=1

(To both commands appropriate cross-compilition flags can be added).
2015-10-17 15:52:35 +03:00
Damien George
035a0a2b6e py: Add support for _ in REPL to hold last computed value.
Only available when MICROPY_CAN_OVERRIDE_BUILTINS is enabled.
2015-10-17 12:55:25 +01:00
Damien George
e813541e3f py: Add option for inline assembler to support ARMv7-M instructions.
Cortex-M0, M0+ and M1 only have ARMv6-M Thumb/Thumb2 instructions.  M3,
M4 and M7 have a superset of these, named ARMv7-M.  This patch adds a
config option to enable support of the superset of instructions.
2015-10-16 22:08:57 +01:00
Damien George
4bf3f2d3c0 py: Fix with+for+return bug by popping for-iter when unwinding exc stack.
Addresses issue #1182.
2015-10-15 17:48:28 +01:00
Damien George
556c8a9a4f unix: Fix coverage build now that mp_plat_print uses write. 2015-10-15 00:23:03 +01:00
Damien George
4300c7dba2 py: Remove dependency on printf/fwrite in mp_plat_print.
See issue #1500.
2015-10-15 00:05:55 +01:00
Paul Sokolovsky
74d0df7324 unix: Allow to build against Android down to 1.5.
Bionic libc in Android 1.5 missed log2() and nan() functions.
2015-10-15 00:11:09 +03:00
Damien George
d7e3b36a09 py/compile: Remove unnecessary label in compilation of for statement. 2015-10-14 15:51:12 +01:00
Damien George
fcce1483fa py: Fix build of ARM native emitter due to recent viper changes.
Addresses #1510.
2015-10-14 12:40:54 +01:00
Paul Sokolovsky
2430dfac31 tests/jni: Start adding modjni tests.
These are currently not intended to run with the rest of testsuite, as
they require dependencies and special environment setup anyway (drafted
in tests/jni/README).
2015-10-14 00:56:01 +03:00
Paul Sokolovsky
fe29cc192d unix/modjni: Add iteration support for Java List objects.
Using generic iteration-via-subscription support (TODO: factor it out for
reuse).
2015-10-14 00:36:03 +03:00
Paul Sokolovsky
41eb705477 unix/modjni: call_method: Check for Java exception after method return. 2015-10-14 00:25:10 +03:00
Damien George
2ec835f572 tests: Add more tests for viper 16/32-bit load/store, and ellipsis. 2015-10-13 18:24:36 +01:00
Damien George
59a41e8fcd py/qstr: Fix calc of qstr memory usage, due to new qstr chunk allocation. 2015-10-13 15:52:06 +01:00
Damien George
d6442407f5 docs: Fix formatting of DAC code examples. 2015-10-13 14:44:00 +01:00
Damien George
b5c43be135 stmhal: Allow to set bits resolution for DAC; 8 is default, can have 12.
This patch allows to configure the DAC resolution in the constructor and
in the init function, eg:

dac = DAC(1, bits=12).

The default resolution is 8 bits for backwards compatibility.  The bits
sets the maximum value accepted by write and write_timed methods, being
2**bits - 1.

When using write_timed with 12-bit resolution, the input buffer is
treated as an unsigned half-word array, typecode 'H'.

See PR #1130 for discussion.
2015-10-13 14:33:04 +01:00
Damien George
b8f9ac5411 py: Implement ptr32 load and store in viper emitter. 2015-10-13 00:50:17 +01:00
Paul Sokolovsky
21f43ba9b0 unix/modtermios: tcsetattr: If 0 passed for "when" param, treat as TCSANOW.
As we dn't export constants for TCSANOW, etc., zero makes a good "don't
care" param, and now it will work also under Android Bionic and any other
libc.
2015-10-13 00:37:55 +03:00
Damien George
3c9c3687d6 py: Add support to call __init__ from a builtin module on first import. 2015-10-12 13:46:01 +01:00
Paul Sokolovsky
408b74d74c py: Allow to to build MicroPython as a static library.
The whole current port gets slurped into a static lib named
"libmicropython.a". Maybe that's not ideal, but at least something
to start with.
2015-10-12 15:32:06 +03:00
Damien George
fdfcee7b1e py/parse: Make parser error handling cleaner, less spaghetti-like. 2015-10-12 12:59:18 +01:00
Damien George
64f2b213bb py: Move constant folding from compiler to parser.
It makes much more sense to do constant folding in the parser while the
parse tree is being built.  This eliminates the need to create parse
nodes that will just be folded away.  The code is slightly simpler and a
bit smaller as well.

Constant folding now has a configuration option,
MICROPY_COMP_CONST_FOLDING, which is enabled by default.
2015-10-12 12:58:45 +01:00
Paul Sokolovsky
91fc075a33 py/objarray: Allow to create array of void pointers, as extension to CPython.
Using 'P' format specifier (matches struct module). This is another shortcut
for FFI, just as previously introduced "array of objects" ('O').
2015-10-12 10:13:51 +03:00
Damien George
3aa7dd23c9 unix: Add exit and paste-mode hints to shell startup banner.
Thanks to @nyov for the initial patch.
2015-10-12 00:19:00 +01:00
nyov
fccbe9aa4d README.md: Document "Ctrl+D" shell exit. 2015-10-12 00:15:41 +01:00
Damien George
0334058fa4 Rename "Micro Python" to "MicroPython" in REPL, help, readme's and misc. 2015-10-12 00:06:25 +01:00
Damien George
6206f431cf stmhal: Enable REPL auto indent; document paste mode in help(). 2015-10-11 23:33:46 +01:00
Damien George
46a1102852 repl: Add paste mode to friendly REPL, entered via CTRL-E.
Use CTRL-E to enter paste mode.  Prompt starts with "===" and accepts
all characters verbatim, echoing them back.  Only control characters are
CTRL-C which cancels the input and returns to normal REPL, and CTRL-D
which ends the input and executes it.  The input is executed as though
it were a file.  The input is not added to the prompt history.
2015-10-11 23:30:22 +01:00
Paul Sokolovsky
1b586f3a73 py: Rename MP_BOOL() to mp_obj_new_bool() for consistency in naming. 2015-10-11 15:18:15 +03:00
Paul Sokolovsky
53ca6ae1f3 py/makeqstrdata.py: Catch and report case of empty input file.
The usual cause would be that a cross-compiler for a port is not in PATH.
2015-10-11 11:09:57 +03:00
Anmol Sarma
95b352064e unix/modsocket: Fix usage of pointers to locals outside scope 2015-10-10 17:29:26 +05:30
Damien George
24652228af drivers/sdcard: Allow up to 5 retries to initialise SD card.
Apparently some cards need more than 2 retries.  See issue #1482.
2015-10-10 00:07:40 +01:00
Damien George
845b5a2a58 docs: Describe properly how MCU can be woken from pyb.standby() state. 2015-10-10 00:03:14 +01:00
Paul Sokolovsky
7381b7ac71 unix/modjni: py2jvalue: Support bool and None values. 2015-10-10 01:20:48 +03:00
Peter Hinch
0e87bc7be6 tests: In pyb RTC tests, check wakeup register values. 2015-10-09 23:06:05 +01:00
Dave Hylands
01d64914c5 stmhal: Fix USB CDC-only mode under Windows.
This fix adds PIDs 9801 and 9802 to the pybcdc.inf file.

When in CDC only mode, it presents itself as a Communcations
device rather than as a composite device. Presenting as a
composite device with only the CDC interface seems to confuse
windows.

To test and make sure that the correct pybcdc.inf was being used,
I used USBDeview from http://www.nirsoft.net/utils/usb_devices_view.html
to uninstall any old pyboard drivers (Use Control-F and search
for pyboard). I found running USBDeview as administrator worked best.

Installing the driver in CDC+MSC mode first is recommended (since the
pybcdc.inf file in on the internal flash drive). Then when you switch
modes everything seems to work properly.

I used https://github.com/dhylands/upy-examples/blob/master/boot_switch.py
to easily switch the pyboard between the various USB modes for testing.
2015-10-09 00:18:01 +01:00
Damien George
366239b8b9 py/parse: Factor logic when creating parse node from and-rule. 2015-10-08 23:13:18 +01:00
Paul Sokolovsky
02041bf2e0 unix/modjni: jvalue2py() is currently not used.
Not remove so far, may be needed later.
2015-10-09 00:27:27 +03:00
Paul Sokolovsky
216b6a494e unix/modjni: Allow to access fields of objects. 2015-10-08 16:57:02 +03:00
Damien George
b948de36fb py: Don't generate unnecessary parse nodes for assignment or kwargs.
This patch eliminates the need for a nested parse node for assignments
and keyword arguments.  It saves a little bit of RAM when parsing.
2015-10-08 14:26:01 +01:00
Damien George
4fb5ff86ee tests: Add test for evaluation order of dictionary key/value pairs.
In Python 3.4 the value is evaluated before the key.  In Python 3.5 it's
key then value.
2015-10-08 13:15:07 +01:00
Damien George
9f5f156b9d py/emitnative: Raise ViperTypeError for unsupported unary ops. 2015-10-08 13:08:59 +01:00
Damien George
7e12a601b8 py/compile: Fix edge case when constant-folding negation of integer.
Also adds tests specifically for testing constant folding.
2015-10-08 13:02:00 +01:00
Damien George
2a8d7ee0f8 stmhal: Fix RTC.wakeup so it correctly calculates WUT for large periods.
Thanks to Peter Hinch.  Addresses issue #1488.
2015-10-08 12:41:12 +01:00
Paul Sokolovsky
fd38799049 unix/modjni: After Call*Method(), Java exception should always be checked.
OpenJDK seemed to return NULL in case of exception, but Dalvik returns
arbitrary value, so skip such "optimizations".
2015-10-07 07:40:29 +03:00
Damien George
fa391eed9d stmhal: In RTC.wakeup, fix setting of wucksel to get correct period.
Thanks to Peter Hinch.  See issue #1490.
2015-10-06 23:39:57 +01:00
Radomir Dopieralski
37ab061f4d docs: Update esp8266 documentation to match the code.
* Move the esp.status() to network module.
* Describe the wifi.isconnected() method.
* Describe esp.mac(), esp.wifi_mode(), esp.phy_mode(), esp.sleep_type(),
  esp.deepsleep(), and esp.flash_id() functions.
2015-10-06 23:25:35 +01:00
Paul Sokolovsky
aaa8867d4a modussl: SSL socket wrapper module based on axTLS. 2015-10-06 18:10:39 +03:00
Paul Sokolovsky
062bd81814 tests/basics/builtin_range: PEP8 fixes. 2015-10-05 20:02:52 +03:00
Paul Sokolovsky
f4d55c91fe lib/axtls: Update submodule, adds .gitignore . 2015-10-04 15:55:37 +03:00
Paul Sokolovsky
326ff54649 unix: Add support for building axtls dependency lib. 2015-10-04 02:39:01 +03:00
Paul Sokolovsky
90a36942b4 lib/axtls: Add axtls git submodule, dependency of modussl.
From https://github.com/pfalcon/axtls , branch micropython.
2015-10-04 02:39:00 +03:00
Paul Sokolovsky
1ea4b77a9a unix/modjni: jclass.__str__/__repr__: Return Java .toString() value. 2015-10-04 01:57:07 +03:00
Damien George
0496de26d3 py: Allow to enable inline assembler without native emitter. 2015-10-03 17:07:54 +01:00
Paul Sokolovsky
f22be4ebd9 unix/modjni: jobject.__str__/__repr__: Return Java .toString() value. 2015-10-03 08:58:46 -07:00
Damien George
34f26ea862 tests: Allow tests to pass against CPython 3.5.
All breaking changes going from 3.4 to 3.5 are contained in
basics/python34.py.
2015-10-02 13:01:47 +01:00
Paul Sokolovsky
9e0a3d46b6 unix/modjni: Convert Java's IndexOutOfBoundsException to Python's IndexError. 2015-10-02 00:22:09 -07:00
Damien George
90b1cc5103 minimal: Tune parser chunk allocation policy for very small heap. 2015-10-02 00:33:26 +01:00
Damien George
58e0f4ac50 py: Allocate parse nodes in chunks to reduce fragmentation and RAM use.
With this patch parse nodes are allocated sequentially in chunks.  This
reduces fragmentation of the heap and prevents waste at the end of
individually allocated parse nodes.

Saves roughly 20% of RAM during parse stage.
2015-10-02 00:11:11 +01:00
Damien George
e5635f4ab3 py: Catch all cases of integer (big and small) division by zero. 2015-10-01 22:48:48 +01:00
Damien George
2065373f67 py/mpz: Fix bignum anding of large negative with smaller positive int. 2015-10-01 22:35:06 +01:00
Damien George
a81539db25 tests: Add further tests for mpz code. 2015-10-01 18:49:37 +01:00
Damien George
2f4e8511cd py/mpz: Force rhs of mpz_shl_inpl/mpz_shr_inpl to be unsigned.
Python semantics are that rhs of shift must be non-negative, so there's
no need to handle negative values in the underlying mpz implementation.
2015-10-01 18:01:37 +01:00
Damien George
4c02e54298 py/mpz: Raise NotImplError instead of failing assertion. 2015-10-01 17:57:36 +01:00
Damien George
5f3c3ec5e6 py/parsenum: Provide detailed error for int parsing with escaped bytes.
This patch adds more fine grained error message control for errors when
parsing integers (now has terse, normal and detailed).  When detailed is
enabled, the error now escapes bytes when printing them so they can be
more easily seen.
2015-10-01 17:18:12 +01:00
Paul Sokolovsky
c4489a0543 unix/modjni: Propagate Java exceptions on list access. 2015-10-01 01:20:56 -07:00
Paul Sokolovsky
0eba162ab5 unix/modjni: Fix method argument matching. 2015-09-30 00:55:09 -07:00
Paul Sokolovsky
f3ca8623f7 unix/modjni: Implement len() for objects with java.util.List interface. 2015-09-29 10:06:07 -07:00
Paul Sokolovsky
77020281ae unix/modjni: call_method: Delete done local references in loop.
To avoid local ref table overflow.
2015-09-28 08:37:34 -07:00
Tom Soulanille
f1a9923308 py/objrange: Bugfix for range_subscr() when index is a slice object. 2015-09-28 14:01:28 +00:00
Tom Soulanille
2a8a564fbd tests: Test slicing a range that does not start at zero. 2015-09-28 14:01:20 +00:00
Paul Sokolovsky
0d28a3edb9 unix/modjni: call_method: Better resource release. 2015-09-27 22:32:54 -07:00
Daniel Campora
ff736d6f6f cc3200: WiPy SW v1.0.0 release. 2015-09-28 00:14:25 +02:00
Daniel Campora
d88d3b0b3a tests/wipy: Skip the rtc_irq test. 2015-09-27 21:36:38 +02:00
Daniel Campora
b6bdb0dbda cc3200: Always reset WLAN after setting the mode. 2015-09-27 20:12:42 +02:00
Daniel Campora
ed6a5b78ad cc3200: Make auth param positional in wlan.connect. 2015-09-27 19:10:09 +02:00
Daniel Campora
d5de1bf853 tests: Skip uheapq1 test if target is WiPy. 2015-09-27 18:47:35 +02:00
Daniel Campora
eb9a3ec654 cc3200: Disable uheapq and uhashlib.
Those two are rarely used features and better to have the extra heap.
2015-09-27 18:04:11 +02:00
Daniel Campora
6143f63560 tests/wipy: Fix error in wlan test. 2015-09-27 18:00:36 +02:00
Daniel Campora
37a2015cc5 tests/wipy: Add machine module tests. 2015-09-27 17:35:58 +02:00
Daniel Campora
958e273336 tests: Skip extmod machine tests when target is WiPy. 2015-09-27 17:35:45 +02:00
Daniel Campora
c92e6a45eb cc3200: Rename pyb module to machine. 2015-09-27 16:50:27 +02:00
Daniel Campora
0a7e4fa5ce tests/wipy: Improve robustness of rtc_irq test. 2015-09-27 14:20:38 +02:00
Daniel Campora
8192310dad tests/wipy: Improve robustness of time test. 2015-09-27 12:32:02 +02:00
Daniel Campora
ef369249cb cc3200: Implement support for os.dupterm(). 2015-09-27 11:27:24 +02:00
Daniel Campora
a7261ae059 cc3200/mods: Use mp_obj_get_array_fixed_n() where applicable. 2015-09-27 09:28:27 +02:00
Daniel Campora
635ef16432 cc3200/tools: Improve update script robustness. 2015-09-27 02:00:46 +02:00
Daniel Campora
57fa14b5be cc3200: New WLAN API including test. 2015-09-27 01:50:52 +02:00
Daniel Campora
dbdcb58d64 cc3200: New irq API, affects all classes that provide the irq method. 2015-09-27 01:48:20 +02:00
Paul Sokolovsky
81d64ab939 unix/modjni: call_method(): If name doesn't match, cleanup via goto next_method. 2015-09-26 08:51:22 -07:00
Paul Sokolovsky
c0a79cc919 unix/modjni: Need to really use per-rettype Call*Method functions. 2015-09-26 08:49:12 -07:00
Paul Sokolovsky
7e18d3b6ff unix/modjni: new_jobject(): Handle null reference. 2015-09-24 15:29:57 -07:00
Damien George
9d5e5c08ab py/compile: Put compiler state on the C stack.
It's relatively small (between 44 and 56 bytes) and helps to reduce heap
pressure and fragmentation during compilation.
2015-09-24 13:15:57 +01:00
Damien George
5572f735b6 docs: Bump version to 1.4.6. 2015-09-23 17:16:22 +01:00
Paul Sokolovsky
e632b1fda7 unix/modjni: Factor out is_object_type(). 2015-09-23 07:11:56 -07:00
stijn
941040e9e8 windows: Make mpconfigport.h up-to-date with the unix port 2015-09-23 07:10:00 -07:00
stijn
dfa915a6af tests: Omit process output parsing in case of CalledProcessError
Adding a line-end makes the determination of skip_native fail as it compares
the output against b'CRASH' while it is in fact b'CRASH\n'
2015-09-23 11:50:24 +01:00
Damien George
fbcaf0ea18 py: Slightly simplify compile and emit of star/double-star arguments.
Saves a few bytes of code space and eliminates need for rot_two
bytecode (hence saving RAM and execution time, by a tiny bit).
2015-09-23 11:47:01 +01:00
Delio Brignoli
e6978a4e26 py: Fix call args when a stararg is followed by keyword args. 2015-09-23 11:37:00 +01:00
Vicente Olivert Riera
587914169c unix/modffi.c: cast first to intptr_t when casting from/to pointer
This fixes errors like these ones:

modffi.c: In function 'return_ffi_value':
modffi.c:143:29: error: cast to pointer from integer of different size
[-Werror=int-to-pointer-cast]
             const char *s = (const char *)val;
                             ^
modffi.c:162:20: error: cast to pointer from integer of different size
[-Werror=int-to-pointer-cast]
             return (mp_obj_t)val;
                    ^
modffi.c: In function 'ffifunc_call':
modffi.c:358:25: error: cast from pointer to integer of different size
[-Werror=pointer-to-int-cast]
             values[i] = (ffi_arg)a;
                         ^
modffi.c:373:25: error: cast from pointer to integer of different size
[-Werror=pointer-to-int-cast]
             values[i] = (ffi_arg)s;
                         ^
modffi.c:381:25: error: cast from pointer to integer of different size
[-Werror=pointer-to-int-cast]
             values[i] = (ffi_arg)bufinfo.buf;
                         ^
modffi.c:384:25: error: cast from pointer to integer of different size
[-Werror=pointer-to-int-cast]
             values[i] = (ffi_arg)p->func;
                         ^

These errors can be highlighted when building micropython from MIPS64
n32 because ffi_arg is 64-bit wide and the pointers on MIPS64 n32 are
32-bit wide, so it's trying to case an integer to a pointer (or
vice-versa) of a different size. We should cast first the pointer (or the
integer) to a pointer sized integer (intptr_t) to fix that problem.

Signed-off-by: Vicente Olivert Riera <Vincent.Riera@imgtec.com>
2015-09-22 18:54:31 -07:00
Paul Sokolovsky
ed22e9ba3e unix/modjni: Move type analysis logic to new_jobject(), for reuse. 2015-09-22 17:02:17 -07:00
stijn
dcbe936c50 windows/msvc: Exclude modjni from build. 2015-09-22 11:07:03 +01:00
Daniel Campora
dffa9f6da6 cc3200: New SD and RTC API plus os and time modules' extensions. 2015-09-21 22:30:32 +02:00
Daniel Campora
660f8613fd tests/wipy: Remove unneeded dependencies to pyb.Pin. 2015-09-21 22:30:11 +02:00
Daniel Campora
06d93b36f9 cc3200: Correct safe boot level 1 blinking period. 2015-09-21 22:30:04 +02:00
Paul Sokolovsky
b2d880d749 unix/modjni: Support for subscripting of Java lists (r/o so far). 2015-09-21 12:02:54 -07:00
Paul Sokolovsky
6196aa45ed unix/modjni: jvalue2py: Handle boolean. 2015-09-20 00:36:51 +03:00
Alex March
15018291b2 tests: Add escaped quotes tests for REPL.
Test possible combinations of single and double quotes with escaped
quotes and parenthesis with and without function calls in REPL.

Covers: #1419
2015-09-19 14:06:23 +01:00
Alex March
bfb272b9e0 py/repl: Treat escaped quotes correctly in REPL continuation.
Escaped quotes are now recognised correctly in REPL when used
inside normal quotes.

Fixes: #1419
2015-09-19 14:06:23 +01:00
Alex March
c0035d1694 unix: Use MICROPY_HAL_H macro for header inclusion.
Follow the same format as other ports using the macro to include
the HAL header.
2015-09-19 14:03:57 +01:00
Paul Sokolovsky
1e9d8e110b unix/modjni: py2jvalue: Pass jobject's down to Java.
So far, no signature check is done (TODO).
2015-09-19 01:05:25 +03:00
Damien George
b0c08c8c17 drivers/nrf24l01: Fix SPI phase setting to match specs of nRF chip.
Addresses issue #1466.
2015-09-18 13:00:12 +00:00
Paul Sokolovsky
011c7f5718 unix/modjni: py2jvalue: Handle both int and long java types (with TODO for long). 2015-09-18 13:21:21 +03:00
Paul Sokolovsky
1cb5de2cd5 unix/modjni: jvalue2py: Handle class-containing jvalues. 2015-09-17 13:31:40 +03:00
Daniel Campora
861fad5819 docs: Adapt WiPy's ADC doc and quickref to the new API. 2015-09-16 10:10:40 +02:00
Daniel Campora
22b4c28f85 cc3200: New ADC API. 2015-09-16 10:10:38 +02:00
Daniel Campora
0e52d9860a tests/wipy: Improve I2C tests. 2015-09-16 10:10:35 +02:00
Daniel Campora
aba75e1233 cc3200: New SPI API. 2015-09-16 10:10:33 +02:00
Daniel Campora
624cdeacc4 docs/wipy: Add pins to the I2C constructor. 2015-09-16 10:10:31 +02:00
Daniel Campora
41f6948545 cc3200: New WDT API. 2015-09-16 10:10:29 +02:00
Daniel Campora
8332044f75 cc3200: Add UART.ODD and UART.EVEN to select parity. 2015-09-16 10:10:26 +02:00
Daniel Campora
d5ec336eef cc3200: Replace Pin.PULL_NONE with None. 2015-09-16 10:10:24 +02:00
Daniel Campora
f38d16483a docs: Update I2C and UART docs to match the new API. 2015-09-16 10:10:22 +02:00
Daniel Campora
e77abc261b cc3200: Default peripheral ID support on I2C. 2015-09-16 10:10:19 +02:00
Daniel Campora
c69642a460 cc3200: Increase error led blynk period to 100ms 2015-09-16 10:10:17 +02:00
Daniel Campora
3c4b78e166 cc3200: Keep overwriting the same image on sequential updates. 2015-09-16 10:10:15 +02:00
Daniel Campora
7d6b6f6681 cc3200: Make UART choose default id when not given. 2015-09-16 10:10:13 +02:00
Daniel Campora
4ba9b34012 cc3200: Reduce servers cycle time to improve FTP transfer rate. 2015-09-16 10:10:11 +02:00
Paul Sokolovsky
cb6cf5e257 unix/modjni: Add env() module function.
Useful to load native method libraries not loaded by VM (as happens on
Android).
2015-09-16 01:10:09 +03:00
Tom Soulanille
661d9d1901 py/objslice: Fix indent. 2015-09-15 22:46:30 +01:00
Tom Soulanille
aeb62f9ae3 py/objslice: Make slice attributes (start/stop/step) readable.
Configurable with MICROPY_PY_BUILTINS_SLICE_ATTRS.  Disabled by default.
2015-09-15 21:59:20 +01:00
Damien George
d80174d7c3 stmhal: Use polling, not DMA, for 1 byte SPI transfers.
There is an issue sending 1 byte on the SPI bus using DMA, but it only
occurs when the transmit is done for the first time after initialising
the SPI and DMA peripherals.  All other cases (sending 2 or more bytes,
doing send_recv, doing recv first) work okay.  We sidestep this issue by
using polling (not DMA) for all 1 byte transfers.  This is fine because
a 1 byte transfer can't be interrupted and doesn't need the benefits of
DMA (and using polling for this case is more efficient).

Resolves #1456.
2015-09-15 20:45:37 +01:00
Bill Owens
e2bfa471fa esp8266: Added wlan.isconnected() to maintain parity with other ports. 2015-09-15 20:07:50 +03:00
Tom Soulanille
04fffe6562 tests/README: Explain how tests get skipped 2015-09-15 20:05:05 +03:00
Damien George
0d6b2341b8 pic16bit: Add basic unistd.h file since it's not provided by tool chain. 2015-09-15 16:24:13 +01:00
Damien George
8b4fb4fe14 py/mpz: Fix calculation of max digit storage for mpz; fix sys.maxsize.
When creating constant mpz's, the length of the mpz must be exactly how
many digits are used (not allocated) otherwise these numbers are not
compatible with dynamically allocated numbers.

Addresses issue #1448.
2015-09-15 16:15:57 +01:00
Paul Sokolovsky
b230a86d33 unix/modjni: Return any object type value as a jobject. 2015-09-15 14:07:39 +03:00
Paul Sokolovsky
5167332131 unix/modjni: Return Java null as Python None. 2015-09-14 00:15:35 +03:00
Paul Sokolovsky
7a4b10cc4c unix/modjni: Support static methods. 2015-09-14 00:12:47 +03:00
Paul Sokolovsky
a5deadf082 tools: Upgrade upip to 0.5.8.
Adds support for ussl module (which is experimental and not fully
implemented yet itself).
2015-09-13 09:49:09 +03:00
Paul Sokolovsky
26a9b4d48e unix/modjni: Factor out new_jobject(), jvalue2py() functions. 2015-09-13 01:27:47 +03:00
Tom Soulanille
7731edf2f5 stmhal: Add "opt" arg to pyb.main, to set mp_optimise_value.
Use this to set the global optimisation value when executing the main
script (and all scripts it imports).
2015-09-12 22:53:54 +01:00
Damien George
229b908d2e esp8266: Remove "time" command from deploy target. 2015-09-12 22:22:30 +01:00
Damien George
3ca84026db unix: Enable REPL auto-indent. 2015-09-12 22:09:18 +01:00
Damien George
0af73014cc lib/mp-readline: Add auto-indent support.
4 spaces are added at start of line to match previous indent, and if
previous line ended in colon.

Backspace deletes 4 space if only spaces begin a line.

Configurable via MICROPY_REPL_AUTO_INDENT.  Disabled by default.
2015-09-12 22:07:23 +01:00
Paul Sokolovsky
4e7bde8c9e unix/modjni: Factor out py2jvalue() function. 2015-09-12 00:20:06 +03:00
Dave Hylands
9d6128acdc stmhal: fix single precision float printing error
Fixes #1435.
2015-09-11 23:09:50 +03:00
Paul Sokolovsky
e79c6b6312 unix/modjni: "jni" module to interface to JNI-compliant JavaVM.
This includes Android Dalvik VM for example.

Example usage:

import jni
System = jni.cls("java/lang/System")
System.out.println("Hello, Java!")
2015-09-11 21:38:57 +03:00
Daniel Campora
f352fe82a5 tests/wipy: Add I2C tests. 2015-09-10 08:00:59 +02:00
Daniel Campora
d265df589e tests/wipy: Disable the REPL on UART before running the UART test. 2015-09-10 08:00:53 +02:00
Daniel Campora
7c87747db0 cc3200: Disable some uPy features in debug mode to help code fit. 2015-09-10 08:00:47 +02:00
Daniel Campora
425958b616 cc3200: Add SDcard pin af on index 8. 2015-09-10 08:00:41 +02:00
Daniel Campora
4cc0cd6cab tests/wipy: Additional tests for when the UART is un-initialized. 2015-09-10 08:00:35 +02:00
Daniel Campora
d936317143 cc3200: New I2C API. 2015-09-10 08:00:30 +02:00
Daniel Campora
359b4e9ed9 cc3200: Refactor pin af assigment functions. 2015-09-10 08:00:24 +02:00
Daniel Campora
1d399c3c88 cc3200: Improve file system check routine. 2015-09-10 08:00:18 +02:00
Daniel Campora
4d7fa05b43 cc3200: Improve Pin and UART implementation.
Deassign pins af before assigning. Make uart.any() return the
correct value everytime, this requires interrupts to be always
enabled.
2015-09-10 08:00:12 +02:00
Daniel Campora
4054c4eadd cc3200: Remove I2C inline documentation (sphinx is on the lead). 2015-09-10 08:00:05 +02:00
Daniel Campora
f8b98d8329 tests/wipy: Improve UART tests with no pin assignment case. 2015-09-10 07:59:59 +02:00
Daniel Campora
88ca6c94d9 tests: Ignore exception chain test on the WiPy.
Fails because warnings are not enabled on the CC3200.
2015-09-10 07:59:53 +02:00
Daniel Campora
f91f212d9f cc3200: New UART API plus related test. 2015-09-10 07:59:47 +02:00
Daniel Campora
36821d095a cc3200: Add alternate functions list to Pin object.
Also remove pin.high() and pin.low() methods.
2015-09-10 07:59:41 +02:00
Daniel Campora
d5e256486e cc3200: Re-work Pin class according to the new API.
Also add relevant test.
2015-09-10 07:59:35 +02:00
Daniel Campora
42054c3cad cc3200: Add mphal error to raise hardware related exceptions. 2015-09-10 07:59:29 +02:00
Daniel Campora
598aad2140 cc3200: Fix bug in pybsleep remove. 2015-09-10 07:59:23 +02:00
Daniel Campora
475c60eefc cc3200: Add alt param to Pin constructor. 2015-09-10 07:59:16 +02:00
Daniel Campora
86854c7071 cc3200: Adapt smoke.py for the new pin API. 2015-09-10 07:59:10 +02:00
Daniel Campora
e3f8777ee8 cc3200: Implement new Pin API. 2015-09-10 07:59:03 +02:00
Daniel Campora
ec8589e4c9 cc3200: Improve uniflash script and make it a bit more verbose. 2015-09-10 07:56:48 +02:00
Daniel Campora
b864e7afe4 cc3200: Remove the UART0 programming pins from the smoke test. 2015-09-10 07:56:46 +02:00
Damien George
75a811a6df tests: Move int+unicode test to unicode-specific test directory. 2015-09-07 21:36:24 +01:00
Damien George
2b000474d9 py/lexer: Properly classify floats that look like hex numbers.
Eg 0e0 almost looks like a hex number but in fact is a float.
2015-09-07 17:33:44 +01:00
Damien George
0be3c70cd8 py/lexer: Raise SyntaxError when unicode char point out of range. 2015-09-07 17:19:17 +01:00
Damien George
081f9325f5 py/lexer: Raise NotImplError for unicode name escape, instead of assert. 2015-09-07 17:08:49 +01:00
Damien George
a7ffa972f3 tests: Add tests for non-compliant behaviour of lexer. 2015-09-07 16:59:55 +01:00
Damien George
558a016e2c py/compile: Refine SyntaxError for repeated use of global/nonlocal. 2015-09-07 16:55:02 +01:00
Damien George
3a2171e406 py: Eliminate some cases which trigger unused parameter warnings. 2015-09-04 16:53:46 +01:00
Damien George
42cec5c893 py/objstr: Check for keyword args before checking for no posn args.
Otherwise something like bytes(abc=123) will succeed.
2015-09-04 16:51:55 +01:00
Damien George
55b11e6d38 py/objstr: For str.endswith(s, start) raise NotImpl instead of assert. 2015-09-04 16:49:56 +01:00
Damien George
0b7a66ab97 py/objbool: Simplify dispatch of bool binary op.
This optimises (in speed and code size) for the common case where the
binary op for the bool object is supported.  Unsupported binary ops
still behave the same.
2015-09-04 16:46:15 +01:00
Damien George
ea5b59bfe6 py/compile: Only compile function annotations if really needed.
Function annotations are only needed when the native emitter is enabled
and when the current scope is emitted in viper mode.  All other times
the annotations can be skipped completely.
2015-09-04 16:44:14 +01:00
Tony Abboud
8d8fdcb4be stmhal: add option to query for the current usb mode
Fetch the current usb mode and return a string representation when
pyb.usb_mode() is called with no args. The possible string values are interned
as qstr's. None will be returned if an incorrect mode is set.
2015-09-03 23:30:43 +01:00
Damien George
821b7f22fe py: Use mp_not_implemented consistently for not implemented features. 2015-09-03 23:14:06 +01:00
Damien George
25afc7da0d tests: Add tests to improve coverage of objstr.c. 2015-09-03 23:06:18 +01:00
Damien George
e2aa117798 py/objstr: Simplify printing of bytes objects when unicode enabled. 2015-09-03 23:03:57 +01:00
Damien George
516982242d py: Inline single use of mp_obj_str_get_len in mp_obj_len_maybe.
Gets rid of redundant double check for string type.

Also remove obsolete declaration of mp_obj_str_get_hash.
2015-09-03 23:01:07 +01:00
Paul Sokolovsky
8bf00084b6 py: Make "enumerate" qstr be conditional on MICROPY_PY_BUILTINS_ENUMERATE. 2015-09-03 19:35:52 +03:00
Damien George
81794fcd31 py/binary: Add support for array('q') and array('Q'). 2015-09-01 16:31:48 +01:00
Damien George
22602cc37b py/objstr: Make str.rsplit(None,n) raise NotImpl instead of assert(0). 2015-09-01 15:35:31 +01:00
Paul Sokolovsky
1b693543aa tests: Skip exception_chain.py with native emitter. 2015-09-01 11:53:27 +03:00
Paul Sokolovsky
ab2594e341 tests: Add test for exception-chaining raise syntax. 2015-09-01 10:39:11 +03:00
Paul Sokolovsky
2ff2ea5f3b vm: Handle "raise X from Y" statements the best way we can.
By issuing a warning that exception chaining is not supported, and ignoring
"from Y" argument.
2015-09-01 10:39:04 +03:00
Paul Sokolovsky
21ffa7c4ba modbuiltins: Consistently use indentation for #if. 2015-08-31 00:22:11 +03:00
Paul Sokolovsky
696eee9475 modffi: dlsym() doesn't set errno, so use ENOENT for OSError.
This may be a bit confusing, as ENOENT is often rendered as "No such
file or directory", but any other code would be only more confusing.
2015-08-31 00:20:08 +03:00
Paul Sokolovsky
a9058bf294 unix: Allow to build libffi from source and link against it.
Linking against local libffi (and other libs in future) is triggered by
"make MICROPY_STANDALONE=1". Before that, dependent libs should be built
with "make deplibs".
2015-08-30 15:26:25 +03:00
Damien George
39c91d3624 tests: Fix non-compliant expected output to match actual behaviour. 2015-08-30 12:46:08 +01:00
Damien George
000730ecaa py/objstr: Simplify error handling for bad conversion specifier. 2015-08-30 12:43:21 +01:00
Damien George
c9fa667252 tests: Add tests for non-compliant behaviour.
These tests are intended to improve coverage and provide a record of
behaviour that's either not implemented or non-compliant to CPython.
2015-08-30 12:32:26 +01:00
Damien George
c2ec2ad8fb tests: Add test where __getitem__ raises IndexError to stop iteration. 2015-08-30 11:49:59 +01:00
Tom Soulanille
6433f71e8f py/objgetitemiter: Make it_iternext() recognize IndexError. 2015-08-30 11:49:49 +01:00
Paul Sokolovsky
a3fe307400 tests: Consolidate all feature check snippets under feature_check/. 2015-08-30 11:36:42 +03:00
Paul Sokolovsky
1a1b48e51a tests: Add feature_check dir to collect capability detection scripts.
Which are currently intermixed with real scripts and spread around various
dirs.
2015-08-30 11:11:18 +03:00
Paul Sokolovsky
e8ad47a6ca tools: Upgrade to upip 0.5.7.
Just dependent micropython-lib modules update for upip, no new
functionality.
2015-08-30 11:04:38 +03:00
Damien George
b648e98ad0 py/objstr: Fix error reporting for unexpected end of modulo format str. 2015-08-29 23:13:51 +01:00
Damien George
7ef75f9f75 py/objstr: Fix error type for badly formatted format specifier.
Was KeyError, should be ValueError.
2015-08-29 23:13:51 +01:00
Damien George
51b9a0d0c4 py/objstr: Make string formatting 8-bit clean. 2015-08-29 23:13:51 +01:00
Damien George
1d350b8ac6 tests: Add a few tests for bool, bytearray, float to improve coverage. 2015-08-29 23:13:28 +01:00
Paul Sokolovsky
a488c266c3 tests: Add byteorder query script. 2015-08-30 01:04:04 +03:00
Bob Clough
86e6ad76cb stmhal: Add support for STM32F411 Discovery Board (STM32F411E-DISCO). 2015-08-29 22:50:58 +01:00
Paul Sokolovsky
58d9b10d70 tests: Split byteorder-dependent tests to *_endian.py's. 2015-08-30 00:38:00 +03:00
Paul Sokolovsky
0a8b5d160b run-tests: Allow to skip byteorder-dependent tests.
If byteorder of MicroPython under test and host CPython differ.
2015-08-30 00:37:53 +03:00
Paul Sokolovsky
18c22faf4d py: Treat -m32 flag as part of CC, LD, etc.
Indeed, this flag efectively selects architecture target, and must
consistently apply to all compiles and links, including 3rd-party
libraries, unlike CFLAGS, which have MicroPython-specific setting.
2015-08-29 21:18:10 +03:00
Paul Sokolovsky
5cb524673e tests/ffi_float: Split tgammaf() testcase to a separate test.
Some libc's may implement tgammaf as a header macro using tgamma(), so
don't assume it'll be in the library.
2015-08-29 17:24:29 +03:00
Bill Owens
a66a99bfd8 esp8266: Added wifi_mode() to read and set WiFi operating mode. 2015-08-29 16:58:51 +03:00
Paul Sokolovsky
a160b70ced tests: Add test on set/frozenset equality. 2015-08-28 22:42:01 +03:00
Paul Sokolovsky
8b3b2d04a8 objset: frozensets are hashable. 2015-08-28 22:31:52 +03:00
Damien George
936e25b164 tests: For unix ffi float test, add libm.so.6 to library search list.
Latest Arch Linux doesn't have libm.so as a proper shared object and so
we need to load libm.so.6.
2015-08-25 18:14:53 +01:00
Paul Sokolovsky
5ab0a4a671 README: Add hint about "micropython --help".
Also, hint about possibility to adjust heap size.
2015-08-22 23:56:28 +03:00
Paul Sokolovsky
aa65e1edb3 unix: Bump default heap size to 1MB (2MB on 64-bit systems). 2015-08-22 23:54:25 +03:00
Damien George
d007cb8903 tests: Add more tests to improve coverage, mostly testing exceptions. 2015-08-21 12:02:09 +01:00
Damien George
d292a81e95 tests: Make io test cleanup after itself by removing 'testfile'. 2015-08-21 08:45:52 +01:00
Paul Sokolovsky
22ff397fb1 py: Add MICROPY_PY_BUILTINS_FILTER, disable for minimal ports.
Saves 320 bytes on x86.
2015-08-20 01:05:11 +03:00
Damien George
7f70b60f4d py: Remove unused compile scope flags, and irrelevant flag compute code. 2015-08-17 22:39:03 +01:00
Paul Sokolovsky
2a6660ba59 extmod/modmachine: Avoid conflicts with system PAGE_SIZE define, if any. 2015-08-18 00:31:31 +03:00
tobbad
1abb449dfb stmhal: Fixed some typos in stm32f411_af.csv. 2015-08-17 16:51:19 +01:00
Damien George
65dc960e3b unix-cpy: Remove unix-cpy. It's no longer needed.
unix-cpy was originally written to get semantic equivalent with CPython
without writing functional tests.  When writing the initial
implementation of uPy it was a long way between lexer and functional
tests, so the half-way test was to make sure that the bytecode was
correct.  The idea was that if the uPy bytecode matched CPython 1-1 then
uPy would be proper Python if the bytecodes acted correctly.  And having
matching bytecode meant that it was less likely to miss some deep
subtlety in the Python semantics that would require an architectural
change later on.

But that is all history and it no longer makes sense to retain the
ability to output CPython bytecode, because:

1. It outputs CPython 3.3 compatible bytecode.  CPython's bytecode
changes from version to version, and seems to have changed quite a bit
in 3.5.  There's no point in changing the bytecode output to match
CPython anymore.

2. uPy and CPy do different optimisations to the bytecode which makes it
harder to match.

3. The bytecode tests are not run.  They were never part of Travis and
are not run locally anymore.

4. The EMIT_CPYTHON option needs a lot of extra source code which adds
heaps of noise, especially in compile.c.

5. Now that there is an extensive test suite (which tests functionality)
there is no need to match the bytecode.  Some very subtle behaviour is
tested with the test suite and passing these tests is a much better
way to stay Python-language compliant, rather than trying to match
CPy bytecode.
2015-08-17 12:51:26 +01:00
Daniel Campora
0e978349a5 cc3200: Correct smoke test expected result. 2015-08-16 20:18:16 +02:00
Daniel Campora
e9fa7625f4 cc3200: Correct WLAN constructor argument checking. 2015-08-16 20:18:13 +02:00
Daniel Campora
c0c07fb1b6 cc3200: Don't clear the WDT special bit in the bootloader. 2015-08-16 20:18:11 +02:00
Daniel Campora
aa8e8acb7d cc3200: Change HeartBeat period from 5 to 4 seconds. 2015-08-16 20:18:09 +02:00
Daniel Campora
f837d166e5 cc3200: Fix typo in modpyb. 2015-08-16 20:18:07 +02:00
Daniel Campora
9249242119 cc3200: Remove unneeded loops in the FreeRTOS hooks. 2015-08-16 20:18:05 +02:00
Daniel Campora
641a3d39e1 cc3200: Make sure to update sleep objects when registered. 2015-08-16 20:18:02 +02:00
Daniel Campora
6ff2d54347 cc3200: Small renaming in wdt functions for the sake of consistency. 2015-08-16 20:18:00 +02:00
Daniel Campora
11d21081b4 cc3200: Rework SD API. Increase heap to avoid malloc failures. 2015-08-16 20:17:58 +02:00
Daniel Campora
34c290b678 cc3200: Rename SPI nss param to cs.
The nss param in the pyboard has a different meaning that doesn't
apply to the WiPy.
2015-08-16 20:17:55 +02:00
Daniel Campora
ea5061e409 cc3200: Improve callback API.
Rename "wakes" param to "wake_from" and make "value" an object
instead of an integer.
2015-08-16 20:17:52 +02:00
Daniel Campora
4c5bfe2d10 cc3200: Server side SSL socket requires both certfile and keyfile. 2015-08-16 20:17:49 +02:00
Dave Hylands
c6f1d47dcb stmhal: Enable I & D caches for M7 2015-08-15 10:58:24 -07:00
stijn
3179d23cee windows: Make unistd.h more posix compatible
- add SEEK_XXX definitions, this fixes missing definition in py/stream.c
- move R_OK from realpath.c and add W_OK/F_OK defintions
- move STDXXX_FILENO definitions from mpconfigport for consistency
2015-08-14 12:04:23 +02:00
blmorris
bdd78c31b6 py: Add stream_tell method, and use for unix and stmhal file tell. 2015-08-13 22:56:32 +01:00
Damien George
c39093d801 py: In native ARM emitter, load r7 with table earlier in func prelude.
r7 may be needed to set up code state, so it must be loaded before the
set-up function is called.
2015-08-12 23:31:19 +01:00
Damien George
94ef8879cd py/makeversionhdr.py: Use returncode attr to be Python2.7 compat. 2015-08-12 23:28:16 +01:00
Damien George
b7d59060e2 tools: Make gen-changelog.sh print more lines from the tag annotation. 2015-08-11 13:50:40 +01:00
579 changed files with 15061 additions and 24335 deletions

7
.gitmodules vendored Normal file
View File

@@ -0,0 +1,7 @@
[submodule "lib/axtls"]
path = lib/axtls
url = https://github.com/pfalcon/axtls
branch = micropython
[submodule "lib/libffi"]
path = lib/libffi
url = https://github.com/atgreen/libffi

View File

@@ -15,8 +15,8 @@ before_script:
script:
- make -C minimal test
- make -C unix deplibs CC=gcc-4.7
- make -C unix CC=gcc-4.7
- make -C unix-cpy CC=gcc-4.7
- make -C bare-arm
- make -C qemu-arm test
- make -C stmhal

View File

@@ -1,4 +1,4 @@
The Micro Python project was proudly and successfully crowdfunded
The MicroPython project was proudly and successfully crowdfunded
via a Kickstarter campaign which ended on 13th December 2013. The
project was supported by 1923 very generous backers, who pledged
for a total of 2320 pyboards.

View File

@@ -41,12 +41,12 @@ Names:
- Use CAPS_WITH_UNDERSCORE for enums and macros.
- When defining a type use underscore_case and put '_t' after it.
Integer types: Micro Python runs on 16, 32, and 64 bit machines, so it's
Integer types: MicroPython runs on 16, 32, and 64 bit machines, so it's
important to use the correctly-sized (and signed) integer types. The
general guidelines are:
- For most cases use mp_int_t for signed and mp_uint_t for unsigned
integer values. These are guaranteed to be machine-word sized and
therefore big enough to hold the value from a Micro Python small-int
therefore big enough to hold the value from a MicroPython small-int
object.
- Use size_t for things that count bytes / sizes of objects.
- You can use int/uint, but remember that they may be 16-bits wide.

View File

@@ -8,19 +8,19 @@
[istats-issue-img]: http://issuestats.com/github/micropython/micropython/badge/issue
[istats-issue-repo]: http://issuestats.com/github/micropython/micropython
The Micro Python project
========================
The MicroPython project
=======================
<p align="center">
<img src="https://raw.githubusercontent.com/micropython/micropython/master/logo/upython-with-micro.jpg" alt="MicroPython Logo"/>
</p>
This is the Micro Python project, which aims to put an implementation
This is the MicroPython project, which aims to put an implementation
of Python 3.x on microcontrollers and small embedded systems.
WARNING: this project is in beta stage and is subject to changes of the
code-base, including project-wide name changes and API changes.
Micro Python implements the entire Python 3.4 syntax (including exceptions,
MicroPython implements the entire Python 3.4 syntax (including exceptions,
"with", "yield from", etc.). The following core datatypes are provided:
str (including basic Unicode support), bytes, bytearray, tuple, list, dict,
set, frozenset, array.array, collections.namedtuple, classes and instances.
@@ -33,21 +33,20 @@ Python board, the officially supported reference electronic circuit board.
Major components in this repository:
- py/ -- the core Python implementation, including compiler, runtime, and
core library.
- unix/ -- a version of Micro Python that runs on Unix.
- stmhal/ -- a version of Micro Python that runs on the Micro Python board
- unix/ -- a version of MicroPython that runs on Unix.
- stmhal/ -- a version of MicroPython that runs on the MicroPython board
with an STM32F405RG (using ST's Cube HAL drivers).
- minimal/ -- a minimal Micro Python port. Start with this if you want
to port Micro Python to another microcontroller.
- minimal/ -- a minimal MicroPython port. Start with this if you want
to port MicroPython to another microcontroller.
Additional components:
- bare-arm/ -- a bare minimum version of Micro Python for ARM MCUs. Used
- bare-arm/ -- a bare minimum version of MicroPython for ARM MCUs. Used
mostly to control code size.
- teensy/ -- a version of Micro Python that runs on the Teensy 3.1
- teensy/ -- a version of MicroPython that runs on the Teensy 3.1
(preliminary but functional).
- pic16bit/ -- a version of Micro Python for 16-bit PIC microcontrollers.
- cc3200/ -- a version of Micro Python that runs on the CC3200 from TI.
- pic16bit/ -- a version of MicroPython for 16-bit PIC microcontrollers.
- cc3200/ -- a version of MicroPython that runs on the CC3200 from TI.
- esp8266/ -- an experimental port for ESP8266 WiFi modules.
- unix-cpy/ -- a version of Micro Python that outputs bytecode (for testing).
- tests/ -- test framework and test scripts.
- tools/ -- various tools, including the pyboard.py module.
- examples/ -- a few example Python scripts.
@@ -75,6 +74,12 @@ Then to give it a try:
$ ./micropython
>>> list(5 * x + y for x in range(10) for y in [4, 2, 1])
Use `CTRL-D` (i.e. EOF) to exit the shell.
Learn about command-line options (in particular, how to increase heap size
which may be needed for larger applications):
$ ./micropython --help
Run complete testsuite:
$ make test
@@ -89,9 +94,35 @@ Browse available modules on
Standard library modules come from
[micropython-lib](https://github.com/micropython/micropython-lib) project.
(*) Debian/Ubuntu/Mint derivative Linux distros will require build-essentials,
libffi-dev and pkg-config packages installed. If you have problems with some
dependencies, they can be disabled in unix/mpconfigport.mk .
External dependencies
---------------------
Building Unix version requires some dependencies installed. For
Debian/Ubuntu/Mint derivative Linux distros, install `build-essentials`
(includes toolchain and make), `libffi-dev`, and `pkg-config` packages.
Other dependencies can be built together with MicroPython. Oftentimes,
you need to do this to enable extra features or capabilities. To build
these additional dependencies, first fetch git submodules for them:
$ git submodule update --init
Use this same command to get the latest versions of dependencies, as
they are updated from time to time. After that, in `unix/` dir, execute:
$ make deplibs
This will build all available dependencies (regardless whether they
are used or not). If you intend to build MicroPython with additional
options (like cross-compiling), the same set of options should be passed
to `make deplibs`. To actually enabled use of dependencies, edit
`unix/mpconfigport.mk` file, which has inline descriptions of the options.
For example, to build SSL module (required for `upip` tool described above),
set `MICROPY_PY_USSL` to 1.
In `unix/mpconfigport.mk`, you can also disable some dependencies enabled
by default, like FFI support, which requires libffi development files to
be installed.
The STM version
---------------

View File

@@ -8,7 +8,7 @@ include ../py/py.mk
CROSS_COMPILE = arm-none-eabi-
INC = -I.
INC += -I.
INC += -I..
INC += -I$(BUILD)

View File

@@ -16,8 +16,8 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
qstr source_name = lex->source_name;
mp_parse_node_t pn = mp_parse(lex, input_kind);
mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true);
mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);
mp_obj_t module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, true);
mp_call_function_0(module_fun);
nlr_pop();
} else {

View File

@@ -57,6 +57,9 @@ typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
typedef long mp_off_t;
// dummy print
#define MP_PLAT_PRINT_STRN(str, len) (void)0
// extra built in names to add to the global namespace
extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
#define MICROPY_PORT_BUILTINS \

View File

@@ -83,7 +83,7 @@
#define configUSE_TICK_HOOK 1
#define configCPU_CLOCK_HZ ( ( unsigned long ) 80000000 )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 64 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 72 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 16384 ) )
#define configMAX_TASK_NAME_LEN ( 8 )
#define configUSE_TRACE_FACILITY 0

View File

@@ -1,6 +1,6 @@
# Build Instructions for the CC3200
Currently the CC3200 port of Micro Python builds under Linux and OSX **but not under Windows**.
Currently the CC3200 port of MicroPython builds under Linux and OSX **but not under Windows**.
The tool chain required for the build can be found at <https://launchpad.net/gcc-arm-embedded>.
@@ -25,7 +25,7 @@ make BTARGET=bootloader BTYPE=release BOARD=LAUNCHXL
```
## Regarding old revisions of the CC3200-LAUNCHXL
First silicon (pre-release) revisions of the CC3200 had issues with the ram blocks, and Micro Python cannot run
First silicon (pre-release) revisions of the CC3200 had issues with the ram blocks, and MicroPython cannot run
there. Make sure to use a **v4.1 (or higer) LAUNCHXL board** when trying this port, otherwise it won't work.
## Flashing the CC3200
@@ -53,8 +53,6 @@ If `WIPY_IP`, `WIPY_USER` or `WIPY_PWD` are omitted the default values (the ones
Once the software is running, you have two options to access the MicroPython REPL:
- Through the UART.
**Connect to PORT 22, baud rate = 115200, parity = none, stop bits = 1**
- Through telnet.
* Connect to the network created by the board (as boots up in AP mode), **ssid = "wipy-wlan", key = "www.wipy.io"**.
* You can also reinitialize the WLAN in station mode and connect to another AP, or in AP mode but with a

View File

@@ -77,23 +77,22 @@ APP_HAL_SRC_C = $(addprefix hal/,\
APP_MISC_SRC_C = $(addprefix misc/,\
antenna.c \
FreeRTOSHooks.c \
pin_named_pins.c \
help.c \
mpcallback.c \
mpirq.c \
mperror.c \
mpexception.c \
mpsystick.c \
)
APP_MODS_SRC_C = $(addprefix mods/,\
modmachine.c \
modnetwork.c \
moduhashlib.c \
modubinascii.c \
modpyb.c \
moduos.c \
modusocket.c \
modussl.c \
modutime.c \
modwipy.c \
modwlan.c \
pybadc.c \
pybpin.c \

View File

@@ -30,18 +30,10 @@
#define MICROPY_HW_BOARD_NAME "LaunchPad"
#define MICROPY_HW_MCU_NAME "CC3200"
#define MICROPY_HW_HAS_SDCARD (0)
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ANTENNA_DIVERSITY (0)
#define MICROPY_STDIO_UART 1
#define MICROPY_STDIO_UART 0
#define MICROPY_STDIO_UART_BAUD 115200
#define MICROPY_STDIO_UART_RX_BUF_SIZE 128
#define MICROPY_STDIO_UART_TX_PIN (pin_GP1)
#define MICROPY_STDIO_UART_RX_PIN (pin_GP2)
#define MICROPY_STDIO_UART_TX_PIN_AF PIN_MODE_3
#define MICROPY_STDIO_UART_RX_PIN_AF PIN_MODE_3
#define MICROPY_SYS_LED_PRCM PRCM_GPIOA1
#define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA2

View File

@@ -30,9 +30,6 @@
#define MICROPY_HW_BOARD_NAME "WiPy"
#define MICROPY_HW_MCU_NAME "CC3200"
#define MICROPY_HW_HAS_SDCARD (1)
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ANTENNA_DIVERSITY (1)
#define MICROPY_SYS_LED_PRCM PRCM_GPIOA3

View File

@@ -1,25 +1,25 @@
Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,ADC
1,GP10,GP10,GP10,I2C_SCL,,GT_PWM06,,,SDCARD_CLK,UART1_TX,,,,,GT_CCP01,,,,
2,GP11,GP11,GP11,I2C_SDA,,GT_PWM07,pXCLK(XVCLK),,SDCARD_CMD,UART1_RX,,,,,GT_CCP02,McAFSX,,,
3,GP12,GP12,GP12,,,McACLK,pVS(VSYNC),I2C_SCL,,UART0_TX,,,,,GT_CCP03,,,,
4,GP13,GP13,GP13,,,,pHS(HSYNC),I2C_SDA,,UART0_RX,,,,,GT_CCP04,,,,
5,GP14,GP14,GP14,,,,pDATA8(CAM_D4),2C_SCL,,GSPI_CLK,,,,,GT_CCP05,,,,
6,GP15,GP15,GP15,,,,pDATA9(CAM_D5),I2C_SDA,,GSPI_MISO,,,,,,GT_CCP06,,,
7,GP16,GP16,GP16,,,,pDATA10(CAM_D6),UART1_TX,,GSPI_MOSI,,,,,,GT_CCP07,,,
8,GP17,GP17,GP17,,,,pDATA11(CAM_D7),UART1_RX,,GSPI_CS,,,,,,,,,
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,,,
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,,,,,,,,,,,,,,,,
11,FLASH_SPI_CLK,FLASH_SPI_CLK,FLASH_SPI_CLK,,,,,,,,,,,,,,,,
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,,,,,GT_CCP04,,McAFSX,,,,,,,,,
16,GP23,TDI,GP23,TDI,UART1_TX,,,,,,,2C_SCL,,,,,,,
17,GP24,TDO,GP24,TDO,UART1_RX,,GT_CCP06,PWM0,McAFSX,,,I2C_SDA,,,,,,,
15,GP22,GP22,GP22,,,,,TIM2_CC0,,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,,,,,,,
18,GP28,GP28,GP28,,,,,,,,,,,,,,,,
19,TCK,TCK,,TCK,,,,,,,GT_PWM03,,,,,,,,
19,TCK,TCK,,TCK,,,,,,,TIM1_PWM2,,,,,,,,
20,GP29,TMS,GP29,TMS,,,,,,,,,,,,,,,
21,GP25,SOP2,GP25,,McAFSX,,,,,,,GT_PWM02,,,,,,,
21,GP25,SOP2,GP25,,I2S0_FS,,,,,,,TIM1_PWM0,,,,,,,
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,,,,,,,,,,,,,,,,
@@ -43,24 +43,24 @@ Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF1
42,DCDC_PA_OUT,DCDC_PA_O UT,DCDC_PA_O UT,,,,,,,,,,,,,,,,
43,DCDC_DIG_SW,DCDC_DIG_ SW,DCDC_DIG_ SW,,,,,,,,,,,,,,,,
44,VIN_DCDC_DIG,VIN_DCDC_ DIG,VIN_DCDC_ DIG,,,,,,,,,,,,,,,,
45,GP31,DCDC_ANA2_SW_P,GP31,,UART1_RX,,,,McAXR0,GSPI_CLK,,UART0_RX,,,McAFSX,,,,
45,GP31,DCDC_ANA2_SW_P,GP31,,UART1_RX,,,,I2S0_DAT0,SPI0_CLK,,UART0_RX,,,I2S0_FS,,,,
46,DCDC_ANA2_SW_N,DCDC_ANA2_SW_N,DCDC_ANA2_SW_N,,,,,,,,,,,,,,,,
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,McAXR0,,McAXR1,GT_CCP00,,GSPI_CS,UART1_RTS,,UART0_CTS,,,,
50,GP0,GP0,GP0,,,UART0_RTS,I2S0_DAT0,,I2S0_DAT1,TIM0_CC0,,SPI0_CS0,UART1_RTS,,UART0_CTS,,,,
51,RTC_XTAL_P,RTC_XTAL_P,RTC_XTAL_P,,,,,,,,,,,,,,,,
52,RTC_XTAL_N,RTC_XTAL_N,GP32,,McACLK,,McAXR0,,UART0_RTS,,GSPI_MOSI,,,,,,,,
53,GP30,GP30,GP30,,McACLK,McAFSX,GT_CCP05,,,GSPI_MISO,,UART0_TX,,,,,,,
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,,,,,,,
54,VIN_IO2,VIN_IO2,VIN_IO2,,,,,,,,,,,,,,,,
55,GP1,GP1,GP1,,,GSPI_MISO,pCLK (PIXCLK),,UART1_TX,GT_CCP01,,,,,,,,,
55,GP1,GP1,GP1,,,UART0_TX,pCLK (PIXCLK),,UART1_TX,TIM0_CC1,,,,,,,,,
56,VDD_DIG2,VDD_DIG2,VDD_DIG2,,,,,,,,,,,,,,,,
57,GP2,GP2,GP2,,,UART0_RX,,,UART1_RX,GT_CCP02,,,,,,,,,ADC_CH0
58,GP3,GP3,GP3,,,,pDATA7(CAM_D3),,UART1_TX,,,,,,,,,,ADC_CH1
59,GP4,GP4,GP4,,,,pDATA6(CAM_D2),,UART1_RX,,,,,,,,,,ADC_CH2
60,GP5,GP5,GP5,,,,pDATA5(CAM_D1),,McAXR1,GT_CCP05,,,,,,,,,ADC_CH3
61,GP6,GP6,GP6,,,UART1_CTS,pDATA4(CAM_D0),UART0_RTS,UART0_CTS,GT_CCP06,,,,,,,,,
62,GP7,GP7,GP7,,,UART1_RTS,,,,,,,UART0_RTS,UART0_TX,,McACLKX,,,
63,GP8,GP8,GP8,,,,,,SDCARD_IRQ,McAFSX,,,,,GT_CCP06,,,,
64,GP9,GP9,GP9,,,GT_PWM05,,,SDCARD_DATA,McAXR0,,,,,GT_CCP00,,,,
57,GP2,GP2,GP2,,,UART0_RX,,,UART1_RX,TIM1_CC0,,,,,,,,,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,,,,,,,,,
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,,,,
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 I2C_SCL I2C0_SCL GT_PWM06 TIM3_PWM0 SDCARD_CLK SD0_CLK UART1_TX GT_CCP01 TIM0_CC1
3 2 GP11 GP11 GP11 I2C_SDA I2C0_SDA GT_PWM07 TIM3_PWM1 pXCLK(XVCLK) SDCARD_CMD SD0_CMD UART1_RX GT_CCP02 TIM1_CC0 McAFSX I2S0_FS
4 3 GP12 GP12 GP12 McACLK I2S0_CLK pVS(VSYNC) I2C_SCL I2C0_SCL UART0_TX GT_CCP03 TIM1_CC1
5 4 GP13 GP13 GP13 pHS(HSYNC) I2C_SDA I2C0_SDA UART0_RX GT_CCP04 TIM2_CC0
6 5 GP14 GP14 GP14 pDATA8(CAM_D4) 2C_SCL I2C0_SCL GSPI_CLK SPI0_CLK GT_CCP05 TIM2_CC1
7 6 GP15 GP15 GP15 pDATA9(CAM_D5) I2C_SDA I2C0_SDA GSPI_MISO SPI0_MISO SD0_DAT0 GT_CCP06 TIM3_CC0
8 7 GP16 GP16 GP16 pDATA10(CAM_D6) UART1_TX GSPI_MOSI SPI0_MOSI SD0_CLK GT_CCP07 TIM3_CC1
9 8 GP17 GP17 GP17 pDATA11(CAM_D7) UART1_RX GSPI_CS SPI0_CS0 SD0_CMD
10 9 VDD_DIG1 VDD_DIG1 VDD_DIG1
11 10 VIN_IO1 VIN_IO1 VIN_IO1
12 11 FLASH_SPI_CLK FLASH_SPI_CLK FLASH_SPI_CLK
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 GT_CCP04 TIM2_CC0 McAFSX I2S0_FS
17 16 GP23 TDI GP23 TDI UART1_TX 2C_SCL I2C0_SCL
18 17 GP24 TDO GP24 TDO UART1_RX GT_CCP06 TIM3_CC0 PWM0 TIM0_PWM0 McAFSX I2S0_FS I2C_SDA I2C0_SDA
19 18 GP28 GP28 GP28
20 19 TCK TCK TCK GT_PWM03 TIM1_PWM2
21 20 GP29 TMS GP29 TMS
22 21 GP25 SOP2 GP25 McAFSX I2S0_FS GT_PWM02 TIM1_PWM0
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
43 42 DCDC_PA_OUT DCDC_PA_O UT DCDC_PA_O UT
44 43 DCDC_DIG_SW DCDC_DIG_ SW DCDC_DIG_ SW
45 44 VIN_DCDC_DIG VIN_DCDC_ DIG VIN_DCDC_ DIG
46 45 GP31 DCDC_ANA2_SW_P GP31 UART1_RX McAXR0 I2S0_DAT0 GSPI_CLK SPI0_CLK UART0_RX McAFSX I2S0_FS
47 46 DCDC_ANA2_SW_N DCDC_ANA2_SW_N DCDC_ANA2_SW_N
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 McAXR0 I2S0_DAT0 McAXR1 I2S0_DAT1 GT_CCP00 TIM0_CC0 GSPI_CS 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 McACLK I2S0_CLK McAXR0 I2S0_DAT0 UART0_RTS GSPI_MOSI SPI0_MOSI
54 53 GP30 GP30 GP30 McACLK I2S0_CLK McAFSX I2S0_FS GT_CCP05 TIM2_CC1 GSPI_MISO SPI0_MISO UART0_TX
55 54 VIN_IO2 VIN_IO2 VIN_IO2
56 55 GP1 GP1 GP1 GSPI_MISO UART0_TX pCLK (PIXCLK) UART1_TX GT_CCP01 TIM0_CC1
57 56 VDD_DIG2 VDD_DIG2 VDD_DIG2
58 57 GP2 GP2 GP2 UART0_RX UART1_RX GT_CCP02 TIM1_CC0 ADC_CH0 ADC0_CH0
59 58 GP3 GP3 GP3 pDATA7(CAM_D3) UART1_TX ADC_CH1 ADC0_CH1
60 59 GP4 GP4 GP4 pDATA6(CAM_D2) UART1_RX ADC_CH2 ADC0_CH2
61 60 GP5 GP5 GP5 pDATA5(CAM_D1) McAXR1 I2S0_DAT1 GT_CCP05 TIM2_CC1 ADC_CH3 ADC0_CH3
62 61 GP6 GP6 GP6 UART1_CTS pDATA4(CAM_D0) UART0_RTS UART0_CTS GT_CCP06 TIM3_CC0
63 62 GP7 GP7 GP7 UART1_RTS UART0_RTS UART0_TX McACLKX I2S0_CLK
64 63 GP8 GP8 GP8 SDCARD_IRQ SD0_IRQ McAFSX I2S0_FS GT_CCP06 TIM3_CC0
65 64 GP9 GP9 GP9 GT_PWM05 TIM2_PWM1 SDCARD_DATA SD0_DAT0 McAXR0 I2S0_DAT0 GT_CCP00 TIM0_CC0
66 65 GND_TAB GND_TAB GND_TAB

View File

@@ -39,16 +39,31 @@
#include "pybpin.h"
#define PIN(p_pin_name, p_port, p_bit, p_pin_num) \
#define AF(af_name, af_idx, af_fn, af_unit, af_type) \
{ \
.name = MP_QSTR_ ## af_name, \
.idx = (af_idx), \
.fn = PIN_FN_ ## af_fn, \
.unit = (af_unit), \
.type = PIN_TYPE_ ## af_fn ## _ ## af_type, \
}
#define PIN(p_pin_name, p_port, p_bit, p_pin_num, p_af_list, p_num_afs) \
{ \
{ &pin_type }, \
.name = MP_QSTR_ ## p_pin_name, \
.port = PORT_A ## p_port, \
.type = PIN_TYPE_STD, \
.bit = (p_bit), \
.pin_num = (p_pin_num), \
.af = PIN_MODE_0, \
.strength = PIN_STRENGTH_4MA, \
.mode = GPIO_DIR_MODE_IN, \
.isused = false, \
.name = MP_QSTR_ ## p_pin_name, \
.port = PORT_A ## p_port, \
.af_list = (p_af_list), \
.pull = PIN_TYPE_STD, \
.bit = (p_bit), \
.pin_num = (p_pin_num), \
.af = PIN_MODE_0, \
.strength = PIN_STRENGTH_4MA, \
.mode = GPIO_DIR_MODE_IN, \
.num_afs = (p_num_afs), \
.value = 0, \
.used = false, \
.irq_trigger = 0, \
.irq_flags = 0, \
}

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python
"""Generates the pins files for the CC3200."""
"""Generates the pins file for the CC3200."""
from __future__ import print_function
@@ -8,6 +8,15 @@ import sys
import csv
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'),
'SD': ('CLK', 'CMD', 'DAT0'),
'ADC': ('CH0', 'CH1', 'CH2', 'CH3')
}
def parse_port_pin(name_str):
"""Parses a string and returns a (port, gpio_bit) tuple."""
if len(name_str) < 3:
@@ -21,7 +30,21 @@ def parse_port_pin(name_str):
return (port, gpio_bit)
class Pin(object):
class AF:
"""Holds the description of an alternate function"""
def __init__(self, name, idx, fn, unit, type):
self.name = name
self.idx = idx
if self.idx > 15:
self.idx = -1
self.fn = fn
self.unit = unit
self.type = type
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):
self.name = name
@@ -29,45 +52,48 @@ class Pin(object):
self.gpio_bit = gpio_bit
self.pin_num = pin_num
self.board_pin = False
self.afs = []
def cpu_pin_name(self):
return self.name
def is_board_pin(self):
return self.board_pin
def set_is_board_pin(self):
self.board_pin = True
def add_af(self, af):
self.afs.append(af)
def print(self):
print('pin_obj_t pin_{:6s} = PIN({:6s}, {:1d}, {:3d}, {:2d});'.format(
self.name, self.name, self.port, self.gpio_bit, self.pin_num))
print('// {}'.format(self.name))
if len(self.afs):
print('const pin_af_t pin_{}_af[] = {{'.format(self.name))
for af in self.afs:
af.print()
print('};')
print('pin_obj_t pin_{:4s} = PIN({:6s}, {:1d}, {:3d}, {:2d}, pin_{}_af, {});\n'.format(
self.name, self.name, self.port, self.gpio_bit, self.pin_num, self.name, len(self.afs)))
else:
print('pin_obj_t pin_{:4s} = PIN({:6s}, {:1d}, {:3d}, {:2d}, NULL, 0);\n'.format(
self.name, self.name, self.port, self.gpio_bit, self.pin_num))
def print_header(self, hdr_file):
hdr_file.write('extern pin_obj_t pin_{:s};\n'.format(self.name))
class Pins(object):
class Pins:
def __init__(self):
self.cpu_pins = [] # list of pin objects
self.board_pins = [] # list of pin objects
def find_pin(self, port, gpio_bit):
for pin in self.cpu_pins:
for pin in self.board_pins:
if pin.port == port and pin.gpio_bit == gpio_bit:
return pin
def find_pin_by_num(self, pin_num):
for pin in self.cpu_pins:
for pin in self.board_pins:
if pin.pin_num == pin_num:
return pin
def find_pin_by_name(self, name):
for pin in self.cpu_pins:
for pin in self.board_pins:
if pin.name == name:
return pin
def parse_af_file(self, filename, pin_col, pinname_col):
def parse_af_file(self, filename, pin_col, pinname_col, af_start_col):
with open(filename, 'r') as csvfile:
rows = csv.reader(csvfile)
for row in rows:
@@ -76,11 +102,21 @@ class Pins(object):
except:
continue
if not row[pin_col].isdigit():
raise ValueError("Invalid pin number: {:s} in row {:s}".format(row[pin_col]), row)
raise ValueError("Invalid pin number {:s} in row {:s}".format(row[pin_col]), row)
# Pin numbers must start from 0 when used with the TI API
pin_num = int(row[pin_col]) - 1;
pin = Pin(row[pinname_col], port_num, gpio_bit, pin_num)
self.cpu_pins.append(pin)
self.board_pins.append(pin)
af_idx = 0
for af in row[af_start_col:]:
af_splitted = af.split('_')
fn_name = af_splitted[0].rstrip('0123456789')
if fn_name in SUPPORTED_AFS:
type_name = af_splitted[1]
if type_name in SUPPORTED_AFS[fn_name]:
unit_idx = af_splitted[0][-1]
pin.add_af(AF(af, af_idx, fn_name, int(unit_idx), type_name))
af_idx += 1
def parse_board_file(self, filename, cpu_pin_col):
with open(filename, 'r') as csvfile:
@@ -92,37 +128,44 @@ class Pins(object):
else:
pin = self.find_pin_by_name(row[cpu_pin_col])
if pin:
pin.set_is_board_pin()
pin.board_pin = True
def print_named(self, label, pins):
print('')
print('STATIC const mp_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{'.format(label))
for pin in pins:
if pin.is_board_pin():
print(' {{ MP_OBJ_NEW_QSTR(MP_QSTR_{:6s}), (mp_obj_t)&pin_{:6s} }},'.format(pin.cpu_pin_name(), pin.cpu_pin_name()))
if pin.board_pin:
print(' {{ MP_OBJ_NEW_QSTR(MP_QSTR_{:6s}), (mp_obj_t)&pin_{:6s} }},'.format(pin.name, pin.name))
print('};')
print('MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);'.format(label, label));
def print(self):
for pin in self.cpu_pins:
if pin.is_board_pin():
for pin in self.board_pins:
if pin.board_pin:
pin.print()
self.print_named('cpu', self.cpu_pins)
self.print_named('board', self.board_pins)
print('')
def print_header(self, hdr_filename):
with open(hdr_filename, 'wt') as hdr_file:
for pin in self.cpu_pins:
if pin.is_board_pin():
for pin in self.board_pins:
if pin.board_pin:
pin.print_header(hdr_file)
def print_qstr(self, qstr_filename):
with open(qstr_filename, 'wt') as qstr_file:
qstr_set = set([])
for pin in self.cpu_pins:
if pin.is_board_pin():
qstr_set |= set([pin.cpu_pin_name()])
for qstr in sorted(qstr_set):
pin_qstr_set = set([])
af_qstr_set = set([])
for pin in self.board_pins:
if pin.board_pin:
pin_qstr_set |= set([pin.name])
for af in pin.afs:
af_qstr_set |= set([af.name])
print('// Board pins', file=qstr_file)
for qstr in sorted(pin_qstr_set):
print('Q({})'.format(qstr), file=qstr_file)
print('\n// Pin AFs', file=qstr_file)
for qstr in sorted(af_qstr_set):
print('Q({})'.format(qstr), file=qstr_file)
@@ -169,12 +212,12 @@ def main():
print('//')
if args.af_filename:
print('// --af {:s}'.format(args.af_filename))
pins.parse_af_file(args.af_filename, 0, 1)
pins.parse_af_file(args.af_filename, 0, 1, 3)
if args.board_filename:
print('// --board {:s}'.format(args.board_filename))
pins.parse_board_file(args.board_filename, 1)
pins.parse_board_file(args.board_filename, 1)
if args.prefix_filename:
print('// --prefix {:s}'.format(args.prefix_filename))
print('')

View File

@@ -67,7 +67,7 @@
#define BOOTMGR_WAIT_SAFE_MODE_0_MS 500
#define BOOTMGR_WAIT_SAFE_MODE_1_MS 3000
#define BOOTMGR_WAIT_SAFE_MODE_1_BLINK_MS 250
#define BOOTMGR_WAIT_SAFE_MODE_1_BLINK_MS 500
#define BOOTMGR_WAIT_SAFE_MODE_2_MS 3000
#define BOOTMGR_WAIT_SAFE_MODE_2_BLINK_MS 250
@@ -158,8 +158,8 @@ static void bootmgr_board_init(void) {
PRCMCC3200MCUInit();
// clear all the special bits, since we can't trust their content after reset
// except for the WDT reset one!!
PRCMClearSpecialBit(PRCM_SAFE_BOOT_BIT);
PRCMClearSpecialBit(PRCM_WDT_RESET_BIT);
PRCMClearSpecialBit(PRCM_FIRST_BOOT_BIT);
// check the reset after clearing the special bits

View File

@@ -10,12 +10,11 @@
#include <stdbool.h>
#include "py/mpconfig.h"
#include "py/runtime.h"
#include "py/obj.h"
#include "diskio.h" /* FatFs lower layer API */
#include "diskio.h" /* FatFs lower layer API */
#include "sflash_diskio.h" /* Serial flash disk IO API */
#if MICROPY_HW_HAS_SDCARD
#include "sd_diskio.h" /* SDCARD disk IO API */
#endif
#include "sd_diskio.h" /* SDCARD disk IO API */
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
@@ -23,10 +22,9 @@
#include "prcm.h"
#include "pybrtc.h"
#include "timeutils.h"
/* Definitions of physical drive number for each drive */
#define SFLASH 0 /* Map SFLASH drive to drive number 0 */
#define SDCARD 1 /* Map SD card to drive number 1 */
#include "ff.h"
#include "pybsd.h"
#include "moduos.h"
/*-----------------------------------------------------------------------*/
@@ -37,21 +35,20 @@ DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
switch (pdrv) {
case SFLASH :
return sflash_disk_status();
#if MICROPY_HW_HAS_SDCARD
case SDCARD :
return sd_disk_status();
#endif
default:
break;
}
return STA_NODISK;
if (pdrv == FLASH) {
return sflash_disk_status();
} else {
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_volume(pdrv))) {
if (mount_obj->writeblocks[0] == MP_OBJ_NULL) {
return STA_PROTECT;
}
return 0;
}
}
return STA_NODISK;
}
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
@@ -60,29 +57,22 @@ DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
DSTATUS stat = 0;
switch (pdrv) {
case SFLASH :
if (RES_OK != sflash_disk_init()) {
stat = STA_NOINIT;
}
return stat;
#if MICROPY_HW_HAS_SDCARD
case SDCARD :
if (RES_OK != sd_disk_init()) {
stat = STA_NOINIT;
if (pdrv == FLASH) {
if (RES_OK != sflash_disk_init()) {
return STA_NOINIT;
}
return stat;
#endif
default:
break;
}
return STA_NOINIT;
} else {
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_volume(pdrv))) {
if (mount_obj->writeblocks[0] == MP_OBJ_NULL) {
return STA_PROTECT;
}
return 0;
}
}
return STA_NODISK;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
@@ -94,22 +84,25 @@ DRESULT disk_read (
UINT count /* Number of sectors to read */
)
{
switch (pdrv) {
case SFLASH :
return sflash_disk_read(buff, sector, count);
#if MICROPY_HW_HAS_SDCARD
case SDCARD :
return sd_disk_read(buff, sector, count);
#endif
default:
break;
}
return RES_PARERR;
if (pdrv == FLASH) {
return sflash_disk_read(buff, sector, count);
} else {
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_volume(pdrv))) {
// optimization for the built-in sd card device
if (mount_obj->device == (mp_obj_t)&pybsd_obj) {
return sd_disk_read(buff, sector, count);
}
mount_obj->readblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
mount_obj->readblocks[3] = mp_obj_new_bytearray_by_ref(count * 512, buff);
return mp_obj_get_int(mp_call_method_n_kw(2, 0, mount_obj->readblocks));
}
// nothing mounted
return RES_ERROR;
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
@@ -122,18 +115,23 @@ DRESULT disk_write (
UINT count /* Number of sectors to write */
)
{
switch (pdrv) {
case SFLASH :
return sflash_disk_write(buff, sector, count);
#if MICROPY_HW_HAS_SDCARD
case SDCARD :
return sd_disk_write(buff, sector, count);
#endif
default:
break;
}
return RES_PARERR;
if (pdrv == FLASH) {
return sflash_disk_write(buff, sector, count);
} else {
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_volume(pdrv))) {
// optimization for the built-in sd card device
if (mount_obj->device == (mp_obj_t)&pybsd_obj) {
return sd_disk_write(buff, sector, count);
}
mount_obj->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(sector);
mount_obj->writeblocks[3] = mp_obj_new_bytearray_by_ref(count * 512, (void *)buff);
return mp_obj_get_int(mp_call_method_n_kw(2, 0, mount_obj->writeblocks));
}
// nothing mounted
return RES_ERROR;
}
return RES_PARERR;
}
#endif
@@ -149,41 +147,47 @@ DRESULT disk_ioctl (
void *buff /* Buffer to send/receive control data */
)
{
switch (pdrv) {
case SFLASH:
if (pdrv == FLASH) {
switch (cmd) {
case CTRL_SYNC:
return sflash_disk_flush();
case GET_SECTOR_COUNT:
*((DWORD*)buff) = SFLASH_SECTOR_COUNT;
return RES_OK;
break;
case GET_SECTOR_SIZE:
*((WORD*)buff) = SFLASH_SECTOR_SIZE;
*((DWORD*)buff) = SFLASH_SECTOR_SIZE;
return RES_OK;
break;
case GET_BLOCK_SIZE:
*((DWORD*)buff) = 1; // high-level sector erase size in units of the block size
return RES_OK;
}
break;
#if MICROPY_HW_HAS_SDCARD
case SDCARD:
switch (cmd) {
case CTRL_SYNC:
return RES_OK;
case GET_SECTOR_COUNT:
*(WORD*)buff = sd_disk_info.ulNofBlock;
break;
case GET_SECTOR_SIZE :
*(WORD*)buff = SD_SECTOR_SIZE;
break;
case GET_BLOCK_SIZE:
*((DWORD*)buff) = 1; // high-level sector erase size in units of the block size
return RES_OK;
} else {
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_volume(pdrv))) {
switch (cmd) {
case CTRL_SYNC:
if (mount_obj->sync[0] != MP_OBJ_NULL) {
mp_call_method_n_kw(0, 0, mount_obj->sync);
}
return RES_OK;
case GET_SECTOR_COUNT:
// optimization for the built-in sd card device
if (mount_obj->device == (mp_obj_t)&pybsd_obj) {
*((DWORD*)buff) = sd_disk_info.ulNofBlock * (sd_disk_info.ulBlockSize / 512);
} else {
*((DWORD*)buff) = mp_obj_get_int(mp_call_method_n_kw(0, 0, mount_obj->count));
}
return RES_OK;
case GET_SECTOR_SIZE:
*((DWORD*)buff) = SD_SECTOR_SIZE; // Sector size is fixed to 512 bytes, as with SD cards
return RES_OK;
case GET_BLOCK_SIZE:
*((DWORD*)buff) = 1; // high-level sector erase size in units of the block size
return RES_OK;
}
}
break;
#endif
// nothing mounted
return RES_ERROR;
}
return RES_PARERR;
}
@@ -195,7 +199,7 @@ DWORD get_fattime (
)
{
timeutils_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(pybrtc_get_seconds(), &tm);
timeutils_seconds_since_2000_to_struct_time(pyb_rtc_get_seconds(), &tm);
return ((tm.tm_year - 1980) << 25) | ((tm.tm_mon) << 21) |
((tm.tm_mday) << 16) | ((tm.tm_hour) << 11) |

View File

@@ -38,6 +38,8 @@ DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
/* Definitions of physical drive number for each drive */
#define FLASH 0 /* Map FLASH drive to drive number 0 */
/* Disk Status Bits (DSTATUS) */

View File

@@ -279,8 +279,6 @@ DSTATUS sd_disk_init (void) {
sd_disk_info.bStatus = 0;
}
}
// Set card rd/wr block len
MAP_SDHostBlockSizeSet(SDHOST_BASE, SD_SECTOR_SIZE);
}
return sd_disk_info.bStatus;
@@ -302,28 +300,6 @@ void sd_disk_deinit (void) {
sd_disk_info.usRCA = 0;
}
//*****************************************************************************
//
//! Gets the disk status.
//!
//! This function gets the current status of the drive.
//!
//! \return Returns the current status of the specified drive
//
//*****************************************************************************
DSTATUS sd_disk_status (void) {
return sd_disk_info.bStatus;
}
//*****************************************************************************
//
//! Returns wether the sd card is ready to be accessed or not
//
//*****************************************************************************
bool sd_disk_ready (void) {
return (!sd_disk_info.bStatus);
}
//*****************************************************************************
//
//! Reads sector(s) from the disk drive.
@@ -376,6 +352,7 @@ DRESULT sd_disk_read (BYTE* pBuffer, DWORD ulSectorNumber, UINT SectorCount) {
pBuffer += 4;
}
CardSendCmd(CMD_STOP_TRANS, 0);
while (!(MAP_SDHostIntStatus(SDHOST_BASE) & SDHOST_INT_TC));
Res = RES_OK;
}
}
@@ -395,61 +372,62 @@ DRESULT sd_disk_read (BYTE* pBuffer, DWORD ulSectorNumber, UINT SectorCount) {
//
//*****************************************************************************
DRESULT sd_disk_write (const BYTE* pBuffer, DWORD ulSectorNumber, UINT SectorCount) {
DRESULT Res = RES_ERROR;
unsigned long ulSize;
DRESULT Res = RES_ERROR;
unsigned long ulSize;
if (SectorCount > 0) {
// Return if disk not initialized
if (sd_disk_info.bStatus & STA_NOINIT) {
return RES_NOTRDY;
}
if (SectorCount > 0) {
// Return if disk not initialized
if (sd_disk_info.bStatus & STA_NOINIT) {
return RES_NOTRDY;
}
// SDSC uses linear address, SDHC uses block address
if (sd_disk_info.ulCapClass == CARD_CAP_CLASS_SDSC) {
ulSectorNumber = ulSectorNumber * SD_SECTOR_SIZE;
}
// SDSC uses linear address, SDHC uses block address
if (sd_disk_info.ulCapClass == CARD_CAP_CLASS_SDSC) {
ulSectorNumber = ulSectorNumber * SD_SECTOR_SIZE;
}
// Set the block count
MAP_SDHostBlockCountSet(SDHOST_BASE, SectorCount);
// Set the block count
MAP_SDHostBlockCountSet(SDHOST_BASE, SectorCount);
// Compute the number of words
ulSize = (SD_SECTOR_SIZE * SectorCount) / 4;
// Compute the number of words
ulSize = (SD_SECTOR_SIZE * SectorCount) / 4;
// Check if 1 block or multi block transfer
if (SectorCount == 1) {
// Send single block write command
if (CardSendCmd(CMD_WRITE_SINGLE_BLK, ulSectorNumber) == 0) {
// Write the data
while (ulSize--) {
MAP_SDHostDataWrite (SDHOST_BASE, (*(unsigned long *)pBuffer));
pBuffer += 4;
}
// Wait for data transfer complete
while (!(MAP_SDHostIntStatus(SDHOST_BASE) & SDHOST_INT_TC));
Res = RES_OK;
}
}
else {
// Set the card write block count
if (sd_disk_info.ucCardType == CARD_TYPE_SDCARD) {
CardSendCmd(CMD_APP_CMD,sd_disk_info.usRCA << 16);
CardSendCmd(CMD_SET_BLK_CNT, SectorCount);
}
// Check if 1 block or multi block transfer
if (SectorCount == 1) {
// Send single block write command
if (CardSendCmd(CMD_WRITE_SINGLE_BLK, ulSectorNumber) == 0) {
// Write the data
while (ulSize--) {
MAP_SDHostDataWrite (SDHOST_BASE, (*(unsigned long *)pBuffer));
pBuffer += 4;
}
// Wait for data transfer complete
while (!(MAP_SDHostIntStatus(SDHOST_BASE) & SDHOST_INT_TC));
Res = RES_OK;
}
}
else {
// Set the card write block count
if (sd_disk_info.ucCardType == CARD_TYPE_SDCARD) {
CardSendCmd(CMD_APP_CMD,sd_disk_info.usRCA << 16);
CardSendCmd(CMD_SET_BLK_CNT, SectorCount);
}
// Send multi block write command
if (CardSendCmd(CMD_WRITE_MULTI_BLK, ulSectorNumber) == 0) {
// Write the data buffer
while (ulSize--) {
MAP_SDHostDataWrite(SDHOST_BASE, (*(unsigned long *)pBuffer));
pBuffer += 4;
}
// Wait for transfer complete
while (!(MAP_SDHostIntStatus(SDHOST_BASE) & SDHOST_INT_TC));
CardSendCmd(CMD_STOP_TRANS, 0);
Res = RES_OK;
}
}
}
// Send multi block write command
if (CardSendCmd(CMD_WRITE_MULTI_BLK, ulSectorNumber) == 0) {
// Write the data buffer
while (ulSize--) {
MAP_SDHostDataWrite(SDHOST_BASE, (*(unsigned long *)pBuffer));
pBuffer += 4;
}
// Wait for transfer complete
while (!(MAP_SDHostIntStatus(SDHOST_BASE) & SDHOST_INT_TC));
CardSendCmd(CMD_STOP_TRANS, 0);
while (!(MAP_SDHostIntStatus(SDHOST_BASE) & SDHOST_INT_TC));
Res = RES_OK;
}
}
}
return Res;
return Res;
}

View File

@@ -21,8 +21,6 @@ extern DiskInfo_t sd_disk_info;
DSTATUS sd_disk_init (void);
void sd_disk_deinit (void);
DSTATUS sd_disk_status (void);
bool sd_disk_ready (void);
DRESULT sd_disk_read (BYTE* pBuffer, DWORD ulSectorNumber, UINT bSectorCount);
DRESULT sd_disk_write (const BYTE* pBuffer, DWORD ulSectorNumber, UINT bSectorCount);

View File

@@ -54,8 +54,20 @@ DRESULT sflash_disk_init (void) {
// Allocate space for the block cache
ASSERT ((sflash_block_cache = mem_Malloc(SFLASH_BLOCK_SIZE)) != NULL);
sflash_init_done = true;
sflash_prblock = UINT32_MAX;
sflash_cache_is_dirty = false;
// Proceed to format the memory if not done yet
// In order too speed up booting, check the last block, if exists, then
// it means that the file system has been already created
print_block_name (SFLASH_BLOCK_COUNT - 1);
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
if (!sl_FsGetInfo(sflash_block_name, 0, &FsFileInfo)) {
sl_LockObjUnlock (&wlan_LockObj);
return RES_OK;
}
sl_LockObjUnlock (&wlan_LockObj);
// Proceed to format the memory
for (int i = 0; i < SFLASH_BLOCK_COUNT; i++) {
print_block_name (i);
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
@@ -74,15 +86,9 @@ DRESULT sflash_disk_init (void) {
sl_LockObjUnlock (&wlan_LockObj);
return RES_ERROR;
}
} else {
// file system exists, break here to speed up booting
sl_LockObjUnlock (&wlan_LockObj);
break;
}
sl_LockObjUnlock (&wlan_LockObj);
}
sflash_prblock = UINT32_MAX;
sflash_cache_is_dirty = false;
}
return RES_OK;
}

View File

@@ -26,11 +26,11 @@
#include <string.h>
#include "py/mpconfig.h"
#include "py/misc.h"
#include "py/mpstate.h"
#include "ff.h"
#include "ffconf.h"
#include "diskio.h"
#include "moduos.h"
#if _FS_RPATH
extern BYTE ff_CurrVol;
@@ -65,31 +65,29 @@ int ff_get_ldnumber (const TCHAR **path) {
}
if (check_path(path, "/flash", 6)) {
return 0;
return FLASH;
}
#if MICROPY_HW_HAS_SDCARD
else if (check_path(path, "/sd", 3)) {
return 1;
}
#endif
else {
return -1;
for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
if (check_path(path, mount_obj->path, mount_obj->pathlen)) {
return mount_obj->vol;
}
}
}
return -1;
}
void ff_get_volname(BYTE vol, TCHAR **dest) {
#if MICROPY_HW_HAS_SDCARD
if (vol == 0)
#endif
{
if (vol == FLASH) {
memcpy(*dest, "/flash", 6);
*dest += 6;
} else {
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_volume(vol))) {
memcpy(*dest, mount_obj->path, mount_obj->pathlen);
*dest += mount_obj->pathlen;
}
}
#if MICROPY_HW_HAS_SDCARD
else
{
memcpy(*dest, "/sd", 3);
*dest += 3;
}
#endif
}

View File

@@ -28,7 +28,7 @@
#include <ctype.h>
#include "std.h"
#include "py/mpconfig.h"
#include "py/mpstate.h"
#include MICROPY_HAL_H
#include "py/obj.h"
#include "inc/hw_types.h"
@@ -47,10 +47,9 @@
#include "ff.h"
#include "fifo.h"
#include "socketfifo.h"
#include "diskio.h"
#include "sd_diskio.h"
#include "updater.h"
#include "timeutils.h"
#include "moduos.h"
/******************************************************************************
DEFINE PRIVATE CONSTANTS
@@ -94,16 +93,12 @@ typedef enum {
E_FTP_STE_SUB_DISCONNECTED = 0,
E_FTP_STE_SUB_LISTEN_FOR_DATA,
E_FTP_STE_SUB_DATA_CONNECTED
} ftp_data_substate_t;
typedef union {
ftp_data_substate_t data;
} ftp_substate_t;
typedef struct {
bool uservalid : 1;
bool passvalid : 1;
}ftp_loggin_t;
} ftp_loggin_t;
typedef enum {
E_FTP_NOTHING_OPEN = 0,
@@ -129,8 +124,9 @@ typedef struct {
int16_t c_sd;
int16_t d_sd;
int16_t dtimeout;
ftp_state_t state;
ftp_substate_t substate;
uint16_t volcount;
uint8_t state;
uint8_t substate;
uint8_t txRetries;
uint8_t logginRetries;
ftp_loggin_t loggin;
@@ -138,6 +134,7 @@ typedef struct {
bool closechild;
bool enabled;
bool special_file;
bool listroot;
} ftp_data_t;
typedef struct {
@@ -193,7 +190,7 @@ static const ftp_month_t ftp_month[] = { { "Jan" }, { "Feb" }, { "Mar" }, { "Apr
{ "May" }, { "Jun" }, { "Jul" }, { "Ago" },
{ "Sep" }, { "Oct" }, { "Nov" }, { "Dec" } };
static SocketFifoElement_t *ftp_fifoelements;
static SocketFifoElement_t ftp_fifoelements[FTP_SOCKETFIFO_ELEMENTS_MAX];
static FIFO_t ftp_socketfifo;
/******************************************************************************
@@ -218,7 +215,7 @@ static int ftp_print_eplf_drive (char *dest, uint32_t destsize, char *name);
static bool ftp_open_file (const char *path, int mode);
static ftp_result_t ftp_read_file (char *filebuf, uint32_t desiredsize, uint32_t *actualsize);
static ftp_result_t ftp_write_file (char *filebuf, uint32_t size);
static ftp_result_t ftp_open_dir_for_listing (const char *path, char *list, uint32_t maxlistsize, uint32_t *listsize);
static ftp_result_t ftp_open_dir_for_listing (const char *path);
static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *listsize);
static void ftp_open_child (char *pwd, char *dir);
static void ftp_close_child (char *pwd);
@@ -233,7 +230,6 @@ void ftp_init (void) {
ASSERT ((ftp_path = mem_Malloc(FTP_MAX_PARAM_SIZE)) != NULL);
ASSERT ((ftp_scratch_buffer = mem_Malloc(FTP_MAX_PARAM_SIZE)) != NULL);
ASSERT ((ftp_cmd_buffer = mem_Malloc(FTP_MAX_PARAM_SIZE + FTP_CMD_SIZE_MAX)) != NULL);
ASSERT ((ftp_fifoelements = mem_Malloc(FTP_SOCKETFIFO_ELEMENTS_MAX * sizeof(SocketFifoElement_t))) != NULL);
SOCKETFIFO_Init (&ftp_socketfifo, (void *)ftp_fifoelements, FTP_SOCKETFIFO_ELEMENTS_MAX);
ftp_data.c_sd = -1;
ftp_data.d_sd = -1;
@@ -241,8 +237,9 @@ void ftp_init (void) {
ftp_data.ld_sd = -1;
ftp_data.e_open = E_FTP_NOTHING_OPEN;
ftp_data.state = E_FTP_STE_DISABLED;
ftp_data.substate.data = E_FTP_STE_SUB_DISCONNECTED;
ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED;
ftp_data.special_file = false;
ftp_data.volcount = 0;
}
void ftp_run (void) {
@@ -256,7 +253,7 @@ void ftp_run (void) {
}
break;
case E_FTP_STE_READY:
if (ftp_data.c_sd < 0 && ftp_data.substate.data == E_FTP_STE_SUB_DISCONNECTED) {
if (ftp_data.c_sd < 0 && ftp_data.substate == E_FTP_STE_SUB_DISCONNECTED) {
if (E_FTP_RESULT_OK == ftp_wait_for_connection(ftp_data.lc_sd, &ftp_data.c_sd)) {
ftp_data.txRetries = 0;
ftp_data.logginRetries = 0;
@@ -269,7 +266,7 @@ void ftp_run (void) {
}
}
if (SOCKETFIFO_IsEmpty()) {
if (ftp_data.c_sd > 0 && ftp_data.substate.data != E_FTP_STE_SUB_LISTEN_FOR_DATA) {
if (ftp_data.c_sd > 0 && ftp_data.substate != E_FTP_STE_SUB_LISTEN_FOR_DATA) {
ftp_process_cmd();
if (ftp_data.state != E_FTP_STE_READY) {
break;
@@ -286,8 +283,7 @@ void ftp_run (void) {
ftp_list_dir((char *)ftp_data.dBuffer, FTP_BUFFER_SIZE, &listsize);
if (listsize > 0) {
ftp_send_data(listsize);
}
else {
} else {
ftp_send_reply(226, NULL);
ftp_data.state = E_FTP_STE_END_TRANSFER;
}
@@ -358,19 +354,19 @@ void ftp_run (void) {
break;
}
switch (ftp_data.substate.data) {
switch (ftp_data.substate) {
case E_FTP_STE_SUB_DISCONNECTED:
break;
case E_FTP_STE_SUB_LISTEN_FOR_DATA:
if (E_FTP_RESULT_OK == ftp_wait_for_connection(ftp_data.ld_sd, &ftp_data.d_sd)) {
ftp_data.dtimeout = 0;
ftp_data.substate.data = E_FTP_STE_SUB_DATA_CONNECTED;
ftp_data.substate = E_FTP_STE_SUB_DATA_CONNECTED;
}
else if (ftp_data.dtimeout++ > FTP_DATA_TIMEOUT_MS / FTP_CYCLE_TIME_MS) {
ftp_data.dtimeout = 0;
// close the listening socket
servers_close_socket(&ftp_data.ld_sd);
ftp_data.substate.data = E_FTP_STE_SUB_DISCONNECTED;
ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED;
}
break;
case E_FTP_STE_SUB_DATA_CONNECTED:
@@ -379,7 +375,7 @@ void ftp_run (void) {
servers_close_socket(&ftp_data.ld_sd);
servers_close_socket(&ftp_data.d_sd);
ftp_close_filesystem_on_error ();
ftp_data.substate.data = E_FTP_STE_SUB_DISCONNECTED;
ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED;
}
break;
default:
@@ -391,7 +387,7 @@ void ftp_run (void) {
// check the state of the data sockets
if (ftp_data.d_sd < 0 && (ftp_data.state > E_FTP_STE_READY)) {
ftp_data.substate.data = E_FTP_STE_SUB_DISCONNECTED;
ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED;
ftp_data.state = E_FTP_STE_READY;
}
}
@@ -412,7 +408,8 @@ void ftp_reset (void) {
servers_close_socket(&ftp_data.ld_sd);
ftp_close_cmd_data();
ftp_data.state = E_FTP_STE_START;
ftp_data.substate.data = E_FTP_STE_SUB_DISCONNECTED;
ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED;
ftp_data.volcount = 0;
SOCKETFIFO_Flush();
}
@@ -556,7 +553,7 @@ static void ftp_send_from_fifo (void) {
servers_close_socket(&ftp_data.ld_sd);
// this one is the command socket
servers_close_socket(fifoelement.sd);
ftp_data.substate.data = E_FTP_STE_SUB_DISCONNECTED;
ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED;
}
ftp_close_filesystem_on_error();
}
@@ -606,7 +603,6 @@ static void ftp_process_cmd (void) {
_i32 len;
char *bufptr = (char *)ftp_cmd_buffer;
ftp_result_t result;
uint32_t listsize;
FRESULT fres;
FILINFO fno;
#if _USE_LFN
@@ -708,7 +704,7 @@ static void ftp_process_cmd (void) {
{
// some servers (e.g. google chrome) send PASV several times very quickly
servers_close_socket(&ftp_data.d_sd);
ftp_data.substate.data = E_FTP_STE_SUB_DISCONNECTED;
ftp_data.substate = E_FTP_STE_SUB_DISCONNECTED;
bool socketcreated = true;
if (ftp_data.ld_sd < 0) {
socketcreated = ftp_create_listening_socket(&ftp_data.ld_sd, FTP_PASIVE_DATA_PORT, FTP_DATA_CLIENTS_MAX);
@@ -720,7 +716,7 @@ static void ftp_process_cmd (void) {
wlan_get_ip(&ip);
snprintf((char *)ftp_data.dBuffer, FTP_BUFFER_SIZE, "(%u,%u,%u,%u,%u,%u)",
pip[3], pip[2], pip[1], pip[0], (FTP_PASIVE_DATA_PORT >> 8), (FTP_PASIVE_DATA_PORT & 0xFF));
ftp_data.substate.data = E_FTP_STE_SUB_LISTEN_FOR_DATA;
ftp_data.substate = E_FTP_STE_SUB_LISTEN_FOR_DATA;
ftp_send_reply(227, (char *)ftp_data.dBuffer);
}
else {
@@ -729,13 +725,7 @@ static void ftp_process_cmd (void) {
}
break;
case E_FTP_CMD_LIST:
if ((result = ftp_open_dir_for_listing(ftp_path, (char *)ftp_data.dBuffer, FTP_BUFFER_SIZE, &listsize)) == E_FTP_RESULT_OK) {
ftp_data.state = E_FTP_STE_END_TRANSFER;
ftp_send_reply(150, NULL);
ftp_send_data(listsize);
ftp_send_reply(226, NULL);
}
else if (result == E_FTP_RESULT_CONTINUE) {
if (ftp_open_dir_for_listing(ftp_path) == E_FTP_RESULT_CONTINUE) {
ftp_data.state = E_FTP_STE_CONTINUE_LISTING;
ftp_send_reply(150, NULL);
}
@@ -905,7 +895,7 @@ static int ftp_print_eplf_item (char *dest, uint32_t destsize, FILINFO *fno) {
(fno->ftime >> 11) & 0x1f,
(fno->ftime >> 5) & 0x3f,
2 * (fno->ftime & 0x1f));
tseconds = pybrtc_get_seconds();
tseconds = pyb_rtc_get_seconds();
if (FTP_UNIX_SECONDS_180_DAYS < tseconds - fseconds) {
return snprintf(dest, destsize, "%srw-rw-r-- 1 root root %9u %s %2u %5u %s\r\n",
type, (_u32)fno->fsize, ftp_month[mindex].month, day,
@@ -933,7 +923,7 @@ static int ftp_print_eplf_drive (char *dest, uint32_t destsize, char *name) {
timeutils_seconds_since_2000_to_struct_time((FTP_UNIX_TIME_20150101 - FTP_UNIX_TIME_20000101), &tm);
tseconds = pybrtc_get_seconds();
tseconds = pyb_rtc_get_seconds();
if (FTP_UNIX_SECONDS_180_DAYS < tseconds - (FTP_UNIX_TIME_20150101 - FTP_UNIX_TIME_20000101)) {
return snprintf(dest, destsize, "%srw-rw-r-- 1 root root %9u %s %2u %5u %s\r\n",
type, 0, ftp_month[(tm.tm_mon - 1)].month, tm.tm_mday, tm.tm_year, name);
@@ -981,32 +971,25 @@ static ftp_result_t ftp_write_file (char *filebuf, uint32_t size) {
return result;
}
static ftp_result_t ftp_open_dir_for_listing (const char *path, char *list, uint32_t maxlistsize, uint32_t *listsize) {
uint next = 0;
// "hack" to list root directory
static ftp_result_t ftp_open_dir_for_listing (const char *path) {
// "hack" to detect the root directory
if (path[0] == '/' && path[1] == '\0') {
next += ftp_print_eplf_drive((list + next), (maxlistsize - next), "flash");
#if MICROPY_HW_HAS_SDCARD
if (sd_disk_ready()) {
next += ftp_print_eplf_drive((list + next), (maxlistsize - next), "sd");
ftp_data.listroot = true;
} else {
FRESULT res;
res = f_opendir(&ftp_data.dp, path); /* Open the directory */
if (res != FR_OK) {
return E_FTP_RESULT_FAILED;
}
#endif
*listsize = next;
return E_FTP_RESULT_OK;
ftp_data.e_open = E_FTP_DIR_OPEN;
ftp_data.listroot = false;
}
FRESULT res;
res = f_opendir(&ftp_data.dp, path); /* Open the directory */
if (res != FR_OK) {
return E_FTP_RESULT_FAILED;
}
ftp_data.e_open = E_FTP_DIR_OPEN;
return E_FTP_RESULT_CONTINUE;
}
static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *listsize) {
uint next = 0;
uint count = 0;
uint listcount = 0;
FRESULT res;
ftp_result_t result = E_FTP_RESULT_CONTINUE;
FILINFO fno;
@@ -1015,22 +998,40 @@ static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *li
fno.lfsize = _MAX_LFN;
// read up to 2 directory items
while (count < 2) {
while (listcount < 2) {
#else
// read up to 4 directory items
while (count < 4) {
while (listcount < 4) {
#endif
res = f_readdir(&ftp_data.dp, &fno); /* Read a directory item */
if (res != FR_OK || fno.fname[0] == 0) {
result = E_FTP_RESULT_OK;
break; /* Break on error or end of dp */
}
if (fno.fname[0] == '.' && fno.fname[1] == 0) continue; /* Ignore . entry */
if (fno.fname[0] == '.' && fno.fname[1] == '.' && fno.fname[2] == 0) continue; /* Ignore .. entry */
if (ftp_data.listroot) {
// root directory "hack"
if (0 == ftp_data.volcount) {
next += ftp_print_eplf_drive((list + next), (maxlistsize - next), "flash");
} else if (ftp_data.volcount <= MP_STATE_PORT(mount_obj_list).len) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[(ftp_data.volcount - 1)]));
next += ftp_print_eplf_drive((list + next), (maxlistsize - next), (char *)&mount_obj->path[1]);
} else {
if (!next) {
// no volume found this time, we are done
ftp_data.volcount = 0;
}
break;
}
ftp_data.volcount++;
} else {
// a "normal" directory
res = f_readdir(&ftp_data.dp, &fno); /* Read a directory item */
if (res != FR_OK || fno.fname[0] == 0) {
result = E_FTP_RESULT_OK;
break; /* Break on error or end of dp */
}
if (fno.fname[0] == '.' && fno.fname[1] == 0) continue; /* Ignore . entry */
if (fno.fname[0] == '.' && fno.fname[1] == '.' && fno.fname[2] == 0) continue; /* Ignore .. entry */
// add the entry to the list
next += ftp_print_eplf_item((list + next), (maxlistsize - next), &fno);
count++;
// add the entry to the list
next += ftp_print_eplf_item((list + next), (maxlistsize - next), &fno);
}
listcount++;
}
if (result == E_FTP_RESULT_OK) {
ftp_close_files();
@@ -1045,8 +1046,7 @@ static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *li
static void ftp_open_child (char *pwd, char *dir) {
if (dir[0] == '/') {
strcpy (pwd, dir);
}
else {
} else {
if (strlen(pwd) > 1) {
strcat (pwd, "/");
}
@@ -1066,8 +1066,7 @@ static void ftp_close_child (char *pwd) {
}
if (len == 0) {
strcpy (pwd, "/");
}
else {
} else {
pwd[len] = '\0';
}
}
@@ -1080,8 +1079,7 @@ static void ftp_return_to_previous_path (char *pwd, char *dir) {
else {
if (newlen == 0) {
strcpy (pwd, "/");
}
else {
} else {
pwd[newlen] = '\0';
}
}

View File

@@ -87,8 +87,9 @@ bool updater_check_path (void *path) {
if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_READ, NULL, &fhandle)) {
ASSERT (sizeof(sBootInfo_t) == sl_FsRead(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t)));
sl_FsClose(fhandle, 0, 0, 0);
// if we still have an image pending for verification, keep overwriting it
if ((sBootInfo.Status == IMG_STATUS_CHECK && sBootInfo.ActiveImg == IMG_ACT_UPDATE2) ||
sBootInfo.ActiveImg == IMG_ACT_UPDATE1) {
(sBootInfo.ActiveImg == IMG_ACT_UPDATE1 && sBootInfo.Status != IMG_STATUS_CHECK)) {
updater_data.path = IMG_UPDATE2;
}
}

View File

@@ -31,12 +31,16 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "py/mpstate.h"
#include MICROPY_HAL_H
#include "py/runtime.h"
#include "py/objstr.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "hw_memmap.h"
#include "py/mpstate.h"
#include MICROPY_HAL_H
#include "rom_map.h"
#include "interrupt.h"
#include "systick.h"
@@ -47,6 +51,7 @@
#include "pybuart.h"
#include "utils.h"
#include "irq.h"
#include "moduos.h"
#ifdef USE_FREERTOS
#include "FreeRTOS.h"
@@ -67,11 +72,6 @@ static void hal_TickInit (void);
******************************************************************************/
static volatile uint32_t HAL_tickCount;
/******************************************************************************
DECLARE PUBLIC DATA
******************************************************************************/
struct _pyb_uart_obj_t *pyb_stdio_uart;
/******************************************************************************
DECLARE IMPORTED DATA
******************************************************************************/
@@ -128,6 +128,10 @@ void HAL_Delay(uint32_t delay) {
}
}
NORETURN void mp_hal_raise(int errno) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, mp_obj_new_int(errno)));
}
void mp_hal_set_interrupt_char (int c) {
mpexception_set_interrupt_char (c);
}
@@ -137,34 +141,57 @@ void mp_hal_stdout_tx_str(const char *str) {
}
void mp_hal_stdout_tx_strn(const char *str, uint32_t len) {
// send stdout to UART
if (pyb_stdio_uart != NULL) {
uart_tx_strn(pyb_stdio_uart, str, len);
if (MP_STATE_PORT(os_term_dup_obj)) {
if (MP_OBJ_IS_TYPE(MP_STATE_PORT(os_term_dup_obj)->stream_o, &pyb_uart_type)) {
uart_tx_strn(MP_STATE_PORT(os_term_dup_obj)->stream_o, str, len);
} else {
MP_STATE_PORT(os_term_dup_obj)->write[2] = mp_obj_new_str_of_type(&mp_type_str, (const byte *)str, len);
mp_call_method_n_kw(1, 0, MP_STATE_PORT(os_term_dup_obj)->write);
}
}
// and also to telnet
if (telnet_is_active()) {
telnet_tx_strn(str, len);
}
telnet_tx_strn(str, len);
}
void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len) {
// send stdout to UART
if (pyb_stdio_uart != NULL) {
uart_tx_strn_cooked(pyb_stdio_uart, str, len);
void mp_hal_stdout_tx_strn_cooked (const char *str, uint32_t len) {
int32_t nslen = 0;
const char *_str = str;
for (int i = 0; i < len; i++) {
if (str[i] == '\n') {
mp_hal_stdout_tx_strn(_str, nslen);
mp_hal_stdout_tx_strn("\r\n", 2);
_str += nslen + 1;
nslen = 0;
} else {
nslen++;
}
}
// and also to telnet
if (telnet_is_active()) {
telnet_tx_strn_cooked(str, len);
if (_str < str + len) {
mp_hal_stdout_tx_strn(_str, nslen);
}
}
int mp_hal_stdin_rx_chr(void) {
for ( ;; ) {
// read telnet first
if (telnet_rx_any()) {
return telnet_rx_char();
}
else if (pyb_stdio_uart != NULL && uart_rx_any(pyb_stdio_uart)) {
return uart_rx_char(pyb_stdio_uart);
} else if (MP_STATE_PORT(os_term_dup_obj)) { // then the stdio_dup
if (MP_OBJ_IS_TYPE(MP_STATE_PORT(os_term_dup_obj)->stream_o, &pyb_uart_type)) {
if (uart_rx_any(MP_STATE_PORT(os_term_dup_obj)->stream_o)) {
return uart_rx_char(MP_STATE_PORT(os_term_dup_obj)->stream_o);
}
} else {
MP_STATE_PORT(os_term_dup_obj)->read[2] = mp_obj_new_int(1);
mp_obj_t data = mp_call_method_n_kw(1, 0, MP_STATE_PORT(os_term_dup_obj)->read);
// data len is > 0
if (mp_obj_is_true(data)) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
return ((int *)(bufinfo.buf))[0];
}
}
}
HAL_Delay(1);
}

View File

@@ -55,11 +55,6 @@
" isb \n"); \
}
/******************************************************************************
DECLARE PUBLIC DATA
******************************************************************************/
extern struct _pyb_uart_obj_t *pyb_stdio_uart;
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
******************************************************************************/
@@ -69,6 +64,7 @@ extern void HAL_SystemDeInit (void);
extern void HAL_IncrementTick(void);
extern uint32_t HAL_GetTick(void);
extern void HAL_Delay(uint32_t delay);
extern NORETURN void mp_hal_raise(int errno);
extern void mp_hal_set_interrupt_char (int c);
int mp_hal_stdin_rx_chr(void);

View File

@@ -112,17 +112,17 @@
// following wrapper can be used to convert the value from cycles to
// millisecond:
//
// CYCLES_U16MS(cycles) ((cycles *1000)/ 1024),
// CYCLES_U16MS(cycles) ((cycles * 1000) / 1024),
//
// Similarly, before setting the value, it must be first converted (from ms to
// cycles).
//
// U16MS_CYCLES(msec) ((msec *1024)/1000)
// U16MS_CYCLES(msec) ((msec * 1024) / 1000)
//
// Note: There is a precision loss of 1 ms with the above scheme.
//
//
#define SCC_U64MSEC_GET() (MAP_PRCMSlowClkCtrGet() >> 5)
#define SCC_U64MSEC_GET() (RTCFastDomainCounterGet() >> 5)
#define SCC_U64MSEC_MATCH_SET(u64Msec) (MAP_PRCMSlowClkCtrMatchSet(u64Msec << 5))
#define SCC_U64MSEC_MATCH_GET() (MAP_PRCMSlowClkCtrMatchGet() >> 5)
@@ -208,6 +208,39 @@ static void RTCU32SecRegWrite(unsigned long u32Msec)
MAP_PRCMHIBRegWrite(RTC_SECS_U32_REG_ADDR, u32Msec);
}
//*****************************************************************************
// Fast function to get the most accurate RTC counter value
//*****************************************************************************
static unsigned long long RTCFastDomainCounterGet (void) {
#define BRK_IF_RTC_CTRS_ALIGN(c2, c1) if (c2 - c1 <= 1) { \
itr++; \
break; \
}
unsigned long long rtc_count1, rtc_count2, rtc_count3;
unsigned int itr;
do {
rtc_count1 = PRCMSlowClkCtrFastGet();
rtc_count2 = PRCMSlowClkCtrFastGet();
rtc_count3 = PRCMSlowClkCtrFastGet();
itr = 0;
BRK_IF_RTC_CTRS_ALIGN(rtc_count2, rtc_count1);
BRK_IF_RTC_CTRS_ALIGN(rtc_count3, rtc_count2);
BRK_IF_RTC_CTRS_ALIGN(rtc_count3, rtc_count1);
// Consistent values in two consecutive reads implies a correct
// value of the counter. Do note, the counter does not give the
// calendar time but a hardware that ticks upwards continuously.
// The 48-bit counter operates at 32,768 HZ.
} while (true);
return (1 == itr) ? rtc_count2 : rtc_count3;
}
//*****************************************************************************
// Macros
//*****************************************************************************
@@ -1245,6 +1278,35 @@ unsigned long long PRCMSlowClkCtrGet(void)
return ullRTCVal;
}
//*****************************************************************************
//
//! Gets the current value of the internal slow clock counter
//!
//! This function is similar to \sa PRCMSlowClkCtrGet() but reads the counter
//! value from a relatively faster interface using an auto-latch mechainsm.
//!
//! \note Due to the nature of implemetation of auto latching, when using this
//! API, the recommendation is to read the value thrice and identify the right
//! value (as 2 out the 3 read values will always be correct and with a max. of
//! 1 LSB change)
//!
//! \return 64-bit current counter vlaue.
//
//*****************************************************************************
unsigned long long PRCMSlowClkCtrFastGet(void)
{
unsigned long long ullRTCVal;
//
// Read as 2 32-bit values
//
ullRTCVal = HWREG(HIB1P2_BASE + HIB1P2_O_HIB_RTC_TIMER_MSW_1P2);
ullRTCVal = ullRTCVal << 32;
ullRTCVal |= HWREG(HIB1P2_BASE + HIB1P2_O_HIB_RTC_TIMER_LSW_1P2);
return ullRTCVal;
}
//*****************************************************************************
//

View File

@@ -247,6 +247,7 @@ extern void PRCMHibernateWakeupSourceDisable(unsigned long ulHIBWakupSrc);
extern void PRCMHibernateIntervalSet(unsigned long long ullTicks);
extern unsigned long long PRCMSlowClkCtrGet(void);
extern unsigned long long PRCMSlowClkCtrFastGet(void);
extern void PRCMSlowClkCtrMatchSet(unsigned long long ullTicks);
extern unsigned long long PRCMSlowClkCtrMatchGet(void);

View File

@@ -70,10 +70,7 @@ void vApplicationMallocFailedHook (void)
__asm volatile ("bkpt #0 \n");
#endif
for ( ; ; )
{
__fatal_error("FreeRTOS malloc failed!");
}
__fatal_error("FreeRTOS malloc failed!");
}
//*****************************************************************************
@@ -92,10 +89,7 @@ void vApplicationStackOverflowHook (OsiTaskHandle *pxTask, signed char *pcTaskNa
__asm volatile ("bkpt #0 \n");
#endif
for ( ; ; )
{
__fatal_error("Stack overflow!");
}
__fatal_error("Stack overflow!");
}
//*****************************************************************************

View File

@@ -30,7 +30,7 @@
#include "py/mpconfig.h"
#include "py/obj.h"
STATIC const char help_text[] = "Welcome to Micro Python!\n"
STATIC const char help_text[] = "Welcome to MicroPython!\n"
"For online help please visit http://micropython.org/help/.\n"
"For further help on a specific object, type help(obj)\n";

View File

@@ -56,10 +56,10 @@
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
#define MPERROR_TOOGLE_MS (40)
#define MPERROR_SIGNAL_ERROR_MS (1000)
#define MPERROR_TOOGLE_MS (50)
#define MPERROR_SIGNAL_ERROR_MS (1200)
#define MPERROR_HEARTBEAT_ON_MS (80)
#define MPERROR_HEARTBEAT_OFF_MS (4920)
#define MPERROR_HEARTBEAT_OFF_MS (3920)
/******************************************************************************
DECLARE PRIVATE DATA
@@ -94,7 +94,7 @@ void mperror_init0 (void) {
MAP_GPIODirModeSet(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, GPIO_DIR_MODE_OUT);
#else
// configure the system led
pin_config ((pin_obj_t *)&MICROPY_SYS_LED_GPIO, PIN_MODE_0, GPIO_DIR_MODE_OUT, PIN_TYPE_STD, PIN_STRENGTH_6MA);
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_heartbeat_switch_off();
@@ -149,17 +149,13 @@ void mperror_heartbeat_switch_off (void) {
void mperror_heartbeat_signal (void) {
if (mperror_heart_beat.do_disable) {
mperror_heart_beat.do_disable = false;
mperror_heartbeat_switch_off();
mperror_heart_beat.enabled = false;
}
else if (mperror_heart_beat.enabled) {
} else if (mperror_heart_beat.enabled) {
if (!mperror_heart_beat.beating) {
if ((mperror_heart_beat.on_time = HAL_GetTick()) - mperror_heart_beat.off_time > MPERROR_HEARTBEAT_OFF_MS) {
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN);
mperror_heart_beat.beating = true;
}
}
else {
} else {
if ((mperror_heart_beat.off_time = HAL_GetTick()) - mperror_heart_beat.on_time > MPERROR_HEARTBEAT_ON_MS) {
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0);
mperror_heart_beat.beating = false;
@@ -199,48 +195,17 @@ void nlr_jump_fail(void *val) {
#endif
}
#ifndef BOOTLOADER
/******************************************************************************/
// Micro Python bindings
/// \classmethod \constructor()
///
/// Return the heart beat object
STATIC mp_obj_t pyb_heartbeat_make_new(mp_obj_t type_in, 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);
// return constant object
return (mp_obj_t)&pyb_heartbeat_obj;
void mperror_enable_heartbeat (bool enable) {
if (enable) {
mperror_heart_beat.enabled = true;
mperror_heart_beat.do_disable = false;
mperror_heartbeat_switch_off();
} else {
mperror_heart_beat.do_disable = true;
mperror_heart_beat.enabled = false;
}
}
/// \function enable()
/// Enables the heartbeat signal
STATIC mp_obj_t pyb_enable_heartbeat(mp_obj_t self) {
mperror_heart_beat.enabled = true;
return mp_const_none;
bool mperror_is_heartbeat_enabled (void) {
return mperror_heart_beat.enabled;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_enable_heartbeat_obj, pyb_enable_heartbeat);
/// \function disable()
/// Disables the heartbeat signal
STATIC mp_obj_t pyb_disable_heartbeat(mp_obj_t self) {
mperror_heart_beat.do_disable = true;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_disable_heartbeat_obj, pyb_disable_heartbeat);
STATIC const mp_map_elem_t pyb_heartbeat_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&pyb_enable_heartbeat_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&pyb_disable_heartbeat_obj },
};
STATIC MP_DEFINE_CONST_DICT(pyb_heartbeat_locals_dict, pyb_heartbeat_locals_dict_table);
const mp_obj_type_t pyb_heartbeat_type = {
{ &mp_type_type },
.name = MP_QSTR_HeartBeat,
.make_new = pyb_heartbeat_make_new,
.locals_dict = (mp_obj_t)&pyb_heartbeat_locals_dict,
};
#endif

View File

@@ -40,5 +40,7 @@ void mperror_deinit_sfe_pin (void);
void mperror_signal_error (void);
void mperror_heartbeat_switch_off (void);
void mperror_heartbeat_signal (void);
void mperror_enable_heartbeat (bool enable);
bool mperror_is_heartbeat_enabled (void);
#endif // MPERROR_H_

View File

@@ -34,46 +34,51 @@
#include "inc/hw_types.h"
#include "interrupt.h"
#include "pybsleep.h"
#include "mpcallback.h"
#include "mpexception.h"
#include "mperror.h"
#include "mpirq.h"
/******************************************************************************
DEFINE PUBLIC DATA
DECLARE PUBLIC DATA
******************************************************************************/
const mp_arg_t mpcallback_init_args[] = {
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
const mp_arg_t mp_irq_init_args[] = {
{ MP_QSTR_trigger, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_priority, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} }, // the lowest priority
{ MP_QSTR_handler, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_priority, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_wakes, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYB_PWR_MODE_ACTIVE} },
{ MP_QSTR_wake, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC uint8_t mp_irq_priorities[] = { INT_PRIORITY_LVL_7, INT_PRIORITY_LVL_6, INT_PRIORITY_LVL_5, INT_PRIORITY_LVL_4,
INT_PRIORITY_LVL_3, INT_PRIORITY_LVL_2, INT_PRIORITY_LVL_1 };
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
void mpcallback_init0 (void) {
void mp_irq_init0 (void) {
// initialize the callback objects list
mp_obj_list_init(&MP_STATE_PORT(mpcallback_obj_list), 0);
mp_obj_list_init(&MP_STATE_PORT(mp_irq_obj_list), 0);
}
mp_obj_t mpcallback_new (mp_obj_t parent, mp_obj_t handler, const mp_cb_methods_t *methods) {
mpcallback_obj_t *self = m_new_obj(mpcallback_obj_t);
self->base.type = &pyb_callback_type;
mp_obj_t mp_irq_new (mp_obj_t parent, mp_obj_t handler, const mp_irq_methods_t *methods) {
mp_irq_obj_t *self = m_new_obj(mp_irq_obj_t);
self->base.type = &mp_irq_type;
self->handler = handler;
self->parent = parent;
self->methods = (mp_cb_methods_t *)methods;
self->methods = (mp_irq_methods_t *)methods;
self->isenabled = true;
// remove any old callback if present
mpcallback_remove(self->parent);
mp_obj_list_append(&MP_STATE_PORT(mpcallback_obj_list), self);
// remove it in case it was already registered
mp_irq_remove(parent);
mp_obj_list_append(&MP_STATE_PORT(mp_irq_obj_list), self);
return self;
}
mpcallback_obj_t *mpcallback_find (mp_obj_t parent) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(mpcallback_obj_list).len; i++) {
mpcallback_obj_t *callback_obj = ((mpcallback_obj_t *)(MP_STATE_PORT(mpcallback_obj_list).items[i]));
mp_irq_obj_t *mp_irq_find (mp_obj_t parent) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(mp_irq_obj_list).len; i++) {
mp_irq_obj_t *callback_obj = ((mp_irq_obj_t *)(MP_STATE_PORT(mp_irq_obj_list).items[i]));
if (callback_obj->parent == parent) {
return callback_obj;
}
@@ -81,50 +86,40 @@ mpcallback_obj_t *mpcallback_find (mp_obj_t parent) {
return NULL;
}
void mpcallback_wake_all (void) {
void mp_irq_wake_all (void) {
// re-enable all active callback objects one by one
for (mp_uint_t i = 0; i < MP_STATE_PORT(mpcallback_obj_list).len; i++) {
mpcallback_obj_t *callback_obj = ((mpcallback_obj_t *)(MP_STATE_PORT(mpcallback_obj_list).items[i]));
for (mp_uint_t i = 0; i < MP_STATE_PORT(mp_irq_obj_list).len; i++) {
mp_irq_obj_t *callback_obj = ((mp_irq_obj_t *)(MP_STATE_PORT(mp_irq_obj_list).items[i]));
if (callback_obj->isenabled) {
callback_obj->methods->enable(callback_obj->parent);
}
}
}
void mpcallback_remove (const mp_obj_t parent) {
mpcallback_obj_t *callback_obj;
if ((callback_obj = mpcallback_find(parent))) {
mp_obj_list_remove(&MP_STATE_PORT(mpcallback_obj_list), callback_obj);
void mp_irq_disable_all (void) {
// re-enable all active callback objects one by one
for (mp_uint_t i = 0; i < MP_STATE_PORT(mp_irq_obj_list).len; i++) {
mp_irq_obj_t *callback_obj = ((mp_irq_obj_t *)(MP_STATE_PORT(mp_irq_obj_list).items[i]));
callback_obj->methods->disable(callback_obj->parent);
}
}
uint mpcallback_translate_priority (uint priority) {
if (priority < 1 || priority > 7) {
void mp_irq_remove (const mp_obj_t parent) {
mp_irq_obj_t *callback_obj;
if ((callback_obj = mp_irq_find(parent))) {
mp_obj_list_remove(&MP_STATE_PORT(mp_irq_obj_list), callback_obj);
}
}
uint mp_irq_translate_priority (uint priority) {
if (priority < 1 || priority > MP_ARRAY_SIZE(mp_irq_priorities)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
switch (priority) {
case 1:
return INT_PRIORITY_LVL_7;
case 2:
return INT_PRIORITY_LVL_6;
case 3:
return INT_PRIORITY_LVL_5;
case 4:
return INT_PRIORITY_LVL_4;
case 5:
return INT_PRIORITY_LVL_3;
case 6:
return INT_PRIORITY_LVL_2;
case 7:
return INT_PRIORITY_LVL_1;
default:
return INT_PRIORITY_LVL_7;
}
return mp_irq_priorities[priority - 1];
}
void mpcallback_handler (mp_obj_t self_in) {
mpcallback_obj_t *self = self_in;
void mp_irq_handler (mp_obj_t self_in) {
mp_irq_obj_t *self = self_in;
if (self && self->handler != mp_const_none) {
// when executing code within a handler we must lock the GC to prevent
// any memory allocations.
@@ -138,11 +133,11 @@ void mpcallback_handler (mp_obj_t self_in) {
// uncaught exception; disable the callback so that it doesn't run again
self->methods->disable (self->parent);
self->handler = mp_const_none;
// signal the error using the heart beat led and print an
// exception message as well
mperror_signal_error();
// signal the error using the heart beat led and
// by printing a message
printf("Uncaught exception in callback handler\n");
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
mperror_signal_error();
}
gc_unlock();
}
@@ -151,59 +146,57 @@ void mpcallback_handler (mp_obj_t self_in) {
/******************************************************************************/
// Micro Python bindings
/// \method init()
/// Initializes the interrupt callback. With no parameters passed, everything will default
/// to the values assigned to mpcallback_init_args[].
STATIC mp_obj_t callback_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mpcallback_obj_t *self = pos_args[0];
STATIC mp_obj_t mp_irq_init (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_irq_obj_t *self = pos_args[0];
// this is a bit of a hack, but it let us reuse the callback_create method from our parent
((mp_obj_t *)pos_args)[0] = self->parent;
self->methods->init (n_args, pos_args, kw_args);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(callback_init_obj, 1, callback_init);
MP_DEFINE_CONST_FUN_OBJ_KW(mp_irq_init_obj, 1, mp_irq_init);
/// \method enable()
/// Enables the interrupt callback
STATIC mp_obj_t callback_enable (mp_obj_t self_in) {
mpcallback_obj_t *self = self_in;
STATIC mp_obj_t mp_irq_enable (mp_obj_t self_in) {
mp_irq_obj_t *self = self_in;
self->methods->enable(self->parent);
self->isenabled = true;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(callback_enable_obj, callback_enable);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_enable_obj, mp_irq_enable);
/// \method disable()
/// Disables the interrupt callback
STATIC mp_obj_t callback_disable (mp_obj_t self_in) {
mpcallback_obj_t *self = self_in;
STATIC mp_obj_t mp_irq_disable (mp_obj_t self_in) {
mp_irq_obj_t *self = self_in;
self->methods->disable(self->parent);
self->isenabled = false;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(callback_disable_obj, callback_disable);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_disable_obj, mp_irq_disable);
/// \method \call()
/// Triggers the interrupt callback
STATIC mp_obj_t callback_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
STATIC mp_obj_t mp_irq_flags (mp_obj_t self_in) {
mp_irq_obj_t *self = self_in;
return mp_obj_new_int(self->methods->flags(self->parent));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_flags_obj, mp_irq_flags);
STATIC mp_obj_t mp_irq_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, 0, false);
mpcallback_handler (self_in);
mp_irq_handler (self_in);
return mp_const_none;
}
STATIC const mp_map_elem_t callback_locals_dict_table[] = {
STATIC const mp_map_elem_t mp_irq_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&callback_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&callback_enable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&callback_disable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&mp_irq_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&mp_irq_enable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&mp_irq_disable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_flags), (mp_obj_t)&mp_irq_flags_obj },
};
STATIC MP_DEFINE_CONST_DICT(callback_locals_dict, callback_locals_dict_table);
STATIC MP_DEFINE_CONST_DICT(mp_irq_locals_dict, mp_irq_locals_dict_table);
const mp_obj_type_t pyb_callback_type = {
const mp_obj_type_t mp_irq_type = {
{ &mp_type_type },
.name = MP_QSTR_callback,
.call = callback_call,
.locals_dict = (mp_obj_t)&callback_locals_dict,
.name = MP_QSTR_irq,
.call = mp_irq_call,
.locals_dict = (mp_obj_t)&mp_irq_locals_dict,
};

View File

@@ -24,50 +24,52 @@
* THE SOFTWARE.
*/
#ifndef MPCALLBACK_H_
#define MPCALLBACK_H_
#ifndef MPIRQ_H_
#define MPIRQ_H_
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
#define mpcallback_INIT_NUM_ARGS 5
#define mp_irq_INIT_NUM_ARGS 4
/******************************************************************************
DEFINE TYPES
******************************************************************************/
typedef void (*mp_cb_method_t) (mp_obj_t self);
typedef mp_obj_t (*mp_cb_init_t) (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
typedef mp_obj_t (*mp_irq_init_t) (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
typedef void (*mp_irq_void_method_t) (mp_obj_t self);
typedef int (*mp_irq_int_method_t) (mp_obj_t self);
typedef struct {
mp_cb_init_t init;
mp_cb_method_t enable;
mp_cb_method_t disable;
} mp_cb_methods_t;
mp_irq_init_t init;
mp_irq_void_method_t enable;
mp_irq_void_method_t disable;
mp_irq_int_method_t flags;
} mp_irq_methods_t;
typedef struct {
mp_obj_base_t base;
mp_obj_t parent;
mp_obj_t handler;
mp_cb_methods_t *methods;
mp_irq_methods_t *methods;
bool isenabled;
} mpcallback_obj_t;
} mp_irq_obj_t;
/******************************************************************************
DECLARE EXPORTED DATA
******************************************************************************/
extern const mp_arg_t mpcallback_init_args[];
extern const mp_obj_type_t pyb_callback_type;
extern const mp_arg_t mp_irq_init_args[];
extern const mp_obj_type_t mp_irq_type;
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
******************************************************************************/
void mpcallback_init0 (void);
mp_obj_t mpcallback_new (mp_obj_t parent, mp_obj_t handler, const mp_cb_methods_t *methods);
mpcallback_obj_t *mpcallback_find (mp_obj_t parent);
void mpcallback_wake_all (void);
void mpcallback_remove (const mp_obj_t parent);
void mpcallback_handler (mp_obj_t self_in);
uint mpcallback_translate_priority (uint priority);
mp_obj_t mpcallback_new (mp_obj_t parent, mp_obj_t handler, const mp_cb_methods_t *methods);
void mp_irq_init0 (void);
mp_obj_t mp_irq_new (mp_obj_t parent, mp_obj_t handler, const mp_irq_methods_t *methods);
mp_irq_obj_t *mp_irq_find (mp_obj_t parent);
void mp_irq_wake_all (void);
void mp_irq_disable_all (void);
void mp_irq_remove (const mp_obj_t parent);
void mp_irq_handler (mp_obj_t self_in);
uint mp_irq_translate_priority (uint priority);
#endif /* MPCALLBACK_H_ */
#endif /* MPIRQ_H_ */

View File

@@ -58,32 +58,14 @@ void sys_tick_wait_at_least(uint32_t start_tick, uint32_t delay_ms) {
// The SysTick timer counts down at HAL_FCPU_HZ, so we can use that knowledge
// to grab a microsecond counter.
//
// We assume that HAL_GetTick returns milliseconds.
uint32_t sys_tick_get_microseconds(void) {
mp_uint_t irq_state = disable_irq();
uint32_t counter = SysTickValueGet();
uint32_t milliseconds = HAL_GetTick();
uint32_t status = (HWREG(NVIC_ST_CTRL));
enable_irq(irq_state);
// It's still possible for the countflag bit to get set if the counter was
// reloaded between reading VAL and reading CTRL. With interrupts disabled
// it definitely takes less than 50 HCLK cycles between reading VAL and
// reading CTRL, so the test (counter > 50) is to cover the case where VAL
// is +ve and very close to zero, and the COUNTFLAG bit is also set.
if ((status & NVIC_ST_CTRL_COUNT) && counter > 50) {
// This means that the HW reloaded VAL between the time we read VAL and the
// time we read CTRL, which implies that there is an interrupt pending
// to increment the tick counter.
milliseconds++;
}
uint32_t load = (HWREG(NVIC_ST_RELOAD));
uint32_t load = SysTickPeriodGet();
counter = load - counter; // Convert from decrementing to incrementing
// ((load + 1) / 1000) is the number of counts per microsecond.
//
// counter / ((load + 1) / 1000) scales from the systick clock to microseconds
// and is the same thing as (counter * 1000) / (load + 1)
return milliseconds * 1000 + (counter * 1000) / (load + 1);
return (milliseconds * 1000) + ((counter * 1000) / load);
}

View File

@@ -1,71 +0,0 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2015 Daniel Campora
*
* 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 "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/obj.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "pybpin.h"
STATIC void pin_named_pins_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pin_named_pins_obj_t *self = self_in;
mp_printf(print, "<Pin.%q>", self->name);
}
const mp_obj_type_t pin_cpu_pins_obj_type = {
{ &mp_type_type },
.name = MP_QSTR_cpu,
.print = pin_named_pins_obj_print,
.locals_dict = (mp_obj_t)&pin_cpu_pins_locals_dict,
};
pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) {
mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)named_pins);
mp_map_elem_t *named_elem = mp_map_lookup(named_map, name, MP_MAP_LOOKUP);
if (named_elem != NULL && named_elem->value != NULL) {
return named_elem->value;
}
return NULL;
}
pin_obj_t *pin_find_pin_by_port_bit (const mp_obj_dict_t *named_pins, uint port, uint bit) {
mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)named_pins);
for (uint i = 0; i < named_map->used; i++) {
if ((((pin_obj_t *)named_map->table[i].value)->port == port) &&
(((pin_obj_t *)named_map->table[i].value)->bit == bit)) {
return named_map->table[i].value;
}
}
return NULL;
}

218
cc3200/mods/modmachine.c Normal file
View File

@@ -0,0 +1,218 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2015 Daniel Campora
*
* 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 "std.h"
#include "py/mpstate.h"
#include "py/runtime.h"
#include MICROPY_HAL_H
#include "irq.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_uart.h"
#include "rom_map.h"
#include "prcm.h"
#include "pyexec.h"
#include "pybuart.h"
#include "pybpin.h"
#include "pybrtc.h"
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
#include "moduos.h"
#include "FreeRTOS.h"
#include "portable.h"
#include "task.h"
#include "mpexception.h"
#include "random.h"
#include "pybadc.h"
#include "pybi2c.h"
#include "pybsd.h"
#include "pybwdt.h"
#include "pybsleep.h"
#include "pybspi.h"
#include "pybtimer.h"
#include "utils.h"
#include "gccollect.h"
#ifdef DEBUG
extern OsiTaskHandle mpTaskHandle;
extern OsiTaskHandle svTaskHandle;
extern OsiTaskHandle xSimpleLinkSpawnTaskHndl;
#endif
/// \module machine - functions related to the SoC
///
/******************************************************************************/
// Micro Python bindings;
STATIC mp_obj_t machine_reset(void) {
// disable wlan
wlan_stop(SL_STOP_TIMEOUT_LONG);
// reset the cpu and it's peripherals
MAP_PRCMMCUReset(true);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
#ifdef DEBUG
STATIC mp_obj_t machine_info(uint n_args, const mp_obj_t *args) {
// FreeRTOS info
{
printf("---------------------------------------------\n");
printf("FreeRTOS\n");
printf("---------------------------------------------\n");
printf("Total heap: %u\n", configTOTAL_HEAP_SIZE);
printf("Free heap: %u\n", xPortGetFreeHeapSize());
printf("MpTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark((TaskHandle_t)mpTaskHandle));
printf("ServersTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark((TaskHandle_t)svTaskHandle));
printf("SlTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark(xSimpleLinkSpawnTaskHndl));
printf("IdleTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark(xTaskGetIdleTaskHandle()));
uint32_t *pstack = (uint32_t *)&_stack;
while (*pstack == 0x55555555) {
pstack++;
}
printf("MAIN min free stack: %u\n", pstack - ((uint32_t *)&_stack));
printf("---------------------------------------------\n");
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj, 0, 1, machine_info);
#endif
STATIC mp_obj_t machine_freq(void) {
mp_obj_t tuple[1] = {
mp_obj_new_int(HAL_FCPU_HZ),
};
return mp_obj_new_tuple(1, tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_freq_obj, machine_freq);
STATIC mp_obj_t machine_unique_id(void) {
uint8_t mac[SL_BSSID_LENGTH];
wlan_get_mac (mac);
return mp_obj_new_bytes(mac, SL_BSSID_LENGTH);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id);
STATIC mp_obj_t machine_main(mp_obj_t main) {
if (MP_OBJ_IS_STR(main)) {
MP_STATE_PORT(machine_config_main) = main;
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(machine_main_obj, machine_main);
STATIC mp_obj_t machine_idle(void) {
__WFI();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
STATIC mp_obj_t machine_sleep (void) {
pyb_sleep_sleep();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_sleep_obj, machine_sleep);
STATIC mp_obj_t machine_deepsleep (void) {
pyb_sleep_deepsleep();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_deepsleep_obj, machine_deepsleep);
STATIC mp_obj_t machine_reset_cause (void) {
return mp_obj_new_int(pyb_sleep_get_reset_cause());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
STATIC mp_obj_t machine_wake_reason (void) {
return mp_obj_new_int(pyb_sleep_get_wake_reason());
}
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_reset), (mp_obj_t)&machine_reset_obj },
#ifdef DEBUG
{ MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&machine_info_obj },
#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&machine_freq_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_unique_id), (mp_obj_t)&machine_unique_id_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_main), (mp_obj_t)&machine_main_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rng), (mp_obj_t)&machine_rng_get_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_idle), (mp_obj_t)&machine_idle_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&machine_sleep_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deepsleep), (mp_obj_t)&machine_deepsleep_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_reset_cause), (mp_obj_t)&machine_reset_cause_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wake_reason), (mp_obj_t)&machine_wake_reason_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable_irq), (mp_obj_t)&pyb_disable_irq_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable_irq), (mp_obj_t)&pyb_enable_irq_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RTC), (mp_obj_t)&pyb_rtc_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pin_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pyb_adc_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_i2c_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&pyb_spi_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Timer), (mp_obj_t)&pyb_timer_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WDT), (mp_obj_t)&pyb_wdt_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SD), (mp_obj_t)&pyb_sd_type },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_IDLE), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_ACTIVE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_LPDS) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_HIBERNATE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_POWER_ON), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HARD_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HARD_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WDT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WDT_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HIB_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOFT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_SOFT_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WLAN_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_WLAN) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PIN_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_GPIO) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RTC_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_RTC) },
};
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,
.globals = (mp_obj_dict_t*)&machine_module_globals,
};

View File

@@ -29,12 +29,28 @@
#include "py/mpstate.h"
#include MICROPY_HAL_H
#include "py/obj.h"
#include "py/nlr.h"
#include "py/runtime.h"
#include "modnetwork.h"
#include "mpexception.h"
#include "serverstask.h"
#include "simplelink.h"
/******************************************************************************
DEFINE TYPES
******************************************************************************/
typedef struct {
mp_obj_base_t base;
} network_server_obj_t;
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC network_server_obj_t network_server_obj;
STATIC const mp_obj_type_t network_server_type;
/// \module network - network configuration
///
/// This module provides network drivers and server configuration.
@@ -43,48 +59,93 @@ void mod_network_init0(void) {
}
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
STATIC mp_obj_t network_server_running(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args > 0) {
// set
if (mp_obj_is_true(args[0])) {
servers_start();
} else {
servers_stop();
}
return mp_const_none;
} else {
// get
return MP_BOOL(servers_are_enabled());
STATIC mp_obj_t network_server_init_helper(mp_obj_t self, const mp_arg_val_t *args) {
const char *user = SERVERS_DEF_USER;
const char *pass = SERVERS_DEF_PASS;
if (args[0].u_obj != MP_OBJ_NULL) {
mp_obj_t *login;
mp_obj_get_array_fixed_n(args[0].u_obj, 2, &login);
user = mp_obj_str_get_str(login[0]);
pass = mp_obj_str_get_str(login[1]);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_server_running_obj, 0, 1, network_server_running);
STATIC mp_obj_t network_server_login(mp_obj_t user, mp_obj_t pass) {
const char *_user = mp_obj_str_get_str(user);
const char *_pass = mp_obj_str_get_str(pass);
if (strlen(user) > SERVERS_USER_PASS_LEN_MAX || strlen(pass) > SERVERS_USER_PASS_LEN_MAX) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
uint32_t timeout = SERVERS_DEF_TIMEOUT_MS / 1000;
if (args[1].u_obj != MP_OBJ_NULL) {
timeout = mp_obj_get_int(args[1].u_obj);
}
servers_set_login ((char *)_user, (char *)_pass);
// configure the new login
servers_set_login ((char *)user, (char *)pass);
// configure the timeout
servers_set_timeout(timeout * 1000);
// start the servers
servers_start();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_server_login_obj, network_server_login);
STATIC const mp_arg_t network_server_args[] = {
{ MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ 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) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
mp_arg_val_t args[MP_ARRAY_SIZE(network_server_args)];
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), network_server_args, args);
// check the server id
if (args[0].u_obj != MP_OBJ_NULL) {
if (mp_obj_get_int(args[0].u_obj) != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
}
// setup the object and initialize it
network_server_obj_t *self = &network_server_obj;
self->base.type = &network_server_type;
network_server_init_helper(self, &args[1]);
return (mp_obj_t)self;
}
STATIC mp_obj_t network_server_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(network_server_args) - 1];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &network_server_args[1], args);
return network_server_init_helper(pos_args[0], args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_server_init_obj, 1, network_server_init);
// timeout value given in seconds
STATIC mp_obj_t network_server_timeout(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args > 0) {
uint32_t _timeout = mp_obj_get_int(args[0]);
if (!servers_set_timeout(_timeout * 1000)) {
// timeout is too low
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
if (n_args > 1) {
uint32_t timeout = mp_obj_get_int(args[1]);
servers_set_timeout(timeout * 1000);
return mp_const_none;
} else {
// get
return mp_obj_new_int(servers_get_timeout() / 1000);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_server_timeout_obj, 0, 1, network_server_timeout);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_server_timeout_obj, 1, 2, network_server_timeout);
STATIC mp_obj_t network_server_running(mp_obj_t self_in) {
// get
return mp_obj_new_bool(servers_are_enabled());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_server_running_obj, network_server_running);
STATIC mp_obj_t network_server_deinit(mp_obj_t self_in) {
// simply stop the servers
servers_stop();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_server_deinit_obj, network_server_deinit);
#endif
STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
@@ -92,9 +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_running), (mp_obj_t)&network_server_running_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_server_login), (mp_obj_t)&network_server_login_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_server_timeout), (mp_obj_t)&network_server_timeout_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_server), (mp_obj_t)&network_server_type },
#endif
};
@@ -105,3 +164,21 @@ const mp_obj_module_t mp_module_network = {
.name = MP_QSTR_network,
.globals = (mp_obj_dict_t*)&mp_module_network_globals,
};
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
STATIC const mp_map_elem_t network_server_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&network_server_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&network_server_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_timeout), (mp_obj_t)&network_server_timeout_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_isrunning), (mp_obj_t)&network_server_running_obj },
};
STATIC MP_DEFINE_CONST_DICT(network_server_locals_dict, network_server_locals_dict_table);
STATIC const mp_obj_type_t network_server_type = {
{ &mp_type_type },
.name = MP_QSTR_server,
.make_new = network_server_make_new,
.locals_dict = (mp_obj_t)&network_server_locals_dict,
};
#endif

View File

@@ -1,306 +0,0 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2015 Daniel Campora
*
* 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 "std.h"
#include "py/mpstate.h"
#include "py/runtime.h"
#include MICROPY_HAL_H
#include "irq.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_uart.h"
#include "rom_map.h"
#include "prcm.h"
#include "pyexec.h"
#include "pybuart.h"
#include "pybpin.h"
#include "pybrtc.h"
#include "mpsystick.h"
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
#include "moduos.h"
#include "telnet.h"
#include "ff.h"
#include "diskio.h"
#include "sflash_diskio.h"
#include "FreeRTOS.h"
#include "portable.h"
#include "task.h"
#include "mpexception.h"
#include "mpcallback.h"
#include "random.h"
#include "pybadc.h"
#include "pybi2c.h"
#include "pybsd.h"
#include "pybwdt.h"
#include "pybsleep.h"
#include "pybspi.h"
#include "pybtimer.h"
#include "utils.h"
#include "gccollect.h"
#include "mperror.h"
#include "genhdr/mpversion.h"
#ifdef DEBUG
extern OsiTaskHandle mpTaskHandle;
extern OsiTaskHandle svTaskHandle;
extern OsiTaskHandle xSimpleLinkSpawnTaskHndl;
#endif
/// \module pyb - functions related to the pyboard
///
/// The `pyb` module contains specific functions related to the pyboard.
/// \function reset()
/// Resets the pyboard in a manner similar to pushing the external
/// reset button.
STATIC mp_obj_t pyb_reset(void) {
// disable wlan
wlan_stop(SL_STOP_TIMEOUT_LONG);
// reset the cpu and it's peripherals
MAP_PRCMMCUReset(true);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_reset_obj, pyb_reset);
#ifdef DEBUG
/// \function info([dump_alloc_table])
/// Print out some run time info which is helpful duirng development.
STATIC mp_obj_t pyb_info(uint n_args, const mp_obj_t *args) {
// FreeRTOS info
{
printf("---------------------------------------------\n");
printf("FreeRTOS\n");
printf("---------------------------------------------\n");
printf("Total heap: %u\n", configTOTAL_HEAP_SIZE);
printf("Free heap: %u\n", xPortGetFreeHeapSize());
printf("MpTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark((TaskHandle_t)mpTaskHandle));
printf("ServersTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark((TaskHandle_t)svTaskHandle));
printf("SlTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark(xSimpleLinkSpawnTaskHndl));
printf("IdleTask min free stack: %u\n", (unsigned int)uxTaskGetStackHighWaterMark(xTaskGetIdleTaskHandle()));
uint32_t *pstack = (uint32_t *)&_stack;
while (*pstack == 0x55555555) {
pstack++;
}
printf("MAIN min free stack: %u\n", pstack - ((uint32_t *)&_stack));
printf("---------------------------------------------\n");
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj, 0, 1, pyb_info);
#endif
/// \function freq()
/// Returns the CPU frequency: (F_CPU).
STATIC mp_obj_t pyb_freq(void) {
mp_obj_t tuple[1] = {
mp_obj_new_int(HAL_FCPU_HZ),
};
return mp_obj_new_tuple(1, tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_freq_obj, pyb_freq);
/// \function unique_id()
/// Returns a string of 6 bytes (48 bits), which is the unique ID for the MCU.
STATIC mp_obj_t pyb_unique_id(void) {
uint8_t mac[SL_BSSID_LENGTH];
wlan_get_mac (mac);
return mp_obj_new_bytes(mac, SL_BSSID_LENGTH);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_unique_id_obj, pyb_unique_id);
/// \function millis()
/// Returns the number of milliseconds since the board was last reset.
///
/// The result is always a micropython smallint (31-bit signed number), so
/// after 2^30 milliseconds (about 12.4 days) this will start to return
/// negative numbers.
STATIC mp_obj_t pyb_millis(void) {
// We want to "cast" the 32 bit unsigned into a small-int. This means
// copying the MSB down 1 bit (extending the sign down), which is
// equivalent to just using the MP_OBJ_NEW_SMALL_INT macro.
return MP_OBJ_NEW_SMALL_INT(HAL_GetTick());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_millis_obj, pyb_millis);
/// \function elapsed_millis(start)
/// Returns the number of milliseconds which have elapsed since `start`.
///
/// This function takes care of counter wrap, and always returns a positive
/// number. This means it can be used to measure periods upto about 12.4 days.
///
/// Example:
/// start = pyb.millis()
/// while pyb.elapsed_millis(start) < 1000:
/// # Perform some operation
STATIC mp_obj_t pyb_elapsed_millis(mp_obj_t start) {
uint32_t startMillis = mp_obj_get_int(start);
uint32_t currMillis = HAL_GetTick();
return MP_OBJ_NEW_SMALL_INT((currMillis - startMillis) & 0x3fffffff);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_millis_obj, pyb_elapsed_millis);
/// \function micros()
/// Returns the number of microseconds since the board was last reset.
///
/// The result is always a micropython smallint (31-bit signed number), so
/// after 2^30 microseconds (about 17.8 minutes) this will start to return
/// negative numbers.
STATIC mp_obj_t pyb_micros(void) {
// We want to "cast" the 32 bit unsigned into a small-int. This means
// copying the MSB down 1 bit (extending the sign down), which is
// equivalent to just using the MP_OBJ_NEW_SMALL_INT macro.
return MP_OBJ_NEW_SMALL_INT(sys_tick_get_microseconds());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_micros_obj, pyb_micros);
/// \function elapsed_micros(start)
/// Returns the number of microseconds which have elapsed since `start`.
///
/// This function takes care of counter wrap, and always returns a positive
/// number. This means it can be used to measure periods upto about 17.8 minutes.
///
/// Example:
/// start = pyb.micros()
/// while pyb.elapsed_micros(start) < 1000:
/// # Perform some operation
STATIC mp_obj_t pyb_elapsed_micros(mp_obj_t start) {
uint32_t startMicros = mp_obj_get_int(start);
uint32_t currMicros = sys_tick_get_microseconds();
return MP_OBJ_NEW_SMALL_INT((currMicros - startMicros) & 0x3fffffff);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_micros_obj, pyb_elapsed_micros);
/// \function delay(ms)
/// Delay for the given number of milliseconds.
STATIC mp_obj_t pyb_delay(mp_obj_t ms_in) {
mp_int_t ms = mp_obj_get_int(ms_in);
if (ms > 0) {
HAL_Delay(ms);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_delay_obj, pyb_delay);
/// \function udelay(us)
/// Delay for the given number of microseconds.
STATIC mp_obj_t pyb_udelay(mp_obj_t usec_in) {
mp_int_t usec = mp_obj_get_int(usec_in);
if (usec > 0) {
UtilsDelay(UTILS_DELAY_US_TO_COUNT(usec));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_udelay_obj, pyb_udelay);
/// \function repl_uart(uart)
/// Get or set the UART object that the REPL is repeated on.
STATIC mp_obj_t pyb_repl_uart(uint n_args, const mp_obj_t *args) {
if (n_args == 0) {
if (pyb_stdio_uart == NULL) {
return mp_const_none;
} else {
return pyb_stdio_uart;
}
} else {
if (args[0] == mp_const_none) {
pyb_stdio_uart = NULL;
} else if (mp_obj_get_type(args[0]) == &pyb_uart_type) {
pyb_stdio_uart = args[0];
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, mpexception_num_type_invalid_arguments));
}
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_repl_uart_obj, 0, 1, pyb_repl_uart);
MP_DECLARE_CONST_FUN_OBJ(pyb_main_obj); // defined in main.c
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_reset), (mp_obj_t)&pyb_reset_obj },
#ifdef DEBUG
{ MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_info_obj },
#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&pyb_freq_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_unique_id), (mp_obj_t)&pyb_unique_id_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_repl_info), (mp_obj_t)&pyb_set_repl_info_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_repl_uart), (mp_obj_t)&pyb_repl_uart_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable_irq), (mp_obj_t)&pyb_disable_irq_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable_irq), (mp_obj_t)&pyb_enable_irq_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_main), (mp_obj_t)&pyb_main_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 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_micros), (mp_obj_t)&pyb_micros_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_micros), (mp_obj_t)&pyb_elapsed_micros_obj },
{ 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 },
#if MICROPY_HW_ENABLE_RNG
{ MP_OBJ_NEW_QSTR(MP_QSTR_rng), (mp_obj_t)&pyb_rng_get_obj },
#endif
#if MICROPY_HW_ENABLE_RTC
{ MP_OBJ_NEW_QSTR(MP_QSTR_RTC), (mp_obj_t)&pyb_rtc_type },
#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pin_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pyb_adc_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_i2c_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&pyb_spi_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Timer), (mp_obj_t)&pyb_timer_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WDT), (mp_obj_t)&pyb_wdt_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Sleep), (mp_obj_t)&pyb_sleep_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HeartBeat), (mp_obj_t)&pyb_heartbeat_type },
#if MICROPY_HW_HAS_SDCARD
{ MP_OBJ_NEW_QSTR(MP_QSTR_SD), (mp_obj_t)&pyb_sd_type },
#endif
};
STATIC MP_DEFINE_CONST_DICT(pyb_module_globals, pyb_module_globals_table);
const mp_obj_module_t pyb_module = {
.base = { &mp_type_module },
.name = MP_QSTR_pyb,
.globals = (mp_obj_dict_t*)&pyb_module_globals,
};

View File

@@ -28,21 +28,22 @@
#include <stdint.h>
#include <string.h>
#include "py/mpconfig.h"
#include "py/mpstate.h"
#include "py/nlr.h"
#include "py/obj.h"
#include "py/objtuple.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "genhdr/mpversion.h"
#include "ff.h"
#include "moduos.h"
#include "diskio.h"
#include "sflash_diskio.h"
#include "file.h"
#include "random.h"
#include "sd_diskio.h"
#include "mpexception.h"
#include "version.h"
#include "timeutils.h"
#include "pybsd.h"
#include "pybuart.h"
/// \module os - basic "operating system" services
///
@@ -52,20 +53,154 @@
/// drives are accessible from here. They are currently:
///
/// /flash -- the serial flash filesystem
/// /sd -- the SD card (if it exists)
///
/// On boot up, the current directory is `/flash` if no SD card is inserted,
/// otherwise it is `/sd`.
/// On boot up, the current directory is `/flash`.
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC uint32_t os_num_mounted_devices;
STATIC os_term_dup_obj_t os_term_dup_obj;
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
void moduos_init0 (void) {
// initialize the mount objects list
mp_obj_list_init(&MP_STATE_PORT(mount_obj_list), 0);
os_num_mounted_devices = 0;
}
os_fs_mount_t *osmount_find_by_path (const char *path) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
if (!strcmp(path, mount_obj->path)) {
return mount_obj;
}
}
return NULL;
}
os_fs_mount_t *osmount_find_by_volume (uint8_t vol) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
if (vol == mount_obj->vol) {
return mount_obj;
}
}
return NULL;
}
os_fs_mount_t *osmount_find_by_device (mp_obj_t device) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
if (device == mount_obj->device) {
return mount_obj;
}
}
return NULL;
}
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
STATIC bool sd_in_root(void) {
#if MICROPY_HW_HAS_SDCARD
return sd_disk_ready();
#else
return false;
// Checks for path equality, ignoring trailing slashes:
// path_equal(/, /) -> true
// path_equal(/flash//, /flash) -> true
// second argument must be in canonical form (meaning no trailing slash, unless it's just /)
STATIC bool path_equal(const char *path, const char *path_canonical) {
for (; *path_canonical != '\0' && *path == *path_canonical; ++path, ++path_canonical) {
}
if (*path_canonical != '\0') {
return false;
}
for (; *path == '/'; ++path) {
}
return *path == '\0';
}
STATIC void append_dir_item (mp_obj_t dirlist, const char *item, bool string) {
// make a string object for this entry
mp_obj_t entry_o;
if (string) {
entry_o = mp_obj_new_str(item, strlen(item), false);
} else {
entry_o = mp_obj_new_bytes((const byte*)item, strlen(item));
}
// add the entry to the list
mp_obj_list_append(dirlist, entry_o);
}
STATIC void mount (mp_obj_t device, const char *path, uint pathlen, bool readonly) {
// is the mount point already in use?
FILINFO fno;
#if _USE_LFN
fno.lfname = NULL;
fno.lfsize = 0;
#endif
// cannot mount twice or on existing paths
if (f_stat(path, &fno) == FR_OK || osmount_find_by_device(device)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
// create a new object
os_fs_mount_t *self = m_new_obj(os_fs_mount_t);
self->device = device;
self->path = path;
self->pathlen = pathlen;
self->vol = os_num_mounted_devices + 1; // '/flash' is volume 0
if (device == (mp_obj_t)&pybsd_obj) {
// need to make it different to NULL, otherwise it's read only by default
self->writeblocks[0] = mp_const_none;
self->sync[0] = MP_OBJ_NULL; // no need to sync the SD card
self->count[0] = MP_OBJ_NULL;
} else {
// load block protocol methods
mp_load_method(device, MP_QSTR_readblocks, self->readblocks);
mp_load_method_maybe(device, MP_QSTR_writeblocks, self->writeblocks);
mp_load_method_maybe(device, MP_QSTR_sync, self->sync);
mp_load_method(device, MP_QSTR_count, self->count);
}
// Read-only device indicated by writeblocks[0] == MP_OBJ_NULL.
// User can specify read-only device by:
// 1. readonly=True keyword argument
// 2. nonexistent writeblocks method (then writeblocks[0] == MP_OBJ_NULL already)
if (readonly) {
self->writeblocks[0] = MP_OBJ_NULL;
}
// we need to add it before doing the actual mount, so that the volume can be found
mp_obj_list_append(&MP_STATE_PORT(mount_obj_list), self);
// actually mount it
if (f_mount(&self->fatfs, self->path, 1) != FR_OK) {
// remove it and raise
mp_obj_list_remove(&MP_STATE_PORT(mount_obj_list), self);
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
// mount succeeded, increment the count
os_num_mounted_devices++;
}
STATIC void unmount (const char *path) {
if (FR_OK != f_mount (NULL, path, 1)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
// remove from the list after the actual unmount
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_path(path))) {
mp_obj_list_remove(&MP_STATE_PORT(mount_obj_list), mount_obj);
os_num_mounted_devices--;
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
}
/******************************************************************************/
@@ -117,25 +252,20 @@ STATIC mp_obj_t os_chdir(mp_obj_t path_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_chdir_obj, os_chdir);
/// \function getcwd()
/// Get the current directory.
STATIC mp_obj_t os_getcwd(void) {
char buf[MICROPY_ALLOC_PATH_MAX + 1];
FRESULT res = f_getcwd(buf, sizeof buf);
if (res != FR_OK) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
return mp_obj_new_str(buf, strlen(buf), false);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd);
/// \function listdir([dir])
/// With no argument, list the current directory. Otherwise list the given directory.
STATIC mp_obj_t os_listdir(mp_uint_t n_args, const mp_obj_t *args) {
bool is_str_type = true;
const char *path;
mp_obj_t dir_list = mp_obj_new_list(0, NULL);
if (n_args == 1) {
if (mp_obj_get_type(args[0]) == &mp_type_bytes) {
@@ -146,66 +276,51 @@ STATIC mp_obj_t os_listdir(mp_uint_t n_args, const mp_obj_t *args) {
path = "";
}
// "hack" to list root directory
// "hack" to list the root directory
if (path[0] == '/' && path[1] == '\0') {
mp_obj_t dir_list = mp_obj_new_list(0, NULL);
mp_obj_list_append(dir_list, MP_OBJ_NEW_QSTR(MP_QSTR_flash));
#if MICROPY_HW_HAS_SDCARD
if (sd_in_root()) {
mp_obj_list_append(dir_list, MP_OBJ_NEW_QSTR(MP_QSTR_sd));
// add 'flash' to the list
append_dir_item (dir_list, "flash", is_str_type);
for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
append_dir_item (dir_list, &mount_obj->path[1], is_str_type);
}
#endif
return dir_list;
}
} else {
FRESULT res;
DIR dir;
FILINFO fno;
#if _USE_LFN
char lfn_buf[_MAX_LFN + 1];
fno.lfname = lfn_buf;
fno.lfsize = sizeof(lfn_buf);
#endif
FRESULT res;
DIR dir;
FILINFO fno;
#if _USE_LFN
char lfn_buf[_MAX_LFN + 1];
fno.lfname = lfn_buf;
fno.lfsize = sizeof(lfn_buf);
#endif
res = f_opendir(&dir, path); /* Open the directory */
if (res != FR_OK) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
mp_obj_t dir_list = mp_obj_new_list(0, NULL);
for (;;) {
res = f_readdir(&dir, &fno); /* Read a directory item */
if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
if (fno.fname[0] == '.' && fno.fname[1] == 0) continue; /* Ignore . entry */
if (fno.fname[0] == '.' && fno.fname[1] == '.' && fno.fname[2] == 0) continue; /* Ignore .. entry */
#if _USE_LFN
char *fn = *fno.lfname ? fno.lfname : fno.fname;
#else
char *fn = fno.fname;
#endif
// make a string object for this entry
mp_obj_t entry_o;
if (is_str_type) {
entry_o = mp_obj_new_str(fn, strlen(fn), false);
} else {
entry_o = mp_obj_new_bytes((const byte*)fn, strlen(fn));
res = f_opendir(&dir, path); /* Open the directory */
if (res != FR_OK) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
// add the entry to the list
mp_obj_list_append(dir_list, entry_o);
}
for ( ; ; ) {
res = f_readdir(&dir, &fno); /* Read a directory item */
if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
if (fno.fname[0] == '.' && fno.fname[1] == 0) continue; /* Ignore . entry */
if (fno.fname[0] == '.' && fno.fname[1] == '.' && fno.fname[2] == 0) continue; /* Ignore .. entry */
f_closedir(&dir);
#if _USE_LFN
char *fn = *fno.lfname ? fno.lfname : fno.fname;
#else
char *fn = fno.fname;
#endif
// add the entry to the list
append_dir_item (dir_list, fn, is_str_type);
}
f_closedir(&dir);
}
return dir_list;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_listdir_obj, 0, 1, os_listdir);
/// \function mkdir(path)
/// Create a new directory.
STATIC mp_obj_t os_mkdir(mp_obj_t path_o) {
const char *path = mp_obj_str_get_str(path_o);
FRESULT res = f_mkdir(path);
@@ -221,8 +336,6 @@ STATIC mp_obj_t os_mkdir(mp_obj_t path_o) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir);
/// \function rename(old_path, new_path)
/// Rename a file
STATIC mp_obj_t os_rename(mp_obj_t path_in, mp_obj_t path_out) {
const char *old_path = mp_obj_str_get_str(path_in);
const char *new_path = mp_obj_str_get_str(path_out);
@@ -233,12 +346,9 @@ STATIC mp_obj_t os_rename(mp_obj_t path_in, mp_obj_t path_out) {
default:
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename);
/// \function remove(path)
/// Remove a file or a directory
STATIC mp_obj_t os_remove(mp_obj_t path_o) {
const char *path = mp_obj_str_get_str(path_o);
FRESULT res = f_unlink(path);
@@ -251,49 +361,33 @@ STATIC mp_obj_t os_remove(mp_obj_t path_o) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove);
// Checks for path equality, ignoring trailing slashes:
// path_equal(/, /) -> true
// path_equal(/flash//, /flash) -> true
// second argument must be in canonical form (meaning no trailing slash, unless it's just /)
STATIC bool path_equal(const char *path, const char *path_canonical) {
for (; *path_canonical != '\0' && *path == *path_canonical; ++path, ++path_canonical) {
}
if (*path_canonical != '\0') {
return false;
}
for (; *path == '/'; ++path) {
}
return *path == '\0';
}
/// \function stat(path)
/// Get the status of a file or directory.
STATIC mp_obj_t os_stat(mp_obj_t path_in) {
const char *path = mp_obj_str_get_str(path_in);
FRESULT res;
bool isbuilt_in = false;
FILINFO fno;
FRESULT res;
#if _USE_LFN
fno.lfname = NULL;
fno.lfsize = 0;
#endif
if (path_equal(path, "/") || path_equal(path, "/flash") || path_equal(path, "/sd")) {
// check on the user mounted devices
for (mp_uint_t i = 0; i < MP_STATE_PORT(mount_obj_list).len; i++) {
os_fs_mount_t *mount_obj = ((os_fs_mount_t *)(MP_STATE_PORT(mount_obj_list).items[i]));
if (path_equal(path, mount_obj->path)) {
isbuilt_in = true;
break;
}
}
if (path_equal(path, "/") || path_equal(path, "/flash") || isbuilt_in) {
// stat built-in directory
if (path[1] == 's' && !sd_in_root()) {
// no /sd directory
res = FR_NO_PATH;
goto error;
}
fno.fsize = 0;
fno.fdate = 0;
fno.ftime = 0;
fno.fattrib = AM_DIR;
} else {
res = f_stat(path, &fno);
if (res != FR_OK) {
goto error;
}
fno.fsize = 0;
fno.fdate = 0;
fno.ftime = 0;
fno.fattrib = AM_DIR;
} else if ((res = f_stat(path, &fno)) != FR_OK) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
mp_obj_tuple_t *t = mp_obj_new_tuple(10, NULL);
@@ -321,26 +415,16 @@ STATIC mp_obj_t os_stat(mp_obj_t path_in) {
t->items[7] = mp_obj_new_int(seconds); // st_atime
t->items[8] = t->items[7]; // st_mtime
t->items[9] = t->items[7]; // st_ctime
return t;
error:
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_stat_obj, os_stat);
/// \function sync()
/// Sync all filesystems.
STATIC mp_obj_t os_sync(void) {
sflash_disk_flush();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_sync_obj, os_sync);
#if MICROPY_HW_ENABLE_RNG
/// \function urandom(n)
/// Return a bytes object with n random bytes, generated by the hardware
/// random number generator.
STATIC mp_obj_t os_urandom(mp_obj_t num) {
mp_int_t n = mp_obj_get_int(num);
vstr_t vstr;
@@ -351,19 +435,133 @@ STATIC mp_obj_t os_urandom(mp_obj_t num) {
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
#endif
/// \function mkfs('path')
/// Formats the selected drive, useful when the filesystem has been damaged beyond repair
STATIC mp_obj_t os_mkfs(mp_obj_t path_o) {
STATIC mp_obj_t os_mount(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t mount_args[] = {
{ MP_QSTR_readonly, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
// parse args
mp_obj_t device = pos_args[0];
mp_obj_t mount_point = pos_args[1];
mp_arg_val_t args[MP_ARRAY_SIZE(mount_args)];
mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(mount_args), mount_args, args);
// get the mount point
mp_uint_t pathlen;
const char *path_in = mp_obj_str_get_data(mount_point, &pathlen);
if (pathlen == 0) {
goto invalid_args;
}
char *path = m_new(char, pathlen + 1);
memcpy(path, path_in, pathlen);
path[pathlen] = '\0';
// "remove" any extra slahes at the end
while (path[(pathlen - 1)] == '/') {
path[--pathlen] = '\0';
}
// is the mount point valid?
if (pathlen < 2 || path[0] !='/' || strchr(&path[1], '/')) {
goto invalid_args;
}
// now mount it
mount(device, path, pathlen, args[0].u_bool);
return mp_const_none;
invalid_args:
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_value_invalid_arguments));
}
MP_DEFINE_CONST_FUN_OBJ_KW(os_mount_obj, 2, os_mount);
STATIC mp_obj_t os_unmount(mp_obj_t path_o) {
const char *path = mp_obj_str_get_str(path_o);
if (FR_OK != f_mkfs(path, 1, 0)) {
// '/flash' cannot be unmounted, also not the current working directory
if (path_equal(path, "/flash")) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
// now unmount it
unmount (path);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_unmount_obj, os_unmount);
STATIC mp_obj_t os_mkfs(mp_obj_t device) {
const char *path = "/__mkfs__mnt__";
bool unmt = false;
FRESULT res;
if (MP_OBJ_IS_STR_OR_BYTES(device)) {
path = mp_obj_str_get_str(device);
// otherwise the relative path check will pass...
if (path[0] != '/') {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_value_invalid_arguments));
}
} else {
// mount it and unmount it briefly
unmt = true;
mount(device, path, strlen(path), false);
}
byte sfd = 0;
if (!memcmp(path, "/flash", strlen("/flash"))) {
sfd = 1;
} else {
os_fs_mount_t *mount_obj;
if ((mount_obj = osmount_find_by_path(path))) {
if (mount_obj->device != (mp_obj_t)&pybsd_obj &&
mp_obj_get_int(mp_call_method_n_kw(0, 0, mount_obj->count)) < 2048) {
sfd = 1;
}
}
}
// now format the device
res = f_mkfs(path, sfd, 0);
if (unmt) {
unmount (path);
}
if (res != FR_OK) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkfs_obj, os_mkfs);
STATIC mp_obj_t os_dupterm(uint n_args, const mp_obj_t *args) {
if (n_args == 0) {
if (MP_STATE_PORT(os_term_dup_obj) == MP_OBJ_NULL) {
return mp_const_none;
} else {
return MP_STATE_PORT(os_term_dup_obj)->stream_o;
}
} else {
mp_obj_t stream_o = args[0];
if (stream_o == mp_const_none) {
MP_STATE_PORT(os_term_dup_obj) = MP_OBJ_NULL;
} else {
if (!MP_OBJ_IS_TYPE(stream_o, &pyb_uart_type)) {
// must be a stream-like object providing at least read and write methods
mp_load_method(stream_o, MP_QSTR_read, os_term_dup_obj.read);
mp_load_method(stream_o, MP_QSTR_write, os_term_dup_obj.write);
}
os_term_dup_obj.stream_o = stream_o;
MP_STATE_PORT(os_term_dup_obj) = &os_term_dup_obj;
}
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_dupterm_obj, 0, 1, os_dupterm);
STATIC const mp_map_elem_t os_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uos) },
@@ -374,14 +572,17 @@ STATIC const mp_map_elem_t os_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_mkdir), (mp_obj_t)&os_mkdir_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rename), (mp_obj_t)&os_rename_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&os_remove_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rmdir), (mp_obj_t)&os_remove_obj }, // rmdir aliases to remove
{ MP_OBJ_NEW_QSTR(MP_QSTR_rmdir), (mp_obj_t)&os_remove_obj }, // rmdir aliases to remove
{ MP_OBJ_NEW_QSTR(MP_QSTR_stat), (mp_obj_t)&os_stat_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_unlink), (mp_obj_t)&os_remove_obj }, // unlink aliases to remove
{ MP_OBJ_NEW_QSTR(MP_QSTR_unlink), (mp_obj_t)&os_remove_obj }, // unlink aliases to remove
{ MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&os_sync_obj },
#if MICROPY_HW_ENABLE_RNG
{ MP_OBJ_NEW_QSTR(MP_QSTR_urandom), (mp_obj_t)&os_urandom_obj },
#endif
// MicroPython additions
{ MP_OBJ_NEW_QSTR(MP_QSTR_mount), (mp_obj_t)&os_mount_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_unmount), (mp_obj_t)&os_unmount_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mkfs), (mp_obj_t)&os_mkfs_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_dupterm), (mp_obj_t)&os_dupterm_obj },
/// \constant sep - separation character used in paths
{ MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_OBJ_NEW_QSTR(MP_QSTR__slash_) },

View File

@@ -28,5 +28,34 @@
#ifndef MODUOS_H_
#define MODUOS_H_
#include "ff.h"
/******************************************************************************
DEFINE PUBLIC TYPES
******************************************************************************/
typedef struct _os_fs_mount_t {
mp_obj_t device;
const char *path;
mp_uint_t pathlen;
mp_obj_t readblocks[4];
mp_obj_t writeblocks[4];
mp_obj_t sync[2];
mp_obj_t count[2];
FATFS fatfs;
uint8_t vol;
} os_fs_mount_t;
typedef struct _os_term_dup_obj_t {
mp_obj_t stream_o;
mp_obj_t read[3];
mp_obj_t write[3];
} os_term_dup_obj_t;
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
******************************************************************************/
void moduos_init0 (void);
os_fs_mount_t *osmount_find_by_path (const char *path);
os_fs_mount_t *osmount_find_by_volume (uint8_t vol);
#endif // MODUOS_H_

View File

@@ -185,17 +185,23 @@ STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
// method socket.listen(backlog)
STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog) {
mod_network_socket_obj_t *self = self_in;
// method socket.listen([backlog])
STATIC mp_obj_t socket_listen(mp_uint_t n_args, const mp_obj_t *args) {
mod_network_socket_obj_t *self = args[0];
int32_t backlog = 0;
if (n_args > 1) {
backlog = mp_obj_get_int(args[1]);
backlog = (backlog < 0) ? 0 : backlog;
}
int _errno;
if (wlan_socket_listen(self, mp_obj_get_int(backlog), &_errno) != 0) {
if (wlan_socket_listen(self, backlog, &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_listen_obj, 1, 2, socket_listen);
// method socket.accept()
STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
@@ -391,6 +397,21 @@ STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
STATIC mp_obj_t socket_makefile(mp_uint_t n_args, const mp_obj_t *args) {
// TODO: CPython explicitly says that closing the returned object doesn't
// close the original socket (Python2 at all says that fd is dup()ed). But
// we save on the bloat.
mod_network_socket_obj_t *self = args[0];
if (n_args > 1) {
const char *mode = mp_obj_str_get_str(args[1]);
if (strcmp(mode, "rb") && strcmp(mode, "wb")) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
}
return self;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 6, socket_makefile);
STATIC const mp_map_elem_t socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&socket_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj },
@@ -406,7 +427,7 @@ STATIC const mp_map_elem_t socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&socket_setsockopt_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_settimeout), (mp_obj_t)&socket_settimeout_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_setblocking), (mp_obj_t)&socket_setblocking_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_makefile), (mp_obj_t)&mp_identity_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_makefile), (mp_obj_t)&socket_makefile_obj },
// stream methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
@@ -504,16 +525,13 @@ STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(AF_INET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET6), MP_OBJ_NEW_SMALL_INT(AF_INET6) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(SOCK_STREAM) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(SOCK_DGRAM) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_RAW), MP_OBJ_NEW_SMALL_INT(SOCK_RAW) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_SEC), MP_OBJ_NEW_SMALL_INT(SL_SEC_SOCKET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(IPPROTO_TCP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(IPPROTO_UDP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_RAW), MP_OBJ_NEW_SMALL_INT(IPPROTO_RAW) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table);

View File

@@ -61,7 +61,7 @@ STATIC const mp_obj_type_t ssl_socket_type;
/******************************************************************************/
// Micro Python bindings; SSL class
// ssl socket inherits from normal socket, so we take its
// ssl sockets inherit from normal socket, so we take its
// locals and stream methods
STATIC const mp_obj_type_t ssl_socket_type = {
{ &mp_type_type },
@@ -74,12 +74,12 @@ STATIC const mp_obj_type_t ssl_socket_type = {
STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC const mp_arg_t allowed_args[] = {
{ MP_QSTR_sock, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_keyfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_certfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_false} },
{ MP_QSTR_cert_reqs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SSL_CERT_NONE} },
{ MP_QSTR_ca_certs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_sock, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_keyfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_certfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
{ MP_QSTR_cert_reqs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SSL_CERT_NONE} },
{ MP_QSTR_ca_certs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
// parse arguments
@@ -88,17 +88,20 @@ STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args,
// chech if ca validation is required
if (args[4].u_int != SSL_CERT_NONE && args[5].u_obj == mp_const_none) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
goto arg_error;
}
// server side param is irrelevant for us (at least for the moment)
// retrieve the file paths (with an 6 byte offset because to strip the '/flash' prefix)
// retrieve the file paths (with an 6 byte offset in order to strip it from the '/flash' prefix)
const char *keyfile = (args[1].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[1].u_obj)[6]);
const char *certfile = (args[2].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[2].u_obj)[6]);
const char *cafile = (args[5].u_obj == mp_const_none || args[4].u_int != SSL_CERT_REQUIRED) ?
NULL : &(mp_obj_str_get_str(args[5].u_obj)[6]);
// server side requires both certfile and keyfile
if (args[3].u_bool && (!keyfile || !certfile)) {
goto arg_error;
}
_i16 sd = ((mod_network_socket_obj_t *)args[0].u_obj)->sock_base.sd;
_i16 _errno;
if (keyfile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, keyfile, strlen(keyfile))) < 0) {
@@ -113,7 +116,7 @@ STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args,
// create the ssl socket
mp_obj_ssl_socket_t *ssl_sock = m_new_obj(mp_obj_ssl_socket_t);
// ssl socket inherits all properties from the original socket
// ssl sockets inherit all properties from the original socket
memcpy (&ssl_sock->sock_base, &((mod_network_socket_obj_t *)args[0].u_obj)->sock_base, sizeof(mod_network_socket_base_t));
ssl_sock->base.type = &ssl_socket_type;
ssl_sock->sock_base.cert_req = (args[4].u_int == SSL_CERT_REQUIRED) ? true : false;
@@ -123,8 +126,11 @@ STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args,
socket_error:
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
arg_error:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 0, mod_ssl_wrap_socket);
STATIC const mp_map_elem_t mp_module_ussl_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ussl) },

View File

@@ -32,25 +32,32 @@
#include MICROPY_HAL_H
#include "py/nlr.h"
#include "py/obj.h"
#include "py/smallint.h"
#include "timeutils.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "rom_map.h"
#include "prcm.h"
#include "systick.h"
#include "pybrtc.h"
#include "mpsystick.h"
#include "mpexception.h"
#include "utils.h"
/// \module time - time related functions
///
/// The `time` module provides functions for getting the current time and date,
/// and for sleeping.
/******************************************************************************/
// Micro Python bindings
/// \function localtime([secs])
/// Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which
/// contains: (year, month, mday, hour, minute, second, weekday, yearday)
/// If secs is not provided or None, then the current time from the RTC is used.
/// year includes the century (for example 2014)
/// year includes the century (for example 2015)
/// month is 1-12
/// mday is 1-31
/// hour is 0-23
@@ -61,14 +68,9 @@
STATIC mp_obj_t time_localtime(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 0 || args[0] == mp_const_none) {
timeutils_struct_time_t tm;
uint32_t seconds;
uint16_t mseconds;
// get the seconds and the milliseconds from the RTC
MAP_PRCMRTCGet(&seconds, &mseconds);
mseconds = RTC_CYCLES_U16MS(mseconds);
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
// get the seconds from the RTC
timeutils_seconds_since_2000_to_struct_time(pyb_rtc_get_seconds(), &tm);
mp_obj_t tuple[8] = {
mp_obj_new_int(tm.tm_year),
mp_obj_new_int(tm.tm_mon),
@@ -99,11 +101,6 @@ STATIC mp_obj_t time_localtime(mp_uint_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
/// \function mktime()
/// This is inverse function of localtime. It's argument is a full 8-tuple
/// which expresses a time as per localtime. It returns an integer which is
/// the number of seconds since Jan 1, 2000.
STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
mp_uint_t len;
mp_obj_t *elem;
@@ -115,15 +112,16 @@ STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, mpexception_num_type_invalid_arguments));
}
return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]),
mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), mp_obj_get_int(elem[3]),
mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5])));
return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]),
mp_obj_get_int(elem[3]), mp_obj_get_int(elem[4]), mp_obj_get_int(elem[5])));
}
MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime);
STATIC mp_obj_t time_time(void) {
return mp_obj_new_int(pyb_rtc_get_seconds());
}
MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
/// \function sleep(seconds)
/// Sleep for the given number of seconds.
STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
int32_t sleep_s = mp_obj_get_int(seconds_o);
if (sleep_s > 0) {
@@ -133,20 +131,65 @@ STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
}
MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep);
/// \function time()
/// Returns the number of seconds, as an integer, since 1/1/2000.
STATIC mp_obj_t time_time(void) {
return mp_obj_new_int(pybrtc_get_seconds());
STATIC mp_obj_t time_sleep_ms (mp_obj_t ms_in) {
mp_int_t ms = mp_obj_get_int(ms_in);
if (ms > 0) {
HAL_Delay(ms);
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_ms_obj, time_sleep_ms);
STATIC mp_obj_t time_sleep_us (mp_obj_t usec_in) {
mp_int_t usec = mp_obj_get_int(usec_in);
if (usec > 0) {
UtilsDelay(UTILS_DELAY_US_TO_COUNT(usec));
}
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) {
// We want to "cast" the 32 bit unsigned into a 30-bit small-int
return MP_OBJ_NEW_SMALL_INT(HAL_GetTick() & 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) {
// We want to "cast" the 32 bit unsigned into a 30-bit small-int
return MP_OBJ_NEW_SMALL_INT(sys_tick_get_microseconds() & 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) {
// We want to "cast" the 32 bit unsigned into a 30-bit small-int
return MP_OBJ_NEW_SMALL_INT((SysTickPeriodGet() - SysTickValueGet()) & 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 t0, mp_obj_t t1) {
// We want to "cast" the 32 bit unsigned into a 30-bit small-int
uint32_t start = mp_obj_get_int(t0);
uint32_t end = mp_obj_get_int(t1);
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);
STATIC const mp_map_elem_t time_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_utime) },
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_utime) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_localtime), (mp_obj_t)&time_localtime_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mktime), (mp_obj_t)&time_mktime_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&time_sleep_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_time_obj },
{ 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_time), (mp_obj_t)&time_time_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&time_sleep_obj },
// MicroPython additions
{ 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 },
};
STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);

32
cc3200/mods/modwipy.c Normal file
View File

@@ -0,0 +1,32 @@
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/obj.h"
#include "py/runtime.h"
#include "mperror.h"
/******************************************************************************/
// Micro Python bindings
STATIC mp_obj_t mod_wipy_heartbeat (mp_uint_t n_args, const mp_obj_t *args) {
if (n_args) {
mperror_enable_heartbeat (mp_obj_is_true(args[0]));
return mp_const_none;
} else {
return mp_obj_new_bool(mperror_is_heartbeat_enabled());
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_wipy_heartbeat_obj, 0, 1, mod_wipy_heartbeat);
STATIC const mp_map_elem_t wipy_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_wipy) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_heartbeat), (mp_obj_t)&mod_wipy_heartbeat_obj },
};
STATIC MP_DEFINE_CONST_DICT(wipy_module_globals, wipy_module_globals_table);
const mp_obj_module_t wipy_module = {
.base = { &mp_type_module },
.name = MP_QSTR_wipy,
.globals = (mp_obj_dict_t*)&wipy_module_globals,
};

File diff suppressed because it is too large Load Diff

View File

@@ -35,6 +35,10 @@
#define SL_STOP_TIMEOUT 35
#define SL_STOP_TIMEOUT_LONG 575
#define MODWLAN_WIFI_EVENT_ANY 0x01
#define MODWLAN_SSID_LEN_MAX 32
/******************************************************************************
DEFINE TYPES
******************************************************************************/
@@ -45,6 +49,34 @@ typedef enum {
MODWLAN_ERROR_UNKNOWN = -3,
} modwlan_Status_t;
typedef struct _wlan_obj_t {
mp_obj_base_t base;
mp_obj_t irq_obj;
uint32_t status;
uint32_t ip;
int8_t mode;
uint8_t auth;
uint8_t channel;
uint8_t antenna;
// my own ssid, key and mac
uint8_t ssid[(MODWLAN_SSID_LEN_MAX + 1)];
uint8_t key[65];
uint8_t mac[SL_MAC_ADDR_LEN];
// the sssid (or name) and mac of the other device
uint8_t ssid_o[33];
uint8_t bssid[6];
uint8_t irq_flags;
bool irq_enabled;
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
bool servers_enabled;
#endif
} wlan_obj_t;
/******************************************************************************
DECLARE PUBLIC DATA
******************************************************************************/
@@ -54,12 +86,11 @@ extern _SlLockObj_t wlan_LockObj;
DECLARE PUBLIC FUNCTIONS
******************************************************************************/
extern void wlan_pre_init (void);
extern void wlan_sl_enable (int8_t mode, const char *ssid, uint8_t ssid_len, uint8_t sec,
const char *key, uint8_t key_len, uint8_t channel, bool append_mac);
extern void wlan_sl_init (int8_t mode, const char *ssid, uint8_t ssid_len, uint8_t auth, const char *key, uint8_t key_len,
uint8_t channel, uint8_t antenna, bool add_mac);
extern void wlan_first_start (void);
extern void wlan_update(void);
extern void wlan_stop (uint32_t timeout);
extern void wlan_start (void);
extern void wlan_get_mac (uint8_t *macAddress);
extern void wlan_get_ip (uint32_t *ip);
extern bool wlan_is_connected (void);

View File

@@ -52,17 +52,6 @@
#include "mpexception.h"
/// \moduleref pyb
/// \class ADC - analog to digital conversion: read analog values on a pin
///
/// Usage:
///
/// adc = pyb.ADC('GP5') # create an adc object on the given pin (GP2, GP3, GP4 o GP5)
/// adc.read() # read channel value
///
/// The sample rate is fixed to 62.5KHz and the resolution to 12 bits.
/******************************************************************************
DECLARE CONSTANTS
******************************************************************************/
@@ -71,32 +60,69 @@
/******************************************************************************
DEFINE TYPES
******************************************************************************/
typedef struct {
mp_obj_base_t base;
bool enabled;
} pyb_adc_obj_t;
typedef struct {
mp_obj_base_t base;
pin_obj_t *pin;
byte channel;
byte id;
} pyb_adc_obj_t;
bool enabled;
} pyb_adc_channel_obj_t;
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC pyb_adc_obj_t pyb_adc_obj[PYB_ADC_NUM_CHANNELS] = { {.pin = &pin_GP2, .channel = ADC_CH_0, .id = 1}, {.pin = &pin_GP3, .channel = ADC_CH_1, .id = 2},
{.pin = &pin_GP4, .channel = ADC_CH_2, .id = 2}, {.pin = &pin_GP5, .channel = ADC_CH_3, .id = 4} };
STATIC pyb_adc_channel_obj_t pyb_adc_channel_obj[PYB_ADC_NUM_CHANNELS] = { {.pin = &pin_GP2, .channel = ADC_CH_0, .id = 0, .enabled = false},
{.pin = &pin_GP3, .channel = ADC_CH_1, .id = 1, .enabled = false},
{.pin = &pin_GP4, .channel = ADC_CH_2, .id = 2, .enabled = false},
{.pin = &pin_GP5, .channel = ADC_CH_3, .id = 3, .enabled = false} };
STATIC pyb_adc_obj_t pyb_adc_obj = {.enabled = false};
STATIC const mp_obj_type_t pyb_adc_channel_type;
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC mp_obj_t adc_channel_deinit(mp_obj_t self_in);
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
STATIC void pybadc_init (pyb_adc_obj_t *self) {
// configure the pin in analog mode
pin_config (self->pin, PIN_MODE_0, GPIO_DIR_MODE_IN, PYBPIN_ANALOG_TYPE, PIN_STRENGTH_2MA);
// enable the ADC channel
MAP_ADCChannelEnable(ADC_BASE, self->channel);
STATIC void pyb_adc_init (pyb_adc_obj_t *self) {
// enable and configure the timer
MAP_ADCTimerConfig(ADC_BASE, (1 << 17) - 1);
MAP_ADCTimerEnable(ADC_BASE);
// enable the ADC peripheral
MAP_ADCEnable(ADC_BASE);
self->enabled = true;
}
STATIC void pyb_adc_check_init(void) {
// not initialized
if (!pyb_adc_obj.enabled) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
}
STATIC void pyb_adc_channel_init (pyb_adc_channel_obj_t *self) {
// the ADC block must be enabled first
pyb_adc_check_init();
// configure the pin in analog mode
pin_config (self->pin, -1, PIN_TYPE_ANALOG, PIN_TYPE_STD, -1, PIN_STRENGTH_2MA);
// enable the ADC channel
MAP_ADCChannelEnable(ADC_BASE, self->channel);
self->enabled = true;
}
STATIC void pyb_adc_deinit_all_channels (void) {
for (int i = 0; i < PYB_ADC_NUM_CHANNELS; i++) {
adc_channel_deinit(&pyb_adc_channel_obj[i]);
}
}
/******************************************************************************/
@@ -104,73 +130,108 @@ STATIC void pybadc_init (pyb_adc_obj_t *self) {
STATIC void adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_adc_obj_t *self = self_in;
mp_printf(print, "<ADC1 channel=%u on %q>", self->id, self->pin->name);
}
/// \classmethod \constructor(pin)
/// Create an ADC object associated with the given pin.
/// This allows you to then read analog values on that pin.
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 *args) {
// check number of arguments
mp_arg_check_num(n_args, n_kw, 1, 1, false);
// the argument passed is the pin
const pin_obj_t *pin = (pin_obj_t *)pin_find(args[0]);
for (int32_t idx = 0; idx < PYB_ADC_NUM_CHANNELS; idx++) {
if (pin == pyb_adc_obj[idx].pin) {
pyb_adc_obj_t *self = &pyb_adc_obj[idx];
self->base.type = &pyb_adc_type;
pybadc_init (self);
// register it with the sleep module
pybsleep_add ((const mp_obj_t)self, (WakeUpCB_t)pybadc_init);
return self;
}
if (self->enabled) {
mp_printf(print, "ADC(0, bits=12)");
} else {
mp_printf(print, "ADC(0)");
}
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
/// \method read()
/// Read the value on the analog pin and return it. The returned value
/// will be between 0 and 4095.
STATIC mp_obj_t adc_read(mp_obj_t self_in) {
pyb_adc_obj_t *self = self_in;
uint32_t sample;
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) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_adc_init_args)];
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_adc_init_args, args);
// wait until a new value is available
while (!MAP_ADCFIFOLvlGet(ADC_BASE, self->channel));
// read the sample
sample = MAP_ADCFIFORead(ADC_BASE, self->channel);
// the 12 bit sampled value is stored in bits [13:2]
return MP_OBJ_NEW_SMALL_INT((sample & 0x3FFF) >> 2);
// check the peripheral id
if (args[0].u_int != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
// check the number of bits
if (args[1].u_int != 12) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
// setup the object
pyb_adc_obj_t *self = &pyb_adc_obj;
self->base.type = &pyb_adc_type;
// initialize and register with the sleep module
pyb_adc_init(self);
pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)pyb_adc_init);
return self;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_read_obj, adc_read);
/// \method init()
/// Enable the adc channel
STATIC mp_obj_t adc_init(mp_obj_t self_in) {
pyb_adc_obj_t *self = self_in;
pybadc_init(self);
STATIC mp_obj_t adc_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_adc_init_args) - 1];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_adc_init_args[1], args);
// check the number of bits
if (args[0].u_int != 12) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
pyb_adc_init(pos_args[0]);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_init_obj, adc_init);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(adc_init_obj, 1, adc_init);
/// \method deinit()
/// Disable the adc channel
STATIC mp_obj_t adc_deinit(mp_obj_t self_in) {
pyb_adc_obj_t *self = self_in;
MAP_ADCChannelDisable(ADC_BASE, self->channel);
// first deinit all channels
pyb_adc_deinit_all_channels();
MAP_ADCDisable(ADC_BASE);
self->enabled = false;
// unregister it with the sleep module
pybsleep_remove ((const mp_obj_t)self);
pyb_sleep_remove ((const mp_obj_t)self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_deinit_obj, adc_deinit);
STATIC mp_obj_t adc_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC const mp_arg_t pyb_adc_channel_args[] = {
{ MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_pin, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_adc_channel_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_adc_channel_args, args);
uint ch_id;
if (args[0].u_obj != MP_OBJ_NULL) {
ch_id = mp_obj_get_int(args[0].u_obj);
if (ch_id >= PYB_ADC_NUM_CHANNELS) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_os_resource_not_avaliable));
} else if (args[1].u_obj != mp_const_none) {
uint pin_ch_id = pin_find_peripheral_type (args[1].u_obj, PIN_FN_ADC, 0);
if (ch_id != pin_ch_id) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
}
} else {
ch_id = pin_find_peripheral_type (args[1].u_obj, PIN_FN_ADC, 0);
}
// setup the object
pyb_adc_channel_obj_t *self = &pyb_adc_channel_obj[ch_id];
self->base.type = &pyb_adc_channel_type;
pyb_adc_channel_init (self);
// register it with the sleep module
pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)pyb_adc_channel_init);
return self;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(adc_channel_obj, 1, adc_channel);
STATIC const mp_map_elem_t adc_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&adc_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&adc_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&adc_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_channel), (mp_obj_t)&adc_channel_obj },
};
STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table);
@@ -183,3 +244,69 @@ const mp_obj_type_t pyb_adc_type = {
.locals_dict = (mp_obj_t)&adc_locals_dict,
};
STATIC void adc_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_adc_channel_obj_t *self = self_in;
if (self->enabled) {
mp_printf(print, "ADCChannel(%u, pin=%q)", self->id, self->pin->name);
} else {
mp_printf(print, "ADCChannel(%u)", self->id);
}
}
STATIC mp_obj_t adc_channel_init(mp_obj_t self_in) {
pyb_adc_channel_obj_t *self = self_in;
// re-enable it
pyb_adc_channel_init(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_channel_init_obj, adc_channel_init);
STATIC mp_obj_t adc_channel_deinit(mp_obj_t self_in) {
pyb_adc_channel_obj_t *self = self_in;
MAP_ADCChannelDisable(ADC_BASE, self->channel);
// unregister it with the sleep module
pyb_sleep_remove ((const mp_obj_t)self);
self->enabled = false;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_channel_deinit_obj, adc_channel_deinit);
STATIC mp_obj_t adc_channel_value(mp_obj_t self_in) {
pyb_adc_channel_obj_t *self = self_in;
uint32_t value;
// the channel must be enabled
if (!self->enabled) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
// wait until a new value is available
while (!MAP_ADCFIFOLvlGet(ADC_BASE, self->channel));
// read the sample
value = MAP_ADCFIFORead(ADC_BASE, self->channel);
// the 12 bit sampled value is stored in bits [13:2]
return MP_OBJ_NEW_SMALL_INT((value & 0x3FFF) >> 2);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_channel_value_obj, adc_channel_value);
STATIC mp_obj_t adc_channel_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, 0, false);
return adc_channel_value (self_in);
}
STATIC const mp_map_elem_t adc_channel_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&adc_channel_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&adc_channel_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&adc_channel_value_obj },
};
STATIC MP_DEFINE_CONST_DICT(adc_channel_locals_dict, adc_channel_locals_dict_table);
STATIC const mp_obj_type_t pyb_adc_channel_type = {
{ &mp_type_type },
.name = MP_QSTR_ADCChannel,
.print = adc_channel_print,
.call = adc_channel_call,
.locals_dict = (mp_obj_t)&adc_channel_locals_dict,
};

View File

@@ -44,50 +44,11 @@
#include "mpexception.h"
#include "pybsleep.h"
#include "utils.h"
#include "pybpin.h"
#include "pins.h"
/// \moduleref pyb
/// \class I2C - a two-wire serial protocol
///
/// I2C is a two-wire protocol for communicating between devices. At the physical
/// level it consists of 2 wires: SCL and SDA, the clock and data lines respectively.
///
/// I2C objects are created attached to a specific bus. They can be initialised
/// when created, or initialised later on:
///
/// from pyb import I2C
///
/// i2c = I2C(1) # create
/// i2c = I2C(1, I2C.MASTER, baudrate=50000) # create and init with a 50KHz baudrate
/// i2c.init(I2C.MASTER, baudrate=100000) # init with a 100KHz baudrate
/// i2c.deinit() # turn off the peripheral
///
/// Printing the i2c object gives you information about its configuration.
///
/// Basic methods for slave are send and recv:
///
/// i2c.send('abc') # send 3 bytes
/// i2c.send(0x42) # send a single byte, given by the number
/// data = i2c.recv(3) # receive 3 bytes
///
/// To receive inplace, first create a bytearray:
///
/// data = bytearray(3) # create a buffer
/// i2c.recv(data) # receive 3 bytes, writing them into data
///
/// A master must specify the recipient's address:
///
/// i2c.send('123', 0x42) # send 3 bytes to slave with address 0x42
/// i2c.send(b'456', addr=0x42) # keyword for address
///
/// Master also has other methods:
///
/// i2c.is_ready(0x42) # check if slave 0x42 is ready
/// i2c.scan() # scan for slaves on the bus, returning
/// # a list of valid addresses
/// i2c.mem_read(3, 0x42, 2) # read 3 bytes from memory of slave 0x42,
/// # starting at address 2 in the slave
/// i2c.mem_write('abc', 0x42, 2) # write 3 bytes to memory of slave 0x42,
/// # starting at address 2 in the slave
typedef struct _pyb_i2c_obj_t {
mp_obj_base_t base;
@@ -118,6 +79,8 @@ typedef struct _pyb_i2c_obj_t {
******************************************************************************/
STATIC pyb_i2c_obj_t pyb_i2c_obj = {.baudrate = 0};
STATIC const mp_obj_t pyb_i2c_def_pin[2] = {&pin_GP13, &pin_GP23};
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
@@ -174,9 +137,60 @@ STATIC bool pyb_i2c_transaction(uint cmd) {
return true;
}
STATIC bool pyb_i2c_write(byte devAddr, byte *data, uint len, bool stop) {
STATIC void pyb_i2c_check_init(pyb_i2c_obj_t *self) {
// not initialized
if (!self->baudrate) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
}
STATIC bool pyb_i2c_scan_device(byte devAddr) {
// Set I2C codec slave address
MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, devAddr, false);
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
MAP_I2CMasterControl(I2CA0_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);
return true;
}
STATIC bool pyb_i2c_mem_addr_write (byte addr, byte *mem_addr, uint mem_addr_len) {
// Set I2C codec slave address
MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, addr, false);
// Write the first byte to the controller.
MAP_I2CMasterDataPut(I2CA0_BASE, *mem_addr++);
// Initiate the transfer.
RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_START));
// Loop until the completion of transfer or error
while (--mem_addr_len) {
// Write the next byte of data
MAP_I2CMasterDataPut(I2CA0_BASE, *mem_addr++);
// Transact over I2C to send the next byte
RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_CONT));
}
return true;
}
STATIC bool pyb_i2c_mem_write (byte addr, byte *mem_addr, uint mem_addr_len, byte *data, uint data_len) {
if (pyb_i2c_mem_addr_write (addr, mem_addr, mem_addr_len)) {
// Loop until the completion of transfer or error
while (data_len--) {
// Write the next byte of data
MAP_I2CMasterDataPut(I2CA0_BASE, *data++);
// Transact over I2C to send the byte
RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_CONT));
}
// send the stop bit
RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_STOP));
return true;
}
return false;
}
STATIC bool pyb_i2c_write(byte addr, byte *data, uint len, bool stop) {
// Set I2C codec slave address
MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, addr, false);
// Write the first byte to the controller.
MAP_I2CMasterDataPut(I2CA0_BASE, *data++);
// Initiate the transfer.
@@ -190,34 +204,20 @@ STATIC bool pyb_i2c_write(byte devAddr, byte *data, uint len, bool stop) {
RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_CONT));
}
// If a stop bit is to be sent, send it.
// If a stop bit is to be sent, do it.
if (stop) {
RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_SEND_STOP));
}
return true;
}
STATIC bool pyb_i2c_read(byte devAddr, byte *data, uint len) {
uint cmd;
STATIC bool pyb_i2c_read(byte addr, byte *data, uint len) {
// Initiate a burst or single receive sequence
uint cmd = --len > 0 ? I2C_MASTER_CMD_BURST_RECEIVE_START : I2C_MASTER_CMD_SINGLE_RECEIVE;
// Set I2C codec slave address
MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, devAddr, true);
// Check if its a single receive or burst receive
if (len > 1) {
// Initiate a burst receive sequence
cmd = I2C_MASTER_CMD_BURST_RECEIVE_START;
}
else {
// Configure for a single receive
cmd = I2C_MASTER_CMD_SINGLE_RECEIVE;
}
MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, addr, true);
// Initiate the transfer.
RET_IF_ERR(pyb_i2c_transaction(cmd));
// Decrement the count
len--;
// Loop until the completion of reception or error
while (len) {
// Receive the byte over I2C
@@ -225,8 +225,7 @@ STATIC bool pyb_i2c_read(byte devAddr, byte *data, uint len) {
if (--len) {
// Continue with reception
RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_RECEIVE_CONT));
}
else {
} else {
// Complete the last reception
RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_BURST_RECEIVE_FINISH));
}
@@ -234,19 +233,38 @@ STATIC bool pyb_i2c_read(byte devAddr, byte *data, uint len) {
// Receive the last byte over I2C
*data = MAP_I2CMasterDataGet(I2CA0_BASE);
return true;
}
STATIC bool pyb_i2c_scan_device(byte devAddr) {
// Set I2C codec 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
MAP_I2CMasterControl(I2CA0_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);
STATIC void pyb_i2c_read_into (mp_arg_val_t *args, vstr_t *vstr) {
pyb_i2c_check_init(&pyb_i2c_obj);
// get the buffer to receive into
pyb_buf_get_for_recv(args[1].u_obj, vstr);
return true;
// receive the data
if (!pyb_i2c_read(args[0].u_int, (byte *)vstr->buf, vstr->len)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
}
STATIC void pyb_i2c_readmem_into (mp_arg_val_t *args, vstr_t *vstr) {
pyb_i2c_check_init(&pyb_i2c_obj);
// get the buffer to receive into
pyb_buf_get_for_recv(args[2].u_obj, vstr);
// get the addresses
mp_uint_t i2c_addr = args[0].u_int;
mp_uint_t mem_addr = args[1].u_int;
// determine the width of mem_addr (1 or 2 bytes)
mp_uint_t mem_addr_size = args[3].u_int >> 3;
// write the register address to be read from
if (pyb_i2c_mem_addr_write (i2c_addr, (byte *)&mem_addr, mem_addr_size)) {
// Read the specified length of data
if (!pyb_i2c_read (i2c_addr, (byte *)vstr->buf, vstr->len)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
}
}
/******************************************************************************/
@@ -255,79 +273,82 @@ STATIC bool pyb_i2c_scan_device(byte devAddr) {
STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_i2c_obj_t *self = self_in;
if (self->baudrate > 0) {
mp_printf(print, "<I2C1, I2C.MASTER, baudrate=%u>)", self->baudrate);
}
else {
mp_print_str(print, "<I2C1>");
mp_printf(print, "I2C(0, I2C.MASTER, baudrate=%u)", self->baudrate);
} else {
mp_print_str(print, "I2C(0)");
}
}
/// \method init(mode, *, baudrate=100000)
///
/// Initialise the I2C bus with the given parameters:
///
/// - `mode` must be either `I2C.MASTER` or `I2C.SLAVE`
/// - `baudrate` is the SCL clock rate (only sensible for a master)
STATIC const mp_arg_t pyb_i2c_init_args[] = {
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} },
};
#define PYB_I2C_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_init_args)
STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t vals[PYB_I2C_INIT_NUM_ARGS];
mp_arg_parse_all(n_args, args, kw_args, PYB_I2C_INIT_NUM_ARGS, pyb_i2c_init_args, vals);
STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self, const mp_arg_val_t *args) {
// verify that mode is master
if (vals[0].u_int != PYBI2C_MASTER) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
if (args[0].u_int != PYBI2C_MASTER) {
goto invalid_args;
}
// make sure the baudrate is between the valid range
self->baudrate = MIN(MAX(vals[1].u_int, PYBI2C_MIN_BAUD_RATE_HZ), PYBI2C_MAX_BAUD_RATE_HZ);
self->baudrate = MIN(MAX(args[1].u_int, PYBI2C_MIN_BAUD_RATE_HZ), PYBI2C_MAX_BAUD_RATE_HZ);
// assign the pins
mp_obj_t pins_o = args[2].u_obj;
if (pins_o != mp_const_none) {
mp_obj_t *pins;
if (pins_o == MP_OBJ_NULL) {
// use the default pins
pins = (mp_obj_t *)pyb_i2c_def_pin;
} else {
mp_obj_get_array_fixed_n(pins_o, 2, &pins);
}
pin_assign_pins_af (pins, 2, PIN_TYPE_STD_PU, PIN_FN_I2C, 0);
}
// init the I2C bus
i2c_init(self);
// register it with the sleep module
pybsleep_add ((const mp_obj_t)self, (WakeUpCB_t)i2c_init);
pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)i2c_init);
return mp_const_none;
invalid_args:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
/// \classmethod \constructor(bus, ...)
///
/// Construct an I2C object on the given bus. `bus` can only be 1.
/// 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.
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 *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
STATIC const mp_arg_t pyb_i2c_init_args[] = {
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_mode, MP_ARG_INT, {.u_int = PYBI2C_MASTER} },
{ 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) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_init_args)];
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_i2c_init_args, args);
// check the peripheral id
if (args[0].u_int != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
// setup the object
pyb_i2c_obj_t *self = &pyb_i2c_obj;
self->base.type = &pyb_i2c_type;
if (n_args > 1 || n_kw > 0) {
// start the peripheral
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
pyb_i2c_init_helper(self, n_args - 1, args + 1, &kw_args);
}
// start the peripheral
pyb_i2c_init_helper(self, &args[1]);
return (mp_obj_t)self;
}
STATIC mp_obj_t pyb_i2c_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
return pyb_i2c_init_helper(args[0], n_args - 1, args + 1, kw_args);
STATIC mp_obj_t pyb_i2c_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_init_args) - 1];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_i2c_init_args[1], args);
return pyb_i2c_init_helper(pos_args[0], args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_init_obj, 1, pyb_i2c_init);
/// \method deinit()
/// Turn off the I2C bus.
STATIC mp_obj_t pyb_i2c_deinit(mp_obj_t self_in) {
// disable the peripheral
MAP_I2CMasterDisable(I2CA0_BASE);
@@ -335,28 +356,13 @@ STATIC mp_obj_t pyb_i2c_deinit(mp_obj_t self_in) {
// invalidate the baudrate
pyb_i2c_obj.baudrate = 0;
// unregister it with the sleep module
pybsleep_remove ((const mp_obj_t)self_in);
pyb_sleep_remove ((const mp_obj_t)self_in);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_deinit_obj, pyb_i2c_deinit);
/// \method is_ready(addr)
/// Check if an I2C device responds to the given address. Only valid when in master mode.
STATIC mp_obj_t pyb_i2c_is_ready(mp_obj_t self_in, mp_obj_t i2c_addr_o) {
mp_uint_t i2c_addr = mp_obj_get_int(i2c_addr_o);
for (int i = 0; i < 7; i++) {
if (pyb_i2c_scan_device(i2c_addr)) {
return mp_const_true;
}
}
return mp_const_false;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_is_ready_obj, pyb_i2c_is_ready);
/// \method scan()
/// Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond.
/// Only valid when in master mode.
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++) {
@@ -366,193 +372,153 @@ STATIC mp_obj_t pyb_i2c_scan(mp_obj_t self_in) {
}
}
}
return list;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_scan_obj, pyb_i2c_scan);
/// \method send(send, addr=0x00)
/// Send data on the bus:
///
/// - `send` is the data to send (an integer to send, or a buffer object)
/// - `addr` is the address to send to (only required in master mode)
/// Return value: `None`.
STATIC const mp_arg_t pyb_i2c_send_args[] = {
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_addr, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
#define PYB_I2C_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_send_args)
STATIC mp_obj_t pyb_i2c_readfrom(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC const mp_arg_t pyb_i2c_readfrom_args[] = {
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_nbytes, MP_ARG_REQUIRED | MP_ARG_OBJ, },
};
STATIC mp_obj_t pyb_i2c_send(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t vals[PYB_I2C_SEND_NUM_ARGS];
mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_I2C_SEND_NUM_ARGS, pyb_i2c_send_args, vals);
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_readfrom_args, args);
vstr_t vstr;
pyb_i2c_read_into(args, &vstr);
// return the received data
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_obj, 3, pyb_i2c_readfrom);
STATIC mp_obj_t pyb_i2c_readfrom_into(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC const mp_arg_t pyb_i2c_readfrom_into_args[] = {
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, },
};
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_into_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_readfrom_into_args, args);
vstr_t vstr;
pyb_i2c_read_into(args, &vstr);
// return the number of bytes received
return mp_obj_new_int(vstr.len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_into_obj, 1, pyb_i2c_readfrom_into);
STATIC mp_obj_t pyb_i2c_writeto(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC const mp_arg_t pyb_i2c_writeto_args[] = {
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
};
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_writeto_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_writeto_args, args);
pyb_i2c_check_init(&pyb_i2c_obj);
// get the buffer to send from
mp_buffer_info_t bufinfo;
uint8_t data[1];
pyb_buf_get_for_send(vals[0].u_obj, &bufinfo, data);
pyb_buf_get_for_send(args[1].u_obj, &bufinfo, data);
// send the data
if (!pyb_i2c_write(vals[1].u_int, bufinfo.buf, bufinfo.len, true)) {
if (!pyb_i2c_write(args[0].u_int, bufinfo.buf, bufinfo.len, args[2].u_bool)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
return mp_const_none;
// return the number of bytes written
return mp_obj_new_int(bufinfo.len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_send_obj, 1, pyb_i2c_send);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_writeto_obj, 1, pyb_i2c_writeto);
/// \method recv(recv, addr=0x00)
///
/// Receive data on the bus:
///
/// - `recv` can be an integer, which is the number of bytes to receive,
/// or a mutable buffer, which will be filled with received bytes
/// - `addr` is the address to receive from (only required in master mode)
///
/// Return value: if `recv` is an integer then a new buffer of the bytes received,
/// otherwise the same buffer that was passed in to `recv`.
STATIC const mp_arg_t pyb_i2c_recv_args[] = {
{ MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_addr, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
#define PYB_I2C_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_recv_args)
STATIC mp_obj_t pyb_i2c_readfrom_mem(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC const mp_arg_t pyb_i2c_readfrom_mem_args[] = {
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_nbytes, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
};
STATIC mp_obj_t pyb_i2c_recv(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t vals[PYB_I2C_RECV_NUM_ARGS];
mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_I2C_RECV_NUM_ARGS, pyb_i2c_recv_args, vals);
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_mem_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_readfrom_mem_args, args);
// get the buffer to receive into
vstr_t vstr;
mp_obj_t o_ret = pyb_buf_get_for_recv(vals[0].u_obj, &vstr);
// receive the data
if (!pyb_i2c_read(vals[1].u_int, (byte *)vstr.buf, vstr.len)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
// return the received data
if (o_ret != MP_OBJ_NULL) {
return o_ret;
}
else {
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
pyb_i2c_readmem_into (args, &vstr);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_recv_obj, 1, pyb_i2c_recv);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_mem_obj, 1, pyb_i2c_readfrom_mem);
/// \method mem_read(data, addr, memaddr, addr_size=8)
///
/// Read from the memory of an I2C device:
///
/// - `data` can be an integer or a buffer to read into
/// - `addr` is the I2C device address
/// - `memaddr` is the memory location within the I2C device
/// - `addr_size` selects the width of memaddr: 8 or 16 bits
///
/// Returns the read data.
/// This is only valid in master mode.
STATIC const mp_arg_t pyb_i2c_mem_read_args[] = {
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
{ MP_QSTR_addr_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
STATIC const mp_arg_t pyb_i2c_readfrom_mem_into_args[] = {
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
};
#define PYB_I2C_MEM_READ_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_mem_read_args)
STATIC mp_obj_t pyb_i2c_mem_read(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
STATIC mp_obj_t pyb_i2c_readfrom_mem_into(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t vals[PYB_I2C_MEM_READ_NUM_ARGS];
mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_I2C_MEM_READ_NUM_ARGS, pyb_i2c_mem_read_args, vals);
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_mem_into_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), pyb_i2c_readfrom_mem_into_args, args);
// get the buffer to read into
vstr_t vstr;
mp_obj_t o_ret = pyb_buf_get_for_recv(vals[0].u_obj, &vstr);
// get the addresses
mp_uint_t i2c_addr = vals[1].u_int;
mp_uint_t mem_addr = vals[2].u_int;
// determine the width of mem_addr (1 or 2 bytes)
mp_uint_t mem_addr_size = vals[3].u_int >> 3;
// Write the register address to be read from.
if (pyb_i2c_write (i2c_addr, (byte *)&mem_addr, mem_addr_size, false)) {
// Read the specified length of data
if (pyb_i2c_read (i2c_addr, (byte *)vstr.buf, vstr.len)) {
// return the read data
if (o_ret != MP_OBJ_NULL) {
return o_ret;
} else {
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
}
}
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
return mp_const_none;
pyb_i2c_readmem_into (args, &vstr);
return mp_obj_new_int(vstr.len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_mem_read_obj, 1, pyb_i2c_mem_read);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_mem_into_obj, 1, pyb_i2c_readfrom_mem_into);
/// \method mem_write(data, addr, memaddr, addr_size=8)
///
/// Write to the memory of an I2C device:
///
/// - `data` can be an integer or a buffer to write from
/// - `addr` is the I2C device address
/// - `memaddr` is the memory location within the I2C device
/// - `addr_size` selects the width of memaddr: 8 or 16 bits
///
/// Returns `None`.
/// This is only valid in master mode.
STATIC mp_obj_t pyb_i2c_mem_write(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args (same as mem_read)
mp_arg_val_t vals[PYB_I2C_MEM_READ_NUM_ARGS];
mp_arg_parse_all(n_args - 1, args + 1, kw_args, PYB_I2C_MEM_READ_NUM_ARGS, pyb_i2c_mem_read_args, vals);
STATIC mp_obj_t pyb_i2c_writeto_mem(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_readfrom_mem_into_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(pyb_i2c_readfrom_mem_into_args), pyb_i2c_readfrom_mem_into_args, args);
pyb_i2c_check_init(&pyb_i2c_obj);
// get the buffer to write from
mp_buffer_info_t bufinfo;
uint8_t data[1];
pyb_buf_get_for_send(vals[0].u_obj, &bufinfo, data);
pyb_buf_get_for_send(args[2].u_obj, &bufinfo, data);
// get the addresses
mp_uint_t i2c_addr = vals[1].u_int;
mp_uint_t mem_addr = vals[2].u_int;
mp_uint_t i2c_addr = args[0].u_int;
mp_uint_t mem_addr = args[1].u_int;
// determine the width of mem_addr (1 or 2 bytes)
mp_uint_t mem_addr_size = vals[3].u_int >> 3;
mp_uint_t mem_addr_size = args[3].u_int >> 3;
// Write the register address to write to.
if (pyb_i2c_write (i2c_addr, (byte *)&mem_addr, mem_addr_size, false)) {
// Write the specified length of data
if (pyb_i2c_write (i2c_addr, bufinfo.buf, bufinfo.len, true)) {
return mp_const_none;
}
// write the register address to write to.
if (pyb_i2c_mem_write (i2c_addr, (byte *)&mem_addr, mem_addr_size, bufinfo.buf, bufinfo.len)) {
// return the number of bytes written
return mp_obj_new_int(bufinfo.len);
}
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_mem_write_obj, 1, pyb_i2c_mem_write);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_writeto_mem_obj, 1, pyb_i2c_writeto_mem);
STATIC const mp_map_elem_t pyb_i2c_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_i2c_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_i2c_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_is_ready), (mp_obj_t)&pyb_i2c_is_ready_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&pyb_i2c_scan_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_i2c_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_i2c_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_read), (mp_obj_t)&pyb_i2c_mem_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_write), (mp_obj_t)&pyb_i2c_mem_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_i2c_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_i2c_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&pyb_i2c_scan_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readfrom), (mp_obj_t)&pyb_i2c_readfrom_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readfrom_into), (mp_obj_t)&pyb_i2c_readfrom_into_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_writeto), (mp_obj_t)&pyb_i2c_writeto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readfrom_mem), (mp_obj_t)&pyb_i2c_readfrom_mem_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readfrom_mem_into), (mp_obj_t)&pyb_i2c_readfrom_mem_into_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_writeto_mem), (mp_obj_t)&pyb_i2c_writeto_mem_obj },
// class constants
/// \constant MASTER - for initialising the bus to master mode
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(PYBI2C_MASTER) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(PYBI2C_MASTER) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);

File diff suppressed because it is too large Load Diff

View File

@@ -28,26 +28,93 @@
#ifndef PYBPIN_H_
#define PYBPIN_H_
#define PYBPIN_ANALOG_TYPE 0xFF
enum {
PORT_A0 = GPIOA0_BASE,
PORT_A1 = GPIOA1_BASE,
PORT_A2 = GPIOA2_BASE,
PORT_A3 = GPIOA3_BASE,
};
enum {
PORT_A0 = GPIOA0_BASE,
PORT_A1 = GPIOA1_BASE,
PORT_A2 = GPIOA2_BASE,
PORT_A3 = GPIOA3_BASE
PIN_FN_UART = 0,
PIN_FN_SPI,
PIN_FN_I2S,
PIN_FN_I2C,
PIN_FN_TIM,
PIN_FN_SD,
PIN_FN_ADC,
};
enum {
PIN_TYPE_UART_TX = 0,
PIN_TYPE_UART_RX,
PIN_TYPE_UART_RTS,
PIN_TYPE_UART_CTS,
};
enum {
PIN_TYPE_SPI_CLK = 0,
PIN_TYPE_SPI_MOSI,
PIN_TYPE_SPI_MISO,
PIN_TYPE_SPI_CS0,
};
enum {
PIN_TYPE_I2S_CLK = 0,
PIN_TYPE_I2S_FS,
PIN_TYPE_I2S_DAT0,
PIN_TYPE_I2S_DAT1,
};
enum {
PIN_TYPE_I2C_SDA = 0,
PIN_TYPE_I2C_SCL,
};
enum {
PIN_TYPE_TIM_PWM0 = 0,
PIN_TYPE_TIM_PWM1,
PIN_TYPE_TIM_CC0,
PIN_TYPE_TIM_CC1,
};
enum {
PIN_TYPE_SD_CLK = 0,
PIN_TYPE_SD_CMD,
PIN_TYPE_SD_DAT0,
};
enum {
PIN_TYPE_ADC_CH0 = 0,
PIN_TYPE_ADC_CH1,
PIN_TYPE_ADC_CH2,
PIN_TYPE_ADC_CH3,
};
typedef struct {
qstr name;
int8_t idx;
uint8_t fn;
uint8_t unit;
uint8_t type;
} pin_af_t;
typedef struct {
const mp_obj_base_t base;
const qstr name;
const uint32_t port;
uint16_t type;
const pin_af_t *af_list;
uint16_t pull;
const uint8_t bit;
const uint8_t pin_num;
uint8_t af;
int8_t af;
uint8_t strength;
uint8_t mode;
bool isused;
uint8_t mode; // this is now a combination of type and mode
const uint8_t num_afs; // 255 AFs
uint8_t value;
uint8_t used;
uint8_t irq_trigger;
uint8_t irq_flags;
} pin_obj_t;
extern const mp_obj_type_t pin_type;
@@ -63,13 +130,14 @@ typedef struct {
const pin_named_pin_t *named_pins;
} pin_named_pins_obj_t;
extern const mp_obj_type_t pin_cpu_pins_obj_type;
extern const mp_obj_dict_t pin_cpu_pins_locals_dict;
extern const mp_obj_type_t pin_board_pins_obj_type;
extern const mp_obj_dict_t pin_board_pins_locals_dict;
void pin_init0(void);
void pin_config(pin_obj_t *self, uint af, uint mode, uint type, uint strength);
void pin_config(pin_obj_t *self, int af, uint mode, uint type, int value, uint strength);
pin_obj_t *pin_find(mp_obj_t user_obj);
pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name);
pin_obj_t *pin_find_pin_by_port_bit (const mp_obj_dict_t *named_pins, uint port, uint bit);
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);
#endif // PYBPIN_H_

View File

@@ -37,225 +37,438 @@
#include "rom_map.h"
#include "prcm.h"
#include "pybrtc.h"
#include "mpirq.h"
#include "pybsleep.h"
#include "mpcallback.h"
#include "timeutils.h"
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
#include "mpexception.h"
/// \moduleref pyb
/// \class RTC - real time clock
///
/// The RTC is and independent clock that keeps track of the date
/// and time.
///
/// Example usage:
///
/// rtc = pyb.RTC()
/// rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0))
/// print(rtc.datetime())
/******************************************************************************
DECLARE CONSTANTS
******************************************************************************/
#define PYBRTC_CLOCK_FREQUENCY_HZ 32768
#define PYBRTC_MIN_INTERVAL_VALUE 25
/******************************************************************************
DEFINE TYPES
******************************************************************************/
typedef struct {
byte prwmode;
} pybrtc_data_t;
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC pybrtc_data_t pybrtc_data;
STATIC const mp_cb_methods_t pybrtc_cb_methods;
STATIC const mp_obj_base_t pyb_rtc_obj = {&pyb_rtc_type};
STATIC const mp_irq_methods_t pyb_rtc_irq_methods;
STATIC pyb_rtc_obj_t pyb_rtc_obj;
/******************************************************************************
FUNCTION-LIKE MACROS
******************************************************************************/
#define RTC_U16MS_CYCLES(msec) ((msec * 1024) / 1000)
#define RTC_CYCLES_U16MS(cycles) ((cycles * 1000) / 1024)
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC void pyb_rtc_set_time (uint32_t secs, uint16_t msecs);
STATIC uint32_t pyb_rtc_reset (void);
STATIC void pyb_rtc_disable_interupt (void);
STATIC void pyb_rtc_irq_enable (mp_obj_t self_in);
STATIC void pyb_rtc_irq_disable (mp_obj_t self_in);
STATIC int pyb_rtc_irq_flags (mp_obj_t self_in);
STATIC uint pyb_rtc_datetime_s_us(const mp_obj_t datetime, uint32_t *seconds);
STATIC mp_obj_t pyb_rtc_datetime(mp_obj_t self, const mp_obj_t datetime);
STATIC void pyb_rtc_set_alarm (pyb_rtc_obj_t *self, uint32_t seconds, uint16_t mseconds);
STATIC void rtc_msec_add(uint16_t msecs_1, uint32_t *secs, uint16_t *msecs_2);
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
******************************************************************************/
__attribute__ ((section (".boot")))
void pybrtc_init(void) {
// if the RTC was previously set, leave it alone
void pyb_rtc_pre_init(void) {
// only if comming out of a power-on reset
if (MAP_PRCMSysResetCauseGet() == PRCM_POWER_ON) {
// fresh reset; configure the RTC Calendar
// set the date to 1st Jan 2015
// set the time to 00:00:00
uint32_t seconds = timeutils_seconds_since_2000(2015, 1, 1, 0, 0, 0);
// Mark the RTC in use first
MAP_PRCMRTCInUseSet();
// Now set the RTC calendar seconds
MAP_PRCMRTCSet(seconds, 0);
// reset the time and date
pyb_rtc_reset();
}
}
uint32_t pybrtc_get_seconds (void) {
void pyb_rtc_get_time (uint32_t *secs, uint16_t *msecs) {
uint16_t cycles;
MAP_PRCMRTCGet (secs, &cycles);
*msecs = RTC_CYCLES_U16MS(cycles);
}
uint32_t pyb_rtc_get_seconds (void) {
uint32_t seconds;
uint16_t mseconds;
MAP_PRCMRTCGet(&seconds, &mseconds);
pyb_rtc_get_time(&seconds, &mseconds);
return seconds;
}
void pyb_rtc_callback_disable (mp_obj_t self_in) {
// check the wake from param
if (pybrtc_data.prwmode & PYB_PWR_MODE_ACTIVE) {
// disable the slow clock interrupt
MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
void pyb_rtc_calc_future_time (uint32_t a_mseconds, uint32_t *f_seconds, uint16_t *f_mseconds) {
uint32_t c_seconds;
uint16_t c_mseconds;
// get the current time
pyb_rtc_get_time(&c_seconds, &c_mseconds);
// calculate the future seconds
*f_seconds = c_seconds + (a_mseconds / 1000);
// calculate the "remaining" future mseconds
*f_mseconds = a_mseconds % 1000;
// add the current milliseconds
rtc_msec_add (c_mseconds, f_seconds, f_mseconds);
}
void pyb_rtc_repeat_alarm (pyb_rtc_obj_t *self) {
if (self->repeat) {
uint32_t f_seconds, c_seconds;
uint16_t f_mseconds, c_mseconds;
pyb_rtc_get_time(&c_seconds, &c_mseconds);
// substract the time elapsed between waking up and setting up the alarm again
int32_t wake_ms = ((c_seconds * 1000) + c_mseconds) - ((self->alarm_time_s * 1000) + self->alarm_time_ms);
int32_t next_alarm = self->alarm_ms - wake_ms;
next_alarm = next_alarm > 0 ? next_alarm : PYB_RTC_MIN_ALARM_TIME_MS;
pyb_rtc_calc_future_time (next_alarm, &f_seconds, &f_mseconds);
// now configure the alarm
pyb_rtc_set_alarm (self, f_seconds, f_mseconds);
}
// disable wake from ldps and hibernate
pybsleep_configure_timer_wakeup (PYB_PWR_MODE_ACTIVE);
// read the interrupt status to clear any pending interrupt
(void)MAP_PRCMIntStatus();
}
void pyb_rtc_disable_alarm (void) {
pyb_rtc_obj.alarmset = false;
pyb_rtc_disable_interupt();
}
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC void pyb_rtc_callback_enable (mp_obj_t self_in) {
// check the wake from param
if (pybrtc_data.prwmode & PYB_PWR_MODE_ACTIVE) {
// enable the slow clock interrupt
STATIC void pyb_rtc_set_time (uint32_t secs, uint16_t msecs) {
// add the RTC access time
rtc_msec_add(RTC_ACCESS_TIME_MSEC, &secs, &msecs);
// convert from mseconds to cycles
msecs = RTC_U16MS_CYCLES(msecs);
// now set the time
MAP_PRCMRTCSet(secs, msecs);
}
STATIC uint32_t pyb_rtc_reset (void) {
// fresh reset; configure the RTC Calendar
// set the date to 1st Jan 2015
// set the time to 00:00:00
uint32_t seconds = timeutils_seconds_since_2000(2015, 1, 1, 0, 0, 0);
// disable any running alarm
pyb_rtc_disable_alarm();
// Now set the RTC calendar time
pyb_rtc_set_time(seconds, 0);
return seconds;
}
STATIC void pyb_rtc_disable_interupt (void) {
uint primsk = disable_irq();
MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
(void)MAP_PRCMIntStatus();
enable_irq(primsk);
}
STATIC void pyb_rtc_irq_enable (mp_obj_t self_in) {
pyb_rtc_obj_t *self = self_in;
// we always need interrupts if repeat is enabled
if ((self->pwrmode & PYB_PWR_MODE_ACTIVE) || self->repeat) {
MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR);
}
else {
// just in case it was already enabled before
} else { // just in case it was already enabled before
MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
}
pybsleep_configure_timer_wakeup (pybrtc_data.prwmode);
self->irq_enabled = true;
}
STATIC void pyb_rtc_irq_disable (mp_obj_t self_in) {
pyb_rtc_obj_t *self = self_in;
self->irq_enabled = false;
if (!self->repeat) { // we always need interrupts if repeat is enabled
pyb_rtc_disable_interupt();
}
}
STATIC int pyb_rtc_irq_flags (mp_obj_t self_in) {
pyb_rtc_obj_t *self = self_in;
return self->irq_flags;
}
STATIC uint pyb_rtc_datetime_s_us(const mp_obj_t datetime, uint32_t *seconds) {
timeutils_struct_time_t tm;
uint32_t useconds;
// set date and time
mp_obj_t *items;
uint len;
mp_obj_get_array(datetime, &len, &items);
// verify the tuple
if (len < 3 || len > 8) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
tm.tm_year = mp_obj_get_int(items[0]);
tm.tm_mon = mp_obj_get_int(items[1]);
tm.tm_mday = mp_obj_get_int(items[2]);
if (len < 7) {
useconds = 0;
} else {
useconds = mp_obj_get_int(items[6]);
}
if (len < 6) {
tm.tm_sec = 0;
} else {
tm.tm_sec = mp_obj_get_int(items[5]);
}
if (len < 5) {
tm.tm_min = 0;
} else {
tm.tm_min = mp_obj_get_int(items[4]);
}
if (len < 4) {
tm.tm_hour = 0;
} else {
tm.tm_hour = mp_obj_get_int(items[3]);
}
*seconds = timeutils_seconds_since_2000(tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
return useconds;
}
/// The 8-tuple has the same format as CPython's datetime object:
///
/// (year, month, day, hours, minutes, seconds, milliseconds, tzinfo=None)
///
STATIC mp_obj_t pyb_rtc_datetime(mp_obj_t self_in, const mp_obj_t datetime) {
uint32_t seconds;
uint32_t useconds;
if (datetime != MP_OBJ_NULL) {
useconds = pyb_rtc_datetime_s_us(datetime, &seconds);
pyb_rtc_set_time (seconds, useconds / 1000);
} else {
seconds = pyb_rtc_reset();
}
// set WLAN time and date, this is needed to verify certificates
wlan_set_current_time(seconds);
return mp_const_none;
}
STATIC void pyb_rtc_set_alarm (pyb_rtc_obj_t *self, uint32_t seconds, uint16_t mseconds) {
// disable the interrupt before updating anything
if (self->irq_enabled) {
MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
}
// set the match value
MAP_PRCMRTCMatchSet(seconds, RTC_U16MS_CYCLES(mseconds));
self->alarmset = true;
self->alarm_time_s = seconds;
self->alarm_time_ms = mseconds;
// enabled the interrupts again if applicable
if (self->irq_enabled || self->repeat) {
MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR);
}
}
STATIC void rtc_msec_add (uint16_t msecs_1, uint32_t *secs, uint16_t *msecs_2) {
if (msecs_1 + *msecs_2 >= 1000) { // larger than one second
*msecs_2 = (msecs_1 + *msecs_2) - 1000;
*secs += 1; // carry flag
} else {
// simply add the mseconds
*msecs_2 = msecs_1 + *msecs_2;
}
}
/******************************************************************************/
// Micro Python bindings
/// \classmethod \constructor()
/// Create an RTC object.
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) {
// check arguments
mp_arg_check_num(n_args, n_kw, 0, 0, false);
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) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_rtc_init_args)];
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_rtc_init_args, args);
// check the peripheral id
if (args[0].u_int != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
// setup the object
pyb_rtc_obj_t *self = &pyb_rtc_obj;
self->base.type = &pyb_rtc_type;
// set the time and date
pyb_rtc_datetime((mp_obj_t)&pyb_rtc_obj, args[1].u_obj);
// pass it to the sleep module
pyb_sleep_set_rtc_obj (self);
// return constant object
return (mp_obj_t)&pyb_rtc_obj;
}
/// \method datetime([datetimetuple])
/// Get or set the date and time of the RTC.
///
/// With no arguments, this method returns an 8-tuple with the current
/// date and time. With 1 argument (being an 8-tuple) it sets the date
/// and time.
///
/// The 8-tuple has the following format:
///
/// (year, month, day, weekday, hours, minutes, seconds, milliseconds)
///
/// `weekday` is 0-6 for Monday through Sunday.
///
mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
STATIC mp_obj_t pyb_rtc_init (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_rtc_init_args) - 1];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_rtc_init_args[1], args);
return pyb_rtc_datetime(pos_args[0], args[0].u_obj);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_init_obj, 1, pyb_rtc_init);
STATIC mp_obj_t pyb_rtc_now (mp_obj_t self_in) {
timeutils_struct_time_t tm;
uint32_t seconds;
uint16_t mseconds;
if (n_args == 1) {
// get the seconds and the milliseconds from the RTC
MAP_PRCMRTCGet(&seconds, &mseconds);
mseconds = RTC_CYCLES_U16MS(mseconds);
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
// get the time from the RTC
pyb_rtc_get_time(&seconds, &mseconds);
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
mp_obj_t tuple[8] = {
mp_obj_new_int(tm.tm_year),
mp_obj_new_int(tm.tm_mon),
mp_obj_new_int(tm.tm_mday),
mp_obj_new_int(tm.tm_wday),
mp_obj_new_int(tm.tm_hour),
mp_obj_new_int(tm.tm_min),
mp_obj_new_int(tm.tm_sec),
mp_obj_new_int(mseconds)
};
return mp_obj_new_tuple(8, tuple);
mp_obj_t tuple[8] = {
mp_obj_new_int(tm.tm_year),
mp_obj_new_int(tm.tm_mon),
mp_obj_new_int(tm.tm_mday),
mp_obj_new_int(tm.tm_hour),
mp_obj_new_int(tm.tm_min),
mp_obj_new_int(tm.tm_sec),
mp_obj_new_int(mseconds * 1000),
mp_const_none
};
return mp_obj_new_tuple(8, tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_rtc_now_obj, pyb_rtc_now);
STATIC mp_obj_t pyb_rtc_deinit (mp_obj_t self_in) {
pyb_rtc_reset();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_rtc_deinit_obj, pyb_rtc_deinit);
STATIC mp_obj_t pyb_rtc_alarm (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_id, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_time, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_repeat, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
};
// parse args
pyb_rtc_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(args), allowed_args, args);
// check the alarm id
if (args[0].u_int != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
uint32_t f_seconds;
uint16_t f_mseconds;
bool repeat = args[2].u_bool;
if (MP_OBJ_IS_TYPE(args[1].u_obj, &mp_type_tuple)) { // datetime tuple given
// repeat cannot be used with a datetime tuple
if (repeat) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
f_mseconds = pyb_rtc_datetime_s_us (args[1].u_obj, &f_seconds) / 1000;
} else { // then it must be an integer
self->alarm_ms = mp_obj_get_int(args[1].u_obj);
pyb_rtc_calc_future_time (self->alarm_ms, &f_seconds, &f_mseconds);
}
// store the repepat flag
self->repeat = repeat;
// now configure the alarm
pyb_rtc_set_alarm (self, f_seconds, f_mseconds);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_alarm_obj, 1, pyb_rtc_alarm);
STATIC mp_obj_t pyb_rtc_alarm_left (mp_uint_t n_args, const mp_obj_t *args) {
pyb_rtc_obj_t *self = args[0];
int32_t ms_left;
uint32_t c_seconds;
uint16_t c_mseconds;
// only alarm id 0 is available
if (n_args > 1 && mp_obj_get_int(args[1]) != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
// get the current time
pyb_rtc_get_time(&c_seconds, &c_mseconds);
// calculate the ms left
ms_left = ((self->alarm_time_s * 1000) + self->alarm_time_ms) - ((c_seconds * 1000) + c_mseconds);
if (!self->alarmset || ms_left < 0) {
ms_left = 0;
}
return mp_obj_new_int(ms_left);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_alarm_left_obj, 1, 2, pyb_rtc_alarm_left);
STATIC mp_obj_t pyb_rtc_alarm_cancel (mp_uint_t n_args, const mp_obj_t *args) {
// only alarm id 0 is available
if (n_args > 1 && mp_obj_get_int(args[1]) != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
// disable the alarm
pyb_rtc_disable_alarm();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_alarm_cancel_obj, 1, 2, pyb_rtc_alarm_cancel);
/// \method irq(trigger, priority, handler, wake)
STATIC mp_obj_t pyb_rtc_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);
pyb_rtc_obj_t *self = pos_args[0];
// save the power mode data for later
uint8_t pwrmode = (args[3].u_obj == mp_const_none) ? PYB_PWR_MODE_ACTIVE : mp_obj_get_int(args[3].u_obj);
if (pwrmode > (PYB_PWR_MODE_ACTIVE | PYB_PWR_MODE_LPDS | PYB_PWR_MODE_HIBERNATE)) {
goto invalid_args;
}
// check the trigger
if (mp_obj_get_int(args[0].u_obj) == PYB_RTC_ALARM0) {
self->pwrmode = pwrmode;
pyb_rtc_irq_enable((mp_obj_t)self);
} else {
// set date and time
mp_obj_t *items;
mp_obj_get_array_fixed_n(args[1], 8, &items);
tm.tm_year = mp_obj_get_int(items[0]);
tm.tm_mon = mp_obj_get_int(items[1]);
tm.tm_mday = mp_obj_get_int(items[2]);
// skip the weekday
tm.tm_hour = mp_obj_get_int(items[4]);
tm.tm_min = mp_obj_get_int(items[5]);
tm.tm_sec = mp_obj_get_int(items[6]);
mseconds = mp_obj_get_int(items[7]);
seconds = timeutils_seconds_since_2000(tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
mseconds = RTC_U16MS_CYCLES(mseconds);
MAP_PRCMRTCSet(seconds, mseconds);
// set WLAN time and date, this is needed to verify certificates
wlan_set_current_time(seconds);
return mp_const_none;
goto invalid_args;
}
// the interrupt priority is ignored since it's already set to to highest level by the sleep module
// to make sure that the wakeup irqs are always called first when resuming from sleep
// create the callback
mp_obj_t _irq = mp_irq_new ((mp_obj_t)self, args[2].u_obj, &pyb_rtc_irq_methods);
self->irq_obj = _irq;
return _irq;
invalid_args:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_datetime);
/// \method callback(handler, value, pwrmode)
/// Creates a callback object associated with the real time clock
/// min num of arguments is 1 (value). The value is the alarm time
/// in the future, in msec
STATIC mp_obj_t pyb_rtc_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_arg_val_t args[mpcallback_INIT_NUM_ARGS];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mpcallback_INIT_NUM_ARGS, mpcallback_init_args, args);
// check if any parameters were passed
mp_obj_t _callback = mpcallback_find((mp_obj_t)&pyb_rtc_obj);
if (kw_args->used > 0 || !_callback) {
uint32_t f_mseconds = MAX(1, args[3].u_int);
uint32_t seconds;
uint16_t mseconds;
// get the seconds and the milliseconds from the RTC
MAP_PRCMRTCGet(&seconds, &mseconds);
mseconds = RTC_CYCLES_U16MS(mseconds);
// configure the rtc alarm accordingly
seconds += f_mseconds / 1000;
mseconds += f_mseconds - ((f_mseconds / 1000) * 1000);
// disable the interrupt before updating anything
// (the object is not relevant here, the function already knows it)
pyb_rtc_callback_disable(NULL);
// set the match value
MAP_PRCMRTCMatchSet(seconds, mseconds);
// save the power mode data for later
pybrtc_data.prwmode = args[4].u_int;
// create the callback
_callback = mpcallback_new ((mp_obj_t)&pyb_rtc_obj, args[1].u_obj, &pybrtc_cb_methods);
// set the lpds callback
pybsleep_set_timer_lpds_callback(_callback);
// the interrupt priority is ignored since it's already set to to highest level by the sleep module
// to make sure that the wakeup callbacks are always called first when resuming from sleep
// enable the interrupt (the object is not relevant here, the function already knows it)
pyb_rtc_callback_enable(NULL);
}
return _callback;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_callback_obj, 1, pyb_rtc_callback);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_irq_obj, 1, pyb_rtc_irq);
STATIC const mp_map_elem_t pyb_rtc_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_datetime), (mp_obj_t)&pyb_rtc_datetime_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pyb_rtc_callback_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_rtc_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_rtc_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_now), (mp_obj_t)&pyb_rtc_now_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_alarm), (mp_obj_t)&pyb_rtc_alarm_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_alarm_left), (mp_obj_t)&pyb_rtc_alarm_left_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_alarm_cancel), (mp_obj_t)&pyb_rtc_alarm_cancel_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_rtc_irq_obj },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_ALARM0), MP_OBJ_NEW_SMALL_INT(PYB_RTC_ALARM0) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
@@ -266,8 +479,9 @@ const mp_obj_type_t pyb_rtc_type = {
.locals_dict = (mp_obj_t)&pyb_rtc_locals_dict,
};
STATIC const mp_cb_methods_t pybrtc_cb_methods = {
.init = pyb_rtc_callback,
.enable = pyb_rtc_callback_enable,
.disable = pyb_rtc_callback_disable,
STATIC const mp_irq_methods_t pyb_rtc_irq_methods = {
.init = pyb_rtc_irq,
.enable = pyb_rtc_irq_enable,
.disable = pyb_rtc_irq_disable,
.flags = pyb_rtc_irq_flags
};

View File

@@ -28,13 +28,32 @@
#ifndef PYBRTC_H_
#define PYBRTC_H_
#define RTC_U16MS_CYCLES(msec) ((msec * 1024) / 1000)
#define RTC_CYCLES_U16MS(cycles) ((cycles * 1000) / 1024)
// RTC triggers
#define PYB_RTC_ALARM0 (0x01)
#define RTC_ACCESS_TIME_MSEC (5)
#define PYB_RTC_MIN_ALARM_TIME_MS (RTC_ACCESS_TIME_MSEC * 2)
typedef struct _pyb_rtc_obj_t {
mp_obj_base_t base;
mp_obj_t irq_obj;
uint32_t irq_flags;
uint32_t alarm_ms;
uint32_t alarm_time_s;
uint16_t alarm_time_ms;
byte pwrmode;
bool alarmset;
bool repeat;
bool irq_enabled;
} pyb_rtc_obj_t;
extern const mp_obj_type_t pyb_rtc_type;
extern void pybrtc_init(void);
extern void pyb_rtc_callback_disable (mp_obj_t self_in);
extern uint32_t pybrtc_get_seconds (void);
extern void pyb_rtc_pre_init(void);
extern void pyb_rtc_get_time (uint32_t *secs, uint16_t *msecs);
extern uint32_t pyb_rtc_get_seconds (void);
extern void pyb_rtc_calc_future_time (uint32_t a_mseconds, uint32_t *f_seconds, uint16_t *f_mseconds);
extern void pyb_rtc_repeat_alarm (pyb_rtc_obj_t *self);
extern void pyb_rtc_disable_alarm (void);
#endif // PYBRTC_H_

View File

@@ -37,61 +37,46 @@
#include "prcm.h"
#include "gpio.h"
#include "sdhost.h"
#include "pybpin.h"
#include "pybsd.h"
#include "ff.h"
#include "diskio.h"
#include "sd_diskio.h"
#include "simplelink.h"
#include "debug.h"
#include "pybsd.h"
#include "mpexception.h"
#include "pybsleep.h"
#include "pybpin.h"
#include "pins.h"
#if MICROPY_HW_HAS_SDCARD
/******************************************************************************
DEFINE PRIVATE CONSTANTS
******************************************************************************/
#define PYBSD_FREQUENCY_HZ 15000000 // 15MHz
typedef struct {
mp_obj_base_t base;
FATFS *fatfs;
pin_obj_t *pin_clk;
bool pinsset;
bool enabled;
} pybsd_obj_t;
/******************************************************************************
DECLARE PUBLIC DATA
******************************************************************************/
pybsd_obj_t pybsd_obj;
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC pybsd_obj_t pybsd_obj;
STATIC const mp_obj_t pyb_sd_def_pin[3] = {&pin_GP10, &pin_GP11, &pin_GP15};
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC mp_obj_t pybsd_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 pybsd_disable (mp_obj_t self_in);
STATIC mp_obj_t pybsd_enable (mp_obj_t self_in);
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
__attribute__ ((section (".boot")))
void pybsd_init0 (void) {
// allocate memory for the sd file system
ASSERT ((pybsd_obj.fatfs = mem_Malloc(sizeof(FATFS))) != NULL);
}
void pybsd_deinit (void) {
pybsd_disable ((mp_obj_t)&pybsd_obj);
}
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_deinit (mp_obj_t self_in);
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
/// Initalizes the sd card driver
STATIC void pybsd_init (pybsd_obj_t *self) {
// Configure the clock pin as output only
MAP_PinDirModeSet(self->pin_clk->pin_num, PIN_DIR_MODE_OUT);
/// Initalizes the sd card hardware driver
STATIC void pyb_sd_hw_init (pybsd_obj_t *self) {
if (self->pin_clk) {
// Configure the clock pin as output only
MAP_PinDirModeSet(((pin_obj_t *)(self->pin_clk))->pin_num, PIN_DIR_MODE_OUT);
}
// Enable SD peripheral clock
MAP_PRCMPeripheralClkEnable(PRCM_SDHOST, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
// Reset MMCHS
@@ -100,110 +85,95 @@ STATIC void pybsd_init (pybsd_obj_t *self) {
MAP_SDHostInit(SDHOST_BASE);
// Configure the card clock
MAP_SDHostSetExpClk(SDHOST_BASE, MAP_PRCMPeripheralClockGet(PRCM_SDHOST), PYBSD_FREQUENCY_HZ);
// Set card rd/wr block len
MAP_SDHostBlockSizeSet(SDHOST_BASE, SD_SECTOR_SIZE);
self->enabled = true;
}
STATIC mp_obj_t pyb_sd_init_helper (pybsd_obj_t *self, const mp_arg_val_t *args) {
// assign the pins
mp_obj_t pins_o = args[0].u_obj;
if (pins_o != mp_const_none) {
mp_obj_t *pins;
if (pins_o == MP_OBJ_NULL) {
// use the default pins
pins = (mp_obj_t *)pyb_sd_def_pin;
} else {
mp_obj_get_array_fixed_n(pins_o, MP_ARRAY_SIZE(pyb_sd_def_pin), &pins);
}
pin_assign_pins_af (pins, MP_ARRAY_SIZE(pyb_sd_def_pin), PIN_TYPE_STD_PU, PIN_FN_SD, 0);
// save the pins clock
self->pin_clk = pin_find(pins[0]);
}
pyb_sd_hw_init (self);
if (sd_disk_init() != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
// register it with the sleep module
pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)pyb_sd_hw_init);
return mp_const_none;
}
/******************************************************************************/
// Micro Python bindings
//
/// \classmethod \constructor()
/// Configure the pins used for the sd card.
/// May receive 0, or 6 arguments.
///
/// Usage:
/// sd = pyb.SD()
////
/// sd = pyb.SD(d0_pin, d0_af, clk_pin, clk_af, cmd_pin, cmd_af)
///
STATIC mp_obj_t pybsd_make_new (mp_obj_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, 6, false);
if (n_args == 6) {
// save the clock pin for later use
pybsd_obj.pin_clk = (pin_obj_t *)pin_find(args[2]);
// configure the data pin with pull-up enabled
pin_config ((pin_obj_t *)pin_find(args[0]), mp_obj_get_int(args[1]), 0, PIN_TYPE_STD_PU, PIN_STRENGTH_4MA);
// configure the clock pin
pin_config (pybsd_obj.pin_clk, mp_obj_get_int(args[3]), 0, PIN_TYPE_STD, PIN_STRENGTH_4MA);
// configure the command pin with pull-up enabled
pin_config ((pin_obj_t *)pin_find(args[4]), mp_obj_get_int(args[5]), 0, PIN_TYPE_STD_PU, PIN_STRENGTH_4MA);
pybsd_obj.pinsset = true;
pybsd_obj.base.type = &pyb_sd_type;
}
else if (!pybsd_obj.pinsset) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, mpexception_num_type_invalid_arguments));
}
return &pybsd_obj;
}
/// \method enable()
/// Enables the sd card and mounts the file system
STATIC mp_obj_t pybsd_enable (mp_obj_t self_in) {
pybsd_obj_t *self = self_in;
if (!self->enabled) {
// do the init first
pybsd_init (self);
// try to mount the sd card on /sd
if (FR_OK != f_mount(self->fatfs, "/sd", 1)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd));
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd_slash_lib));
// register it with the sleep module
pybsleep_add ((const mp_obj_t)&pybsd_obj, (WakeUpCB_t)pybsd_init);
self->enabled = true;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pybsd_enable_obj, pybsd_enable);
/// \method disable()
/// Disables the sd card and unmounts the file system
STATIC mp_obj_t pybsd_disable (mp_obj_t self_in) {
pybsd_obj_t *self = self_in;
if (self->enabled) {
self->enabled = false;
// unmount the sd card
f_mount (NULL, "/sd", 1);
// remove sd paths from mp_sys_path
mp_obj_list_remove(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd));
mp_obj_list_remove(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_sd_slash_lib));
// disable the peripheral
MAP_PRCMPeripheralClkDisable(PRCM_SDHOST, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
// de-initialze de sd card at diskio level
sd_disk_deinit();
// unregister it with the sleep module
pybsleep_remove (self);
// change the drive in case it was /sd
f_chdrive("/flash");
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pybsd_disable_obj, pybsd_disable);
STATIC const mp_map_elem_t pybsd_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&pybsd_enable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&pybsd_disable_obj },
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_DEFINE_CONST_DICT(pybsd_locals_dict, pybsd_locals_dict_table);
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) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_sd_init_args)];
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_sd_init_args, args);
// check the peripheral id
if (args[0].u_int != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
// setup and initialize the object
mp_obj_t self = &pybsd_obj;
pybsd_obj.base.type = &pyb_sd_type;
pyb_sd_init_helper (self, &args[1]);
return self;
}
STATIC mp_obj_t pyb_sd_init (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_sd_init_args) - 1];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_sd_init_args[1], args);
return pyb_sd_init_helper(pos_args[0], args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_sd_init_obj, 1, pyb_sd_init);
STATIC mp_obj_t pyb_sd_deinit (mp_obj_t self_in) {
pybsd_obj_t *self = self_in;
// disable the peripheral
self->enabled = false;
MAP_PRCMPeripheralClkDisable(PRCM_SDHOST, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
// de-initialze the sd card at diskio level
sd_disk_deinit();
// unregister it from the sleep module
pyb_sleep_remove (self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sd_deinit_obj, pyb_sd_deinit);
STATIC const mp_map_elem_t pyb_sd_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_sd_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_sd_deinit_obj },
};
STATIC MP_DEFINE_CONST_DICT(pyb_sd_locals_dict, pyb_sd_locals_dict_table);
const mp_obj_type_t pyb_sd_type = {
{ &mp_type_type },
.name = MP_QSTR_SD,
.make_new = pybsd_make_new,
.locals_dict = (mp_obj_t)&pybsd_locals_dict,
.make_new = pyb_sd_make_new,
.locals_dict = (mp_obj_t)&pyb_sd_locals_dict,
};
#endif // MICROPY_HW_HAS_SDCARD

View File

@@ -26,11 +26,19 @@
#ifndef PYBSD_H_
#define PYBSD_H_
#if MICROPY_HW_HAS_SDCARD
/******************************************************************************
DEFINE PUBLIC TYPES
******************************************************************************/
typedef struct {
mp_obj_base_t base;
mp_obj_t pin_clk;
bool enabled;
} pybsd_obj_t;
/******************************************************************************
DECLARE EXPORTED DATA
******************************************************************************/
extern pybsd_obj_t pybsd_obj;
extern const mp_obj_type_t pyb_sd_type;
void pybsd_init0 (void);
void pybsd_deinit (void);
#endif
#endif // PYBSD_H_

View File

@@ -43,6 +43,7 @@
#include "spi.h"
#include "pin.h"
#include "pybsleep.h"
#include "mpirq.h"
#include "pybpin.h"
#include "simplelink.h"
#include "modnetwork.h"
@@ -50,11 +51,12 @@
#include "osi.h"
#include "debug.h"
#include "mpexception.h"
#include "mpcallback.h"
#include "mperror.h"
#include "sleeprestore.h"
#include "serverstask.h"
#include "antenna.h"
#include "cryptohash.h"
#include "pybrtc.h"
/******************************************************************************
DECLARE PRIVATE CONSTANTS
@@ -69,7 +71,7 @@
#define WAKEUP_TIME_LPDS (LPDS_UP_TIME + LPDS_DOWN_TIME + USER_OFFSET) // 20 msec
#define WAKEUP_TIME_HIB (32768) // 1 s
#define FORCED_TIMER_INTERRUPT_MS (1)
#define FORCED_TIMER_INTERRUPT_MS (PYB_RTC_MIN_ALARM_TIME_MS)
#define FAILED_SLEEP_DELAY_MS (FORCED_TIMER_INTERRUPT_MS * 3)
/******************************************************************************
@@ -109,35 +111,37 @@ typedef struct {
mp_obj_base_t base;
mp_obj_t obj;
WakeUpCB_t wakeup;
} pybsleep_obj_t;
} pyb_sleep_obj_t;
typedef struct {
mp_obj_t wlan_lpds_wake_cb;
mp_obj_t timer_lpds_wake_cb;
mp_obj_t gpio_lpds_wake_cb;
uint timer_wake_pwrmode;
mp_obj_t gpio_lpds_wake_cb;
wlan_obj_t *wlan_obj;
pyb_rtc_obj_t *rtc_obj;
} pybsleep_data_t;
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC const mp_obj_type_t pybsleep_type;
STATIC nvic_reg_store_t *nvic_reg_store;
STATIC pybsleep_data_t pybsleep_data = {NULL, NULL, NULL, 0};
STATIC pybsleep_data_t pybsleep_data = {NULL, NULL, NULL};
volatile arm_cm4_core_regs_t vault_arm_registers;
STATIC pybsleep_reset_cause_t pybsleep_reset_cause = PYB_SLP_PWRON_RESET;
STATIC pybsleep_wake_reason_t pybsleep_wake_reason = PYB_SLP_WAKED_PWRON;
STATIC const mp_obj_type_t pyb_sleep_type = {
{ &mp_type_type },
.name = MP_QSTR_sleep,
};
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC pybsleep_obj_t *pybsleep_find (mp_obj_t obj);
STATIC void pybsleep_flash_powerdown (void);
STATIC NORETURN void pybsleep_suspend_enter (void);
void pybsleep_suspend_exit (void);
STATIC void pybsleep_obj_wakeup (void);
STATIC pyb_sleep_obj_t *pyb_sleep_find (mp_obj_t obj);
STATIC void pyb_sleep_flash_powerdown (void);
STATIC NORETURN void pyb_sleep_suspend_enter (void);
void pyb_sleep_suspend_exit (void);
STATIC void pyb_sleep_obj_wakeup (void);
STATIC void PRCMInterruptHandler (void);
STATIC void pybsleep_iopark (bool hibernate);
STATIC void pyb_sleep_iopark (bool hibernate);
STATIC bool setup_timer_lpds_wake (void);
STATIC bool setup_timer_hibernate_wake (void);
@@ -145,14 +149,14 @@ STATIC bool setup_timer_hibernate_wake (void);
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
__attribute__ ((section (".boot")))
void pybsleep_pre_init (void) {
void pyb_sleep_pre_init (void) {
// allocate memory for nvic registers vault
ASSERT ((nvic_reg_store = mem_Malloc(sizeof(nvic_reg_store_t))) != NULL);
}
void pybsleep_init0 (void) {
void pyb_sleep_init0 (void) {
// initialize the sleep objects list
mp_obj_list_init(&MP_STATE_PORT(pybsleep_obj_list), 0);
mp_obj_list_init(&MP_STATE_PORT(pyb_sleep_obj_list), 0);
// register and enable the PRCM interrupt
osi_InterruptRegister(INT_PRCM, (P_OSI_INTR_ENTRY)PRCMInterruptHandler, INT_PRIORITY_LVL_1);
@@ -163,7 +167,7 @@ void pybsleep_init0 (void) {
MAP_PRCMHibernateWakeupSourceDisable(PRCM_HIB_SLOW_CLK_CTR | PRCM_HIB_GPIO2 | PRCM_HIB_GPIO4 | PRCM_HIB_GPIO13 |
PRCM_HIB_GPIO17 | PRCM_HIB_GPIO11 | PRCM_HIB_GPIO24 | PRCM_HIB_GPIO26);
// store the reset casue (if it's soft reset, leave it as it is)
// check the reset casue (if it's soft reset, leave it as it is)
if (pybsleep_reset_cause != PYB_SLP_SOFT_RESET) {
switch (MAP_PRCMSysResetCauseGet()) {
case PRCM_POWER_ON:
@@ -187,6 +191,7 @@ void pybsleep_init0 (void) {
switch (MAP_PRCMHibernateWakeupCauseGet()) {
case PRCM_HIB_WAKEUP_CAUSE_SLOW_CLOCK:
pybsleep_wake_reason = PYB_SLP_WAKED_BY_RTC;
// TODO repeat the alarm
break;
case PRCM_HIB_WAKEUP_CAUSE_GPIO:
pybsleep_wake_reason = PYB_SLP_WAKED_BY_GPIO;
@@ -202,55 +207,109 @@ void pybsleep_init0 (void) {
}
}
void pybsleep_signal_soft_reset (void) {
void pyb_sleep_signal_soft_reset (void) {
pybsleep_reset_cause = PYB_SLP_SOFT_RESET;
}
void pybsleep_add (const mp_obj_t obj, WakeUpCB_t wakeup) {
pybsleep_obj_t * sleep_obj = m_new_obj(pybsleep_obj_t);
sleep_obj->base.type = &pybsleep_type;
void pyb_sleep_add (const mp_obj_t obj, WakeUpCB_t wakeup) {
pyb_sleep_obj_t *sleep_obj = m_new_obj(pyb_sleep_obj_t);
sleep_obj->base.type = &pyb_sleep_type;
sleep_obj->obj = obj;
sleep_obj->wakeup = wakeup;
// only add objects once
if (!pybsleep_find(sleep_obj)) {
mp_obj_list_append(&MP_STATE_PORT(pybsleep_obj_list), sleep_obj);
// remove it in case it was already registered
pyb_sleep_remove (obj);
mp_obj_list_append(&MP_STATE_PORT(pyb_sleep_obj_list), sleep_obj);
}
void pyb_sleep_remove (const mp_obj_t obj) {
pyb_sleep_obj_t *sleep_obj;
if ((sleep_obj = pyb_sleep_find(obj))) {
mp_obj_list_remove(&MP_STATE_PORT(pyb_sleep_obj_list), sleep_obj);
}
}
void pybsleep_remove (const mp_obj_t obj) {
pybsleep_obj_t *sleep_obj;
if ((sleep_obj = pybsleep_find(obj))) {
mp_obj_list_remove(&MP_STATE_PORT(pybsleep_obj_list), sleep_obj);
}
}
void pybsleep_set_wlan_lpds_callback (mp_obj_t cb_obj) {
pybsleep_data.wlan_lpds_wake_cb = cb_obj;
}
void pybsleep_set_gpio_lpds_callback (mp_obj_t cb_obj) {
void pyb_sleep_set_gpio_lpds_callback (mp_obj_t cb_obj) {
pybsleep_data.gpio_lpds_wake_cb = cb_obj;
}
void pybsleep_set_timer_lpds_callback (mp_obj_t cb_obj) {
pybsleep_data.timer_lpds_wake_cb = cb_obj;
void pyb_sleep_set_wlan_obj (mp_obj_t wlan_obj) {
pybsleep_data.wlan_obj = (wlan_obj_t *)wlan_obj;
}
void pybsleep_configure_timer_wakeup (uint pwrmode) {
pybsleep_data.timer_wake_pwrmode = pwrmode;
void pyb_sleep_set_rtc_obj (mp_obj_t rtc_obj) {
pybsleep_data.rtc_obj = (pyb_rtc_obj_t *)rtc_obj;
}
pybsleep_reset_cause_t pybsleep_get_reset_cause (void) {
void pyb_sleep_sleep (void) {
nlr_buf_t nlr;
// check if we should enable timer wake-up
if (pybsleep_data.rtc_obj->irq_enabled && (pybsleep_data.rtc_obj->pwrmode & PYB_PWR_MODE_LPDS)) {
if (!setup_timer_lpds_wake()) {
// lpds entering is not possible, wait for the forced interrupt and return
HAL_Delay (FAILED_SLEEP_DELAY_MS);
return;
}
} else {
// disable the timer as wake source
MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER);
}
// do we need network wake-up?
if (pybsleep_data.wlan_obj->irq_enabled) {
MAP_PRCMLPDSWakeupSourceEnable (PRCM_LPDS_HOST_IRQ);
server_sleep_sockets();
} else {
MAP_PRCMLPDSWakeupSourceDisable (PRCM_LPDS_HOST_IRQ);
}
// entering and exiting suspended mode must be an atomic operation
// therefore interrupts need to be disabled
uint primsk = disable_irq();
if (nlr_push(&nlr) == 0) {
pyb_sleep_suspend_enter();
nlr_pop();
}
// an exception is always raised when exiting suspend mode
enable_irq(primsk);
}
void pyb_sleep_deepsleep (void) {
// check if we should enable timer wake-up
if (pybsleep_data.rtc_obj->irq_enabled && (pybsleep_data.rtc_obj->pwrmode & PYB_PWR_MODE_HIBERNATE)) {
if (!setup_timer_hibernate_wake()) {
// hibernating is not possible, wait for the forced interrupt and return
HAL_Delay (FAILED_SLEEP_DELAY_MS);
return;
}
} else {
// disable the timer as hibernate wake source
MAP_PRCMLPDSWakeupSourceDisable(PRCM_HIB_SLOW_CLK_CTR);
}
wlan_stop(SL_STOP_TIMEOUT);
pyb_sleep_flash_powerdown();
// must be done just before entering hibernate mode
pyb_sleep_iopark(true);
MAP_PRCMHibernateEnter();
}
pybsleep_reset_cause_t pyb_sleep_get_reset_cause (void) {
return pybsleep_reset_cause;
}
pybsleep_wake_reason_t pyb_sleep_get_wake_reason (void) {
return pybsleep_wake_reason;
}
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
STATIC pybsleep_obj_t *pybsleep_find (mp_obj_t obj) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(pybsleep_obj_list).len; i++) {
STATIC pyb_sleep_obj_t *pyb_sleep_find (mp_obj_t obj) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(pyb_sleep_obj_list).len; i++) {
// search for the object and then remove it
pybsleep_obj_t *sleep_obj = ((pybsleep_obj_t *)(MP_STATE_PORT(pybsleep_obj_list).items[i]));
pyb_sleep_obj_t *sleep_obj = ((pyb_sleep_obj_t *)(MP_STATE_PORT(pyb_sleep_obj_list).items[i]));
if (sleep_obj->obj == obj) {
return sleep_obj;
}
@@ -258,7 +317,7 @@ STATIC pybsleep_obj_t *pybsleep_find (mp_obj_t obj) {
return NULL;
}
STATIC void pybsleep_flash_powerdown (void) {
STATIC void pyb_sleep_flash_powerdown (void) {
uint32_t status;
// Enable clock for SSPI module
@@ -303,7 +362,7 @@ STATIC void pybsleep_flash_powerdown (void) {
MAP_SPICSDisable(SSPI_BASE);
}
STATIC NORETURN void pybsleep_suspend_enter (void) {
STATIC NORETURN void pyb_sleep_suspend_enter (void) {
// enable full RAM retention
MAP_PRCMSRAMRetentionEnable(PRCM_SRAM_COL_1 | PRCM_SRAM_COL_2 | PRCM_SRAM_COL_3 | PRCM_SRAM_COL_4, PRCM_SRAM_LPDS_RET);
@@ -340,7 +399,7 @@ STATIC NORETURN void pybsleep_suspend_enter (void) {
mperror_heartbeat_switch_off();
// park the gpio pins
pybsleep_iopark(false);
pyb_sleep_iopark(false);
// store the cpu registers
sleep_store();
@@ -353,7 +412,7 @@ STATIC NORETURN void pybsleep_suspend_enter (void) {
for ( ; ; );
}
void pybsleep_suspend_exit (void) {
void pyb_sleep_suspend_exit (void) {
// take the I2C semaphore
uint32_t reg = HWREG(COMMON_REG_BASE + COMMON_REG_O_I2C_Properties_Register);
reg = (reg & ~0x3) | 0x1;
@@ -407,10 +466,13 @@ void pybsleep_suspend_exit (void) {
sl_IfOpen (NULL, 0);
// restore the configuration of all active peripherals
pybsleep_obj_wakeup();
pyb_sleep_obj_wakeup();
// reconfigure all the previously enabled interrupts
mpcallback_wake_all();
mp_irq_wake_all();
// we need to init the crypto hash engine again
//CRYPTOHASH_Init();
// trigger a sw interrupt
MAP_IntPendSet(INT_PRCM);
@@ -422,25 +484,35 @@ void pybsleep_suspend_exit (void) {
STATIC void PRCMInterruptHandler (void) {
// reading the interrupt status automatically clears the interrupt
if (PRCM_INT_SLOW_CLK_CTR == MAP_PRCMIntStatus()) {
// this interrupt is triggered during active mode
mpcallback_handler(pybsleep_data.timer_lpds_wake_cb);
}
else {
// reconfigure it again (if repeat is true)
pyb_rtc_repeat_alarm (pybsleep_data.rtc_obj);
pybsleep_data.rtc_obj->irq_flags = PYB_RTC_ALARM0;
// need to check if irq's are enabled from the user point of view
if (pybsleep_data.rtc_obj->irq_enabled && (pybsleep_data.rtc_obj->pwrmode & PYB_PWR_MODE_ACTIVE)) {
mp_irq_handler(pybsleep_data.rtc_obj->irq_obj);
}
pybsleep_data.rtc_obj->irq_flags = 0;
} else {
// interrupt has been triggered while waking up from LPDS
switch (MAP_PRCMLPDSWakeupCauseGet()) {
case PRCM_LPDS_HOST_IRQ:
mpcallback_handler(pybsleep_data.wlan_lpds_wake_cb);
pybsleep_data.wlan_obj->irq_flags = MODWLAN_WIFI_EVENT_ANY;
mp_irq_handler(pybsleep_data.wlan_obj->irq_obj);
pybsleep_wake_reason = PYB_SLP_WAKED_BY_WLAN;
pybsleep_data.wlan_obj->irq_flags = 0;
break;
case PRCM_LPDS_GPIO:
mpcallback_handler(pybsleep_data.gpio_lpds_wake_cb);
mp_irq_handler(pybsleep_data.gpio_lpds_wake_cb);
pybsleep_wake_reason = PYB_SLP_WAKED_BY_GPIO;
break;
case PRCM_LPDS_TIMER:
// disable the timer as wake-up source
pybsleep_data.timer_wake_pwrmode &= ~PYB_PWR_MODE_LPDS;
// reconfigure it again if repeat is true
pyb_rtc_repeat_alarm (pybsleep_data.rtc_obj);
pybsleep_data.rtc_obj->irq_flags = PYB_RTC_ALARM0;
// next one clears the wake cause flag
MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER);
mpcallback_handler(pybsleep_data.timer_lpds_wake_cb);
mp_irq_handler(pybsleep_data.rtc_obj->irq_obj);
pybsleep_data.rtc_obj->irq_flags = 0;
pybsleep_wake_reason = PYB_SLP_WAKED_BY_RTC;
break;
default:
@@ -449,18 +521,17 @@ STATIC void PRCMInterruptHandler (void) {
}
}
STATIC void pybsleep_obj_wakeup (void) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(pybsleep_obj_list).len; i++) {
pybsleep_obj_t *sleep_obj = ((pybsleep_obj_t *)MP_STATE_PORT(pybsleep_obj_list).items[i]);
STATIC void pyb_sleep_obj_wakeup (void) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(pyb_sleep_obj_list).len; i++) {
pyb_sleep_obj_t *sleep_obj = ((pyb_sleep_obj_t *)MP_STATE_PORT(pyb_sleep_obj_list).items[i]);
sleep_obj->wakeup(sleep_obj->obj);
}
}
STATIC void pybsleep_iopark (bool hibernate) {
mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)&pin_cpu_pins_locals_dict);
STATIC void pyb_sleep_iopark (bool hibernate) {
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; i++) {
pin_obj_t * pin = (pin_obj_t *)named_map->table[i].value;
// skip the sflash pins since these are shared with the network processor
switch (pin->pin_num) {
#ifdef DEBUG
// skip the JTAG pins
@@ -471,9 +542,9 @@ STATIC void pybsleep_iopark (bool hibernate) {
break;
#endif
default:
// enable a weak pull-down if the pin is unused
if (!pin->isused) {
MAP_PinConfigSet(pin->pin_num, pin->strength, PIN_TYPE_STD_PD);
// enable a weak pull-up if the pin is unused
if (!pin->used) {
MAP_PinConfigSet(pin->pin_num, pin->strength, PIN_TYPE_STD_PU);
}
if (hibernate) {
// make it an input
@@ -515,191 +586,72 @@ STATIC void pybsleep_iopark (bool hibernate) {
}
STATIC bool setup_timer_lpds_wake (void) {
uint64_t t_match, t_curr, t_remaining;
uint64_t t_match, t_curr;
int64_t t_remaining;
// get the time remaining for the RTC timer to expire
t_match = MAP_PRCMSlowClkCtrMatchGet();
t_curr = MAP_PRCMSlowClkCtrGet();
if (t_match > t_curr) {
// get the time remaining in terms of slow clocks
t_remaining = (t_match - t_curr);
if (t_remaining > WAKEUP_TIME_LPDS) {
// subtract the time it takes for wakeup from lpds
t_remaining -= WAKEUP_TIME_LPDS;
t_remaining = (t_remaining > 0xFFFFFFFF) ? 0xFFFFFFFF: t_remaining;
// setup the LPDS wake time
MAP_PRCMLPDSIntervalSet((uint32_t)t_remaining);
// enable the wake source
MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_TIMER);
return true;
}
}
else {
// setup a timer interrupt immediately
MAP_PRCMRTCMatchSet(0, FORCED_TIMER_INTERRUPT_MS);
// get the time remaining in terms of slow clocks
t_remaining = (t_match - t_curr);
if (t_remaining > WAKEUP_TIME_LPDS) {
// subtract the time it takes to wakeup from lpds
t_remaining -= WAKEUP_TIME_LPDS;
t_remaining = (t_remaining > 0xFFFFFFFF) ? 0xFFFFFFFF: t_remaining;
// setup the LPDS wake time
MAP_PRCMLPDSIntervalSet((uint32_t)t_remaining);
// enable the wake source
MAP_PRCMLPDSWakeupSourceEnable(PRCM_LPDS_TIMER);
return true;
}
// disable the timer as wake source
MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER);
// LPDS wake by timer was not possible, force
// an interrupt in active mode instead
uint32_t f_seconds;
uint16_t f_mseconds;
// setup a timer interrupt immediately
pyb_rtc_calc_future_time (FORCED_TIMER_INTERRUPT_MS, &f_seconds, &f_mseconds);
MAP_PRCMRTCMatchSet(f_seconds, f_mseconds);
// LPDS wake by timer was not possible, force an interrupt in active mode instead
MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR);
return false;
}
STATIC bool setup_timer_hibernate_wake (void) {
uint64_t t_match, t_curr, t_remaining;
uint64_t t_match, t_curr;
int64_t t_remaining;
// get the time remaining for the RTC timer to expire
t_match = MAP_PRCMSlowClkCtrMatchGet();
t_curr = MAP_PRCMSlowClkCtrGet();
if (t_match > t_curr) {
// get the time remaining in terms of slow clocks
t_remaining = (t_match - t_curr);
if (t_remaining > WAKEUP_TIME_HIB) {
// subtract the time it takes for wakeup from hibernate
t_remaining -= WAKEUP_TIME_HIB;
// setup the LPDS wake time
MAP_PRCMHibernateIntervalSet((uint32_t)t_remaining);
// enable the wake source
MAP_PRCMHibernateWakeupSourceEnable(PRCM_HIB_SLOW_CLK_CTR);
return true;
}
}
else {
// setup a timer interrupt immediately
MAP_PRCMRTCMatchSet(0, FORCED_TIMER_INTERRUPT_MS);
// get the time remaining in terms of slow clocks
t_remaining = (t_match - t_curr);
if (t_remaining > WAKEUP_TIME_HIB) {
// subtract the time it takes for wakeup from hibernate
t_remaining -= WAKEUP_TIME_HIB;
// setup the LPDS wake time
MAP_PRCMHibernateIntervalSet((uint32_t)t_remaining);
// enable the wake source
MAP_PRCMHibernateWakeupSourceEnable(PRCM_HIB_SLOW_CLK_CTR);
return true;
}
// disable the timer as wake source
MAP_PRCMLPDSWakeupSourceDisable(PRCM_HIB_SLOW_CLK_CTR);
// hibernate wake by timer was not possible, force
// an interrupt in active mode instead
uint32_t f_seconds;
uint16_t f_mseconds;
// setup a timer interrupt immediately
pyb_rtc_calc_future_time (FORCED_TIMER_INTERRUPT_MS, &f_seconds, &f_mseconds);
MAP_PRCMRTCMatchSet(f_seconds, f_mseconds);
// LPDS wake by timer was not possible, force an interrupt in active mode instead
MAP_PRCMIntEnable(PRCM_INT_SLOW_CLK_CTR);
return false;
}
/******************************************************************************/
// Micro Python bindings; Sleep class
/// \function idle()
/// Gates the processor clock until an interrupt is triggered
STATIC mp_obj_t pyb_sleep_idle (mp_obj_t self_in) {
__WFI();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sleep_idle_obj, pyb_sleep_idle);
/// \function suspend(wlan)
/// Enters suspended mode. Wake up sources should have been enable prior to
/// calling this method.
STATIC mp_obj_t pyb_sleep_suspend (mp_obj_t self_in) {
nlr_buf_t nlr;
// check if we should enable timer wake-up
if (pybsleep_data.timer_wake_pwrmode & PYB_PWR_MODE_LPDS) {
if (!setup_timer_lpds_wake()) {
// lpds entering is not possible, wait for the forced interrupt and return
pybsleep_data.timer_wake_pwrmode &= ~PYB_PWR_MODE_LPDS;
HAL_Delay (FAILED_SLEEP_DELAY_MS);
return mp_const_none;
}
}
// do we need network wake-up?
if (pybsleep_data.wlan_lpds_wake_cb) {
MAP_PRCMLPDSWakeupSourceEnable (PRCM_LPDS_HOST_IRQ);
server_sleep_sockets();
}
else {
MAP_PRCMLPDSWakeupSourceDisable (PRCM_LPDS_HOST_IRQ);
}
// entering and exiting suspended mode must be an atomic operation
// therefore interrupts need to be disabled
uint primsk = disable_irq();
if (nlr_push(&nlr) == 0) {
pybsleep_suspend_enter();
nlr_pop();
}
// an exception is always raised when exiting suspend mode
enable_irq(primsk);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sleep_suspend_obj, pyb_sleep_suspend);
/// \function hibernate()
/// Enters hibernate mode. Wake up sources should have been enable prior to
/// calling this method.
STATIC mp_obj_t pyb_sleep_hibernate (mp_obj_t self_in) {
// check if we should enable timer wake-up
if (pybsleep_data.timer_wake_pwrmode & PYB_PWR_MODE_HIBERNATE) {
if (!setup_timer_hibernate_wake()) {
// hibernating is not possible, wait for the forced interrupt and return
pybsleep_data.timer_wake_pwrmode &= ~PYB_PWR_MODE_HIBERNATE;
HAL_Delay (FAILED_SLEEP_DELAY_MS);
return mp_const_none;
}
}
wlan_stop(SL_STOP_TIMEOUT);
pybsleep_flash_powerdown();
// must be done just before entering hibernate mode
pybsleep_iopark(true);
MAP_PRCMHibernateEnter();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sleep_hibernate_obj, pyb_sleep_hibernate);
/// \function reset_cause()
/// Returns the last reset casue
STATIC mp_obj_t pyb_sleep_reset_cause (mp_obj_t self_in) {
return MP_OBJ_NEW_SMALL_INT(pybsleep_reset_cause);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sleep_reset_cause_obj, pyb_sleep_reset_cause);
/// \function wake_reason()
/// Returns the wake up reson from ldps or hibernate
STATIC mp_obj_t pyb_sleep_wake_reason (mp_obj_t self_in) {
return MP_OBJ_NEW_SMALL_INT(pybsleep_wake_reason);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sleep_wake_reason_obj, pyb_sleep_wake_reason);
STATIC const mp_map_elem_t pybsleep_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_idle), (mp_obj_t)&pyb_sleep_idle_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_suspend), (mp_obj_t)&pyb_sleep_suspend_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_hibernate), (mp_obj_t)&pyb_sleep_hibernate_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_reset_cause), (mp_obj_t)&pyb_sleep_reset_cause_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wake_reason), (mp_obj_t)&pyb_sleep_wake_reason_obj },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_ACTIVE), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_ACTIVE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SUSPENDED), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_LPDS) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HIBERNATING), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_HIBERNATE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_POWER_ON), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HARD_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HARD_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WDT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WDT_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HIB_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HIB_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOFT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_SOFT_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WLAN_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_WLAN) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PIN_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_GPIO) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RTC_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_RTC) },
};
STATIC MP_DEFINE_CONST_DICT(pybsleep_locals_dict, pybsleep_locals_dict_table);
STATIC const mp_obj_type_t pybsleep_type = {
{ &mp_type_type },
.name = MP_QSTR_Sleep,
.locals_dict = (mp_obj_t)&pybsleep_locals_dict,
};
const mp_obj_base_t pyb_sleep_obj = {&pybsleep_type};

View File

@@ -54,23 +54,20 @@ typedef enum {
typedef void (*WakeUpCB_t)(const mp_obj_t self);
/******************************************************************************
DECLARE EXPORTED VARIABLES
******************************************************************************/
extern const mp_obj_base_t pyb_sleep_obj;
/******************************************************************************
DECLARE FUNCTIONS
******************************************************************************/
void pybsleep_pre_init (void);
void pybsleep_init0 (void);
void pybsleep_signal_soft_reset (void);
void pybsleep_add (const mp_obj_t obj, WakeUpCB_t wakeup);
void pybsleep_remove (const mp_obj_t obj);
void pybsleep_set_wlan_lpds_callback (mp_obj_t cb_obj);
void pybsleep_set_gpio_lpds_callback (mp_obj_t cb_obj);
void pybsleep_set_timer_lpds_callback (mp_obj_t cb_obj);
void pybsleep_configure_timer_wakeup (uint pwrmode);
pybsleep_reset_cause_t pybsleep_get_reset_cause (void);
void pyb_sleep_pre_init (void);
void pyb_sleep_init0 (void);
void pyb_sleep_signal_soft_reset (void);
void pyb_sleep_add (const mp_obj_t obj, WakeUpCB_t wakeup);
void pyb_sleep_remove (const mp_obj_t obj);
void pyb_sleep_set_gpio_lpds_callback (mp_obj_t cb_obj);
void pyb_sleep_set_wlan_obj (mp_obj_t wlan_obj);
void pyb_sleep_set_rtc_obj (mp_obj_t rtc_obj);
void pyb_sleep_sleep (void);
void pyb_sleep_deepsleep (void);
pybsleep_reset_cause_t pyb_sleep_get_reset_cause (void);
pybsleep_wake_reason_t pyb_sleep_get_wake_reason (void);
#endif /* PYBSLEEP_H_ */

View File

@@ -43,28 +43,11 @@
#include "pybspi.h"
#include "mpexception.h"
#include "pybsleep.h"
#include "pybpin.h"
#include "pins.h"
/// \moduleref pyb
/// \class SPI - a master-driven serial protocol
///
/// SPI is a serial protocol that is driven by a master. At the physical level
/// there are 3 lines: SCK, MOSI, MISO.
///
/// See usage model of I2C; SPI is very similar. Main difference is
/// parameters to init the SPI bus:
///
/// from pyb import SPI
/// spi = SPI(1, SPI.MASTER, baudrate=2000000, bits=8, polarity=0, phase=0, nss=SPI.ACTIVE_LOW)
///
/// Only required parameter is the baudrate, in Hz. polarity and phase may be 0 or 1.
/// Bit accepts 8, 16, 32. Chip select values are ACTIVE_LOW and ACTIVE_HIGH
///
/// Additional method for SPI:
///
/// data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes
/// buf = bytearray(4)
/// spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf
/// spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf
/******************************************************************************
DEFINE TYPES
@@ -73,10 +56,6 @@ typedef struct _pyb_spi_obj_t {
mp_obj_base_t base;
uint baudrate;
uint config;
vstr_t tx_vstr;
vstr_t rx_vstr;
uint tx_index;
uint rx_index;
byte polarity;
byte phase;
byte submode;
@@ -86,13 +65,15 @@ typedef struct _pyb_spi_obj_t {
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
#define PYBSPI_DEF_BAUDRATE 1000000 // 1MHz
#define PYBSPI_FIRST_BIT_MSB 0
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC pyb_spi_obj_t pyb_spi_obj = {.baudrate = 0};
STATIC const mp_obj_t pyb_spi_def_pin[3] = {&pin_GP14, &pin_GP16, &pin_GP30};
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
@@ -112,21 +93,19 @@ STATIC void pybspi_init (const pyb_spi_obj_t *self) {
}
STATIC void pybspi_tx (pyb_spi_obj_t *self, const void *data) {
uint32_t txdata = 0xFFFFFFFF;
if (data) {
switch (self->wlen) {
case 1:
txdata = (uint8_t)(*(char *)data);
break;
case 2:
txdata = (uint16_t)(*(uint16_t *)data);
break;
case 4:
txdata = (uint32_t)(*(uint32_t *)data);
break;
default:
return;
}
uint32_t txdata;
switch (self->wlen) {
case 1:
txdata = (uint8_t)(*(char *)data);
break;
case 2:
txdata = (uint16_t)(*(uint16_t *)data);
break;
case 4:
txdata = (uint32_t)(*(uint32_t *)data);
break;
default:
return;
}
MAP_SPIDataPut (GSPI_BASE, txdata);
}
@@ -151,11 +130,14 @@ STATIC void pybspi_rx (pyb_spi_obj_t *self, void *data) {
}
}
STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxdata, uint32_t len) {
STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxdata, uint32_t len, uint32_t *txchar) {
if (!self->baudrate) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
// send and receive the data
MAP_SPICSEnable(GSPI_BASE);
for (int i = 0; i < len / self->wlen; i += self->wlen) {
pybspi_tx(self, txdata ? (const void *)&txdata[i] : NULL);
for (int i = 0; i < len; i += self->wlen) {
pybspi_tx(self, txdata ? (const void *)&txdata[i] : txchar);
pybspi_rx(self, rxdata ? (void *)&rxdata[i] : NULL);
}
MAP_SPICSDisable(GSPI_BASE);
@@ -166,40 +148,15 @@ STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxda
/******************************************************************************/
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 = self_in;
if (self->baudrate > 0) {
mp_printf(print, "<SPI1, SPI.MASTER, baudrate=%u, bits=%u, polarity=%u, phase=%u, nss=%q>",
self->baudrate, (self->wlen * 8), self->polarity, self->phase,
(self->config & SPI_CS_ACTIVELOW) ? MP_QSTR_ACTIVE_LOW : MP_QSTR_ACTIVE_HIGH);
mp_printf(print, "SPI(0, SPI.MASTER, baudrate=%u, bits=%u, polarity=%u, phase=%u, firstbit=SPI.MSB)",
self->baudrate, (self->wlen * 8), self->polarity, self->phase);
} else {
mp_print_str(print, "<SPI1>");
mp_print_str(print, "SPI(0)");
}
}
/// \method init(mode, *, baudrate=1000000, bits=8, polarity=0, phase=0, nss=SPI.ACTIVE_LOW)
///
/// Initialise the SPI bus with the given parameters:
///
/// - `mode` must be MASTER.
/// - `baudrate` is the SCK clock rate.
/// - `bits` is the transfer width size (8, 16, 32).
/// - `polarity` (0, 1).
/// - `phase` (0, 1).
/// - `nss` can be ACTIVE_LOW or ACTIVE_HIGH.
static const mp_arg_t pybspi_init_args[] = {
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYBSPI_DEF_BAUDRATE} },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_nss, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_CS_ACTIVELOW} },
};
STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(pybspi_init_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(pybspi_init_args), pybspi_init_args, args);
STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, const mp_arg_val_t *args) {
// verify that mode is master
if (args[0].u_int != SPI_MODE_MASTER) {
goto invalid_args;
@@ -227,24 +184,37 @@ STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, mp_uint_t n_args, const
goto invalid_args;
}
uint nss = args[5].u_int;
if (nss != SPI_CS_ACTIVELOW && nss != SPI_CS_ACTIVEHIGH) {
uint firstbit = args[5].u_int;
if (firstbit != PYBSPI_FIRST_BIT_MSB) {
goto invalid_args;
}
// build the configuration
self->baudrate = args[1].u_int;
self->wlen = args[2].u_int >> 3;
self->config = bits | nss | SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF;
self->config = bits | SPI_CS_ACTIVELOW | SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF;
self->polarity = polarity;
self->phase = phase;
self->submode = (polarity << 1) | phase;
// assign the pins
mp_obj_t pins_o = args[6].u_obj;
if (pins_o != mp_const_none) {
mp_obj_t *pins;
if (pins_o == MP_OBJ_NULL) {
// use the default pins
pins = (mp_obj_t *)pyb_spi_def_pin;
} else {
mp_obj_get_array_fixed_n(pins_o, 3, &pins);
}
pin_assign_pins_af (pins, 3, PIN_TYPE_STD_PU, PIN_FN_SPI, 0);
}
// init the bus
pybspi_init((const pyb_spi_obj_t *)self);
// register it with the sleep module
pybsleep_add((const mp_obj_t)self, (WakeUpCB_t)pybspi_init);
pyb_sleep_add((const mp_obj_t)self, (WakeUpCB_t)pybspi_init);
return mp_const_none;
@@ -252,32 +222,43 @@ invalid_args:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
/// \classmethod \constructor(bus, ...)
///
/// Construct an SPI object with the given baudrate. Bus can only be 1.
/// With no extra 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.
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 *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
static const mp_arg_t pyb_spi_init_args[] = {
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_mode, MP_ARG_INT, {.u_int = SPI_MODE_MASTER} },
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000000} }, // 1MHz
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ 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) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_spi_init_args)];
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_spi_init_args, args);
// check the peripheral id
if (args[0].u_int != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
// setup the object
pyb_spi_obj_t *self = &pyb_spi_obj;
self->base.type = &pyb_spi_type;
if (n_args > 1 || n_kw > 0) {
// start the peripheral
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
pyb_spi_init_helper(self, n_args - 1, args + 1, &kw_args);
}
// start the peripheral
pyb_spi_init_helper(self, &args[1]);
return self;
}
STATIC mp_obj_t pyb_spi_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
return pyb_spi_init_helper(args[0], n_args - 1, args + 1, kw_args);
STATIC mp_obj_t pyb_spi_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_spi_init_args) - 1];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_spi_init_args[1], args);
return pyb_spi_init_helper(pos_args[0], args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_init_obj, 1, pyb_spi_init);
@@ -290,157 +271,117 @@ STATIC mp_obj_t pyb_spi_deinit(mp_obj_t self_in) {
// invalidate the baudrate
pyb_spi_obj.baudrate = 0;
// unregister it with the sleep module
pybsleep_remove((const mp_obj_t)self_in);
pyb_sleep_remove((const mp_obj_t)self_in);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_spi_deinit_obj, pyb_spi_deinit);
/// \method send(send, *, timeout=5000)
/// Send data on the bus:
///
/// - `send` is the data to send (a byte to send, or a buffer object).
/// - `timeout` is the timeout in milliseconds to wait for the send.
///
STATIC mp_obj_t pyb_spi_send (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_send, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
STATIC mp_obj_t pyb_spi_write (mp_obj_t self_in, mp_obj_t buf) {
// parse args
pyb_spi_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);
pyb_spi_obj_t *self = self_in;
// get the buffer to send from
mp_buffer_info_t bufinfo;
uint8_t data[1];
pyb_buf_get_for_send(args[0].u_obj, &bufinfo, data);
pyb_buf_get_for_send(buf, &bufinfo, data);
// just send
pybspi_transfer(self, (const char *)bufinfo.buf, NULL, bufinfo.len);
pybspi_transfer(self, (const char *)bufinfo.buf, NULL, bufinfo.len, NULL);
return mp_const_none;
// return the number of bytes written
return mp_obj_new_int(bufinfo.len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_send_obj, 1, pyb_spi_send);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_spi_write_obj, pyb_spi_write);
/// \method recv(recv, *, timeout=5000)
///
/// Receive data on the bus:
///
/// - `recv` can be an integer, which is the number of bytes to receive,
/// or a mutable buffer, which will be filled with received bytes.
/// - `timeout` is the timeout in milliseconds to wait for the receive.
///
/// Return: if `recv` is an integer then a new buffer of the bytes received,
/// otherwise the same buffer that was passed in to `recv`.
STATIC mp_obj_t pyb_spi_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC mp_obj_t pyb_spi_read(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_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
{ MP_QSTR_nbytes, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_write, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x00} },
};
// parse args
pyb_spi_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);
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), allowed_args, args);
// get the buffer to receive into
vstr_t vstr;
mp_obj_t o_ret = pyb_buf_get_for_recv(args[0].u_obj, &vstr);
pyb_buf_get_for_recv(args[0].u_obj, &vstr);
// just receive
pybspi_transfer(self, NULL, vstr.buf, vstr.len);
uint32_t write = args[1].u_int;
pybspi_transfer(self, NULL, vstr.buf, vstr.len, &write);
// return the received data
if (o_ret != MP_OBJ_NULL) {
return o_ret;
} else {
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_recv_obj, 1, pyb_spi_recv);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_read_obj, 1, pyb_spi_read);
/// \method send_recv(send, recv=None, *, timeout=5000)
///
/// Send and receive data on the bus at the same time:
///
/// - `send` is the data to send (an integer to send, or a buffer object).
/// - `recv` is a mutable buffer which will be filled with received bytes.
/// It can be the same as `send`, or omitted. If omitted, a new buffer will
/// be created.
/// - `timeout` is the timeout in milliseconds to wait for the transaction to complete.
///
/// Return: the buffer with the received bytes.
STATIC mp_obj_t pyb_spi_send_recv (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC mp_obj_t pyb_spi_readinto(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_send, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_recv, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_write, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x00} },
};
// parse args
pyb_spi_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);
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), allowed_args, args);
// get buffers to send from/receive to
mp_buffer_info_t bufinfo_send;
// get the buffer to receive into
vstr_t vstr;
pyb_buf_get_for_recv(args[0].u_obj, &vstr);
// just receive
uint32_t write = args[1].u_int;
pybspi_transfer(self, NULL, vstr.buf, vstr.len, &write);
// return the number of bytes received
return mp_obj_new_int(vstr.len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_readinto_obj, 1, pyb_spi_readinto);
STATIC mp_obj_t pyb_spi_write_readinto (mp_obj_t self, mp_obj_t writebuf, mp_obj_t readbuf) {
// get buffers to write from/read to
mp_buffer_info_t bufinfo_write;
uint8_t data_send[1];
mp_buffer_info_t bufinfo_recv;
vstr_t vstr_recv;
mp_obj_t o_ret;
mp_buffer_info_t bufinfo_read;
if (args[0].u_obj == args[1].u_obj) {
// same object for sending and receiving, it must be a r/w buffer
mp_get_buffer_raise(args[0].u_obj, &bufinfo_send, MP_BUFFER_RW);
bufinfo_recv = bufinfo_send;
o_ret = args[0].u_obj;
if (writebuf == readbuf) {
// same object for writing and reading, it must be a r/w buffer
mp_get_buffer_raise(writebuf, &bufinfo_write, MP_BUFFER_RW);
bufinfo_read = bufinfo_write;
} else {
// get the buffer to send from
pyb_buf_get_for_send(args[0].u_obj, &bufinfo_send, data_send);
// get the buffer to write from
pyb_buf_get_for_send(writebuf, &bufinfo_write, data_send);
// get the buffer to receive into
if (args[1].u_obj == mp_const_none) {
// only the send was argument given, so create a fresh buffer of the send length
vstr_init_len(&vstr_recv, bufinfo_send.len);
bufinfo_recv.len = vstr_recv.len;
bufinfo_recv.buf = vstr_recv.buf;
o_ret = MP_OBJ_NULL;
} else {
// recv argument given
mp_get_buffer_raise(args[1].u_obj, &bufinfo_recv, MP_BUFFER_WRITE);
if (bufinfo_recv.len != bufinfo_send.len) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
o_ret = args[1].u_obj;
// get the read buffer
mp_get_buffer_raise(readbuf, &bufinfo_read, MP_BUFFER_WRITE);
if (bufinfo_read.len != bufinfo_write.len) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
}
// send and receive
pybspi_transfer(self, (const char *)bufinfo_send.buf, bufinfo_recv.buf, bufinfo_send.len);
pybspi_transfer(self, (const char *)bufinfo_write.buf, bufinfo_read.buf, bufinfo_write.len, NULL);
// return the received data
if (o_ret != MP_OBJ_NULL) {
return o_ret;
} else {
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr_recv);
}
// return the number of transferred bytes
return mp_obj_new_int(bufinfo_write.len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_send_recv_obj, 1, pyb_spi_send_recv);
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_spi_write_readinto_obj, pyb_spi_write_readinto);
STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_spi_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_spi_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_spi_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_spi_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send_recv), (mp_obj_t)&pyb_spi_send_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&pyb_spi_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&pyb_spi_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&pyb_spi_readinto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write_readinto), (mp_obj_t)&pyb_spi_write_readinto_obj },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(SPI_MODE_MASTER) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ACTIVE_LOW), MP_OBJ_NEW_SMALL_INT(SPI_CS_ACTIVELOW) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ACTIVE_HIGH), MP_OBJ_NEW_SMALL_INT(SPI_CS_ACTIVEHIGH) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_MSB), MP_OBJ_NEW_SMALL_INT(PYBSPI_FIRST_BIT_MSB) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table);

View File

@@ -44,8 +44,8 @@
#include "prcm.h"
#include "timer.h"
#include "pybtimer.h"
#include "mpirq.h"
#include "pybsleep.h"
#include "mpcallback.h"
#include "mpexception.h"
@@ -96,7 +96,8 @@ typedef struct _pyb_timer_obj_t {
mp_obj_base_t base;
uint32_t timer;
uint32_t config;
uint16_t intflags;
uint16_t irq_trigger;
uint16_t irq_flags;
uint8_t peripheral;
uint8_t id;
} pyb_timer_obj_t;
@@ -114,7 +115,7 @@ typedef struct _pyb_timer_channel_obj_t {
/******************************************************************************
DEFINE PRIVATE DATA
******************************************************************************/
STATIC const mp_cb_methods_t pyb_timer_channel_cb_methods;
STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods;
STATIC pyb_timer_obj_t pyb_timer_obj[PYBTIMER_NUM_TIMERS] = {{.timer = TIMERA0_BASE, .peripheral = PRCM_TIMERA0},
{.timer = TIMERA1_BASE, .peripheral = PRCM_TIMERA1},
{.timer = TIMERA2_BASE, .peripheral = PRCM_TIMERA2},
@@ -124,7 +125,7 @@ STATIC const mp_obj_type_t pyb_timer_channel_type;
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC mp_obj_t pyb_timer_channel_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
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 TIMER0AIntHandler(void);
STATIC void TIMER0BIntHandler(void);
@@ -142,38 +143,26 @@ void timer_init0 (void) {
mp_obj_list_init(&MP_STATE_PORT(pyb_timer_channel_obj_list), 0);
}
void timer_disable_all (void) {
pyb_timer_obj_t timer = {
.timer = TIMERA0_BASE,
.intflags = TIMER_CAPB_EVENT | TIMER_CAPB_MATCH |
TIMER_TIMB_TIMEOUT | TIMER_CAPA_EVENT |
TIMER_CAPA_MATCH | TIMER_TIMA_TIMEOUT,
.peripheral = PRCM_TIMERA0
};
for (uint32_t i = 0; i < PYBTIMER_NUM_TIMERS; i++) {
// in case it's not clocked
MAP_PRCMPeripheralClkEnable(timer.peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
timer_disable(&timer);
// timer base offset according to hw_memmap.h
timer.timer += 0x1000;
// peripheral offset according to prcm.h
timer.peripheral++;
}
}
void pyb_timer_channel_callback_enable (mp_obj_t self_in) {
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
STATIC void pyb_timer_channel_irq_enable (mp_obj_t self_in) {
pyb_timer_channel_obj_t *self = self_in;
MAP_TimerIntClear(self->timer->timer, self->timer->intflags & self->channel);
MAP_TimerIntEnable(self->timer->timer, self->timer->intflags & self->channel);
MAP_TimerIntClear(self->timer->timer, self->timer->irq_trigger & self->channel);
MAP_TimerIntEnable(self->timer->timer, self->timer->irq_trigger & self->channel);
}
void pyb_timer_channel_callback_disable (mp_obj_t self_in) {
STATIC void pyb_timer_channel_irq_disable (mp_obj_t self_in) {
pyb_timer_channel_obj_t *self = self_in;
MAP_TimerIntDisable(self->timer->timer, self->timer->intflags & self->channel);
MAP_TimerIntDisable(self->timer->timer, self->timer->irq_trigger & self->channel);
}
pyb_timer_channel_obj_t *pyb_timer_channel_find (uint32_t timer, uint16_t channel_n) {
STATIC int pyb_timer_channel_irq_flags (mp_obj_t self_in) {
pyb_timer_channel_obj_t *self = self_in;
return self->timer->irq_flags;
}
STATIC pyb_timer_channel_obj_t *pyb_timer_channel_find (uint32_t timer, uint16_t channel_n) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(pyb_timer_channel_obj_list).len; i++) {
pyb_timer_channel_obj_t *ch = ((pyb_timer_channel_obj_t *)(MP_STATE_PORT(pyb_timer_channel_obj_list).items[i]));
// any 32-bit timer must be matched by any of its 16-bit versions
@@ -184,14 +173,14 @@ pyb_timer_channel_obj_t *pyb_timer_channel_find (uint32_t timer, uint16_t channe
return MP_OBJ_NULL;
}
void pyb_timer_channel_remove (pyb_timer_channel_obj_t *ch) {
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);
}
}
void pyb_timer_channel_add (pyb_timer_channel_obj_t *ch) {
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);
@@ -200,8 +189,8 @@ void pyb_timer_channel_add (pyb_timer_channel_obj_t *ch) {
STATIC void timer_disable (pyb_timer_obj_t *tim) {
// disable all timers and it's interrupts
MAP_TimerDisable(tim->timer, TIMER_A | TIMER_B);
MAP_TimerIntDisable(tim->timer, tim->intflags);
MAP_TimerIntClear(tim->timer, tim->intflags);
MAP_TimerIntDisable(tim->timer, tim->irq_trigger);
MAP_TimerIntClear(tim->timer, tim->irq_trigger);
MAP_PRCMPeripheralClkDisable(tim->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
memset(&pyb_timer_obj[tim->id], 0, sizeof(pyb_timer_obj_t));
}
@@ -355,7 +344,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, mp_uint_t n_args, co
timer_init(tim);
// register it with the sleep module
pybsleep_add ((const mp_obj_t)tim, (WakeUpCB_t)timer_init);
pyb_sleep_add ((const mp_obj_t)tim, (WakeUpCB_t)timer_init);
return mp_const_none;
@@ -490,7 +479,7 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
timer_channel_init(ch);
// register it with the sleep module
pybsleep_add ((const mp_obj_t)ch, (WakeUpCB_t)timer_channel_init);
pyb_sleep_add ((const mp_obj_t)ch, (WakeUpCB_t)timer_channel_init);
// add the timer to the list
pyb_timer_channel_add(ch);
@@ -529,10 +518,11 @@ const mp_obj_type_t pyb_timer_type = {
.locals_dict = (mp_obj_t)&pyb_timer_locals_dict,
};
STATIC const mp_cb_methods_t pyb_timer_channel_cb_methods = {
.init = pyb_timer_channel_callback,
.enable = pyb_timer_channel_callback_enable,
.disable = pyb_timer_channel_callback_disable,
STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods = {
.init = pyb_timer_channel_irq,
.enable = pyb_timer_channel_irq_enable,
.disable = pyb_timer_channel_irq_disable,
.flags = pyb_timer_channel_irq_flags,
};
STATIC void TIMERGenericIntHandler(uint32_t timer, uint16_t channel) {
@@ -542,8 +532,7 @@ STATIC void TIMERGenericIntHandler(uint32_t timer, uint16_t channel) {
if ((self = pyb_timer_channel_find(timer, channel))) {
status = MAP_TimerIntStatus(self->timer->timer, true) & self->channel;
MAP_TimerIntClear(self->timer->timer, status);
mp_obj_t _callback = mpcallback_find(self);
mpcallback_handler(_callback);
mp_irq_handler(mp_irq_find(self));
}
}
@@ -736,128 +725,107 @@ STATIC mp_obj_t pyb_timer_channel_duty_cycle(mp_uint_t n_args, const mp_obj_t *a
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_duty_cycle_obj, 1, 3, pyb_timer_channel_duty_cycle);
/// \method callback(handler, priority, value)
/// create a callback object associated with the timer channel
STATIC mp_obj_t pyb_timer_channel_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_arg_val_t args[mpcallback_INIT_NUM_ARGS];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mpcallback_INIT_NUM_ARGS, mpcallback_init_args, args);
/// \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);
pyb_timer_channel_obj_t *ch = pos_args[0];
mp_obj_t _callback = mpcallback_find(ch);
if (kw_args->used > 0 || !_callback) {
// convert the priority to the correct value
uint priority = mpcallback_translate_priority (args[2].u_int);
// validate the power mode
uint pwrmode = args[4].u_int;
if (pwrmode != PYB_PWR_MODE_ACTIVE) {
goto invalid_args;
}
// convert the priority to the correct value
uint priority = mp_irq_translate_priority (args[1].u_int);
uint32_t _config = (ch->channel == TIMER_B) ? ((ch->timer->config & TIMER_B) >> 8) : (ch->timer->config & TIMER_A);
// validate and set the value if we are in edge count mode
if (_config == TIMER_CFG_A_CAP_COUNT) {
uint32_t c_value = args[3].u_int;
if (!c_value || c_value > 0xFFFF) {
// zero or exceeds the maximum value of a 16-bit timer
goto invalid_args;
}
MAP_TimerMatchSet(ch->timer->timer, ch->channel, c_value);
}
// disable the callback first
pyb_timer_channel_callback_disable(ch);
uint8_t shift = (ch->channel == TIMER_B) ? 8 : 0;
switch (_config) {
case TIMER_CFG_A_ONE_SHOT:
case TIMER_CFG_A_PERIODIC:
ch->timer->intflags |= TIMER_TIMA_TIMEOUT << shift;
break;
case TIMER_CFG_A_CAP_COUNT:
ch->timer->intflags |= TIMER_CAPA_MATCH << shift;
// set the match value and make 1 the minimum
MAP_TimerMatchSet(ch->timer->timer, ch->channel, MAX(1, args[3].u_int));
break;
case TIMER_CFG_A_CAP_TIME:
ch->timer->intflags |= TIMER_CAPA_EVENT << shift;
break;
case TIMER_CFG_A_PWM:
// special case for the PWM match interrupt
ch->timer->intflags |= ((ch->channel & TIMER_A) == TIMER_A) ? TIMER_TIMA_MATCH : TIMER_TIMB_MATCH;
break;
default:
break;
}
// special case for a 32-bit timer
if (ch->channel == (TIMER_A | TIMER_B)) {
ch->timer->intflags |= (ch->timer->intflags << 8);
}
void (*pfnHandler)(void);
uint32_t intregister;
switch (ch->timer->timer) {
case TIMERA0_BASE:
if (ch->channel == TIMER_B) {
pfnHandler = &TIMER0BIntHandler;
intregister = INT_TIMERA0B;
} else {
pfnHandler = &TIMER0AIntHandler;
intregister = INT_TIMERA0A;
}
break;
case TIMERA1_BASE:
if (ch->channel == TIMER_B) {
pfnHandler = &TIMER1BIntHandler;
intregister = INT_TIMERA1B;
} else {
pfnHandler = &TIMER1AIntHandler;
intregister = INT_TIMERA1A;
}
break;
case TIMERA2_BASE:
if (ch->channel == TIMER_B) {
pfnHandler = &TIMER2BIntHandler;
intregister = INT_TIMERA2B;
} else {
pfnHandler = &TIMER2AIntHandler;
intregister = INT_TIMERA2A;
}
break;
default:
if (ch->channel == TIMER_B) {
pfnHandler = &TIMER3BIntHandler;
intregister = INT_TIMERA3B;
} else {
pfnHandler = &TIMER3AIntHandler;
intregister = INT_TIMERA3A;
}
break;
}
// register the interrupt and configure the priority
MAP_IntPrioritySet(intregister, priority);
MAP_TimerIntRegister(ch->timer->timer, ch->channel, pfnHandler);
// create the callback
_callback = mpcallback_new (ch, args[1].u_obj, &pyb_timer_channel_cb_methods);
// reload the timer
uint32_t period_c;
uint32_t match;
compute_prescaler_period_and_match_value(ch, &period_c, &match);
MAP_TimerLoadSet(ch->timer->timer, ch->channel, period_c);
// enable the callback before returning
pyb_timer_channel_callback_enable(ch);
// validate the power mode
uint8_t pwrmode = (args[3].u_obj == mp_const_none) ? PYB_PWR_MODE_ACTIVE : mp_obj_get_int(args[3].u_obj);
if (pwrmode != PYB_PWR_MODE_ACTIVE) {
goto invalid_args;
}
return _callback;
// 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:
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;
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;
break;
default:
break;
}
// special case for a 32-bit timer
if (ch->channel == (TIMER_A | TIMER_B)) {
ch->timer->irq_trigger |= (ch->timer->irq_trigger << 8);
}
void (*pfnHandler)(void);
uint32_t intregister;
switch (ch->timer->timer) {
case TIMERA0_BASE:
if (ch->channel == TIMER_B) {
pfnHandler = &TIMER0BIntHandler;
intregister = INT_TIMERA0B;
} else {
pfnHandler = &TIMER0AIntHandler;
intregister = INT_TIMERA0A;
}
break;
case TIMERA1_BASE:
if (ch->channel == TIMER_B) {
pfnHandler = &TIMER1BIntHandler;
intregister = INT_TIMERA1B;
} else {
pfnHandler = &TIMER1AIntHandler;
intregister = INT_TIMERA1A;
}
break;
case TIMERA2_BASE:
if (ch->channel == TIMER_B) {
pfnHandler = &TIMER2BIntHandler;
intregister = INT_TIMERA2B;
} else {
pfnHandler = &TIMER2AIntHandler;
intregister = INT_TIMERA2A;
}
break;
default:
if (ch->channel == TIMER_B) {
pfnHandler = &TIMER3BIntHandler;
intregister = INT_TIMERA3B;
} else {
pfnHandler = &TIMER3AIntHandler;
intregister = INT_TIMERA3A;
}
break;
}
// register the interrupt and configure the priority
MAP_IntPrioritySet(intregister, priority);
MAP_TimerIntRegister(ch->timer->timer, ch->channel, pfnHandler);
// create the callback
mp_obj_t _irq = mp_irq_new (ch, args[2].u_obj, &pyb_timer_channel_irq_methods);
// enable the callback before returning
pyb_timer_channel_irq_enable(ch);
return _irq;
invalid_args:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_callback_obj, 1, pyb_timer_channel_callback);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_irq_obj, 1, pyb_timer_channel_irq);
STATIC const mp_map_elem_t pyb_timer_channel_locals_dict_table[] = {
// instance methods
@@ -867,7 +835,7 @@ STATIC const mp_map_elem_t pyb_timer_channel_locals_dict_table[] = {
{ 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_callback), (mp_obj_t)&pyb_timer_channel_callback_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_timer_channel_irq_obj },
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table);

View File

@@ -34,5 +34,4 @@ extern const mp_obj_type_t pyb_timer_type;
DECLARE PUBLIC FUNCTIONS
******************************************************************************/
void timer_init0 (void);
void timer_disable_all (void);

View File

@@ -45,64 +45,51 @@
#include "prcm.h"
#include "uart.h"
#include "pybuart.h"
#include "mpirq.h"
#include "pybioctl.h"
#include "pybsleep.h"
#include "mpcallback.h"
#include "mpexception.h"
#include "py/mpstate.h"
#include "osi.h"
#include "utils.h"
#include "pin.h"
#include "pybpin.h"
#include "pins.h"
#include "moduos.h"
/// \moduleref pyb
/// \class UART - duplex serial communication bus
///
/// UART implements the standard UART/USART duplex serial communications protocol. At
/// the physical level it consists of 2 lines: RX and TX.
///
/// UART objects can be created and initialised using:
///
/// from pyb import UART
///
/// uart = UART(1, 9600) # init with given baudrate
/// uart.init(9600, bits=8, stop=1, parity=None) # init with given parameters
///
/// Bits can be 5, 6, 7, 8, parity can be None, 0 (even), 1 (odd). Stop can be 1 or 2.
///
/// A UART object acts like a stream object and reading and writing is done
/// using the standard stream methods:
///
/// uart.read(10) # read 10 characters, returns a bytes object
/// uart.readall() # read all available characters
/// uart.readline() # read a line
/// uart.readinto(buf) # read and store into the given buffer
/// uart.write('abc') # write the 3 characters
///
/// Individual characters can be read/written using:
///
/// uart.readchar() # read 1 character and returns it as an integer
/// uart.writechar(42) # write 1 character
///
/// To check if there is anything to be read, use:
///
/// uart.any() # returns True if any characters waiting
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
#define PYBUART_TX_WAIT_US (50)
*******-***********************************************************************/
#define PYBUART_FRAME_TIME_US(baud) ((11 * 1000000) / baud)
#define PYBUART_2_FRAMES_TIME_US(baud) (PYBUART_FRAME_TIME_US(baud) * 2)
#define PYBUART_RX_TIMEOUT_US(baud) (PYBUART_2_FRAMES_TIME_US(baud) * 8) // we need at least characters in the FIFO
#define PYBUART_TX_WAIT_US(baud) ((PYBUART_FRAME_TIME_US(baud)) + 1)
#define PYBUART_TX_MAX_TIMEOUT_MS (5)
#define PYBUART_RX_BUFFER_LEN (256)
// interrupt triggers
#define UART_TRIGGER_RX_ANY (0x01)
#define UART_TRIGGER_RX_HALF (0x02)
#define UART_TRIGGER_RX_FULL (0x04)
#define UART_TRIGGER_TX_DONE (0x08)
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC void uart_init (pyb_uart_obj_t *self);
STATIC bool uart_rx_wait (pyb_uart_obj_t *self, uint32_t timeout);
STATIC bool uart_rx_wait (pyb_uart_obj_t *self);
STATIC void uart_check_init(pyb_uart_obj_t *self);
STATIC mp_obj_t uart_irq_new (pyb_uart_obj_t *self, byte trigger, mp_int_t priority, mp_obj_t handler);
STATIC void UARTGenericIntHandler(uint32_t uart_id);
STATIC void UART0IntHandler(void);
STATIC void UART1IntHandler(void);
STATIC void uart_callback_enable (mp_obj_t self_in);
STATIC void uart_callback_disable (mp_obj_t self_in);
STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in);
STATIC void uart_irq_enable (mp_obj_t self_in);
STATIC void uart_irq_disable (mp_obj_t self_in);
/******************************************************************************
DEFINE PRIVATE TYPES
@@ -115,36 +102,46 @@ struct _pyb_uart_obj_t {
uint config;
uint flowcontrol;
byte *read_buf; // read buffer pointer
uint16_t timeout; // timeout waiting for first char
uint16_t timeout_char; // timeout waiting between chars
uint16_t read_buf_len; // len in chars; buf can hold len-1 chars
volatile uint16_t read_buf_head; // indexes first empty slot
uint16_t read_buf_tail; // indexes first full slot (not full if equals head)
byte peripheral;
byte irq_trigger;
bool irq_enabled;
byte irq_flags;
};
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC pyb_uart_obj_t pyb_uart_obj[PYB_NUM_UARTS] = {{.reg = UARTA0_BASE, .baudrate = 0, .peripheral = PRCM_UARTA0},
{.reg = UARTA1_BASE, .baudrate = 0, .peripheral = PRCM_UARTA1}};
STATIC const mp_cb_methods_t uart_cb_methods;
STATIC pyb_uart_obj_t pyb_uart_obj[PYB_NUM_UARTS] = { {.reg = UARTA0_BASE, .baudrate = 0, .read_buf = NULL, .peripheral = PRCM_UARTA0},
{.reg = UARTA1_BASE, .baudrate = 0, .read_buf = NULL, .peripheral = PRCM_UARTA1} };
STATIC const mp_irq_methods_t uart_irq_methods;
STATIC const mp_obj_t pyb_uart_def_pin[PYB_NUM_UARTS][2] = { {&pin_GP1, &pin_GP2}, {&pin_GP3, &pin_GP4} };
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
void uart_init0 (void) {
// save references of the UART objects, to prevent the read buffers from being trashed by the gc
MP_STATE_PORT(pyb_uart_objs)[0] = &pyb_uart_obj[0];
MP_STATE_PORT(pyb_uart_objs)[1] = &pyb_uart_obj[1];
}
bool uart_rx_any(pyb_uart_obj_t *self) {
return (self->read_buf_tail != self->read_buf_head || MAP_UARTCharsAvail(self->reg));
uint32_t uart_rx_any(pyb_uart_obj_t *self) {
if (self->read_buf_tail != self->read_buf_head) {
// buffering via irq
return (self->read_buf_head > self->read_buf_tail) ? self->read_buf_head - self->read_buf_tail :
PYBUART_RX_BUFFER_LEN - self->read_buf_tail + self->read_buf_head;
}
return MAP_UARTCharsAvail(self->reg) ? 1 : 0;
}
int uart_rx_char(pyb_uart_obj_t *self) {
if (self->read_buf_tail != self->read_buf_head) {
// buffering via IRQ
// buffering via irq
int data = self->read_buf[self->read_buf_tail];
self->read_buf_tail = (self->read_buf_tail + 1) % self->read_buf_len;
self->read_buf_tail = (self->read_buf_tail + 1) % PYBUART_RX_BUFFER_LEN;
return data;
} else {
// no buffering
@@ -154,12 +151,11 @@ int uart_rx_char(pyb_uart_obj_t *self) {
bool uart_tx_char(pyb_uart_obj_t *self, int c) {
uint32_t timeout = 0;
while (!MAP_UARTCharPutNonBlocking(self->reg, c)) {
if (timeout++ > ((PYBUART_TX_MAX_TIMEOUT_MS * 1000) / PYBUART_TX_WAIT_US)) {
if (timeout++ > ((PYBUART_TX_MAX_TIMEOUT_MS * 1000) / PYBUART_TX_WAIT_US(self->baudrate))) {
return false;
}
UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBUART_TX_WAIT_US));
UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBUART_TX_WAIT_US(self->baudrate)));
}
return true;
}
@@ -173,52 +169,6 @@ bool uart_tx_strn(pyb_uart_obj_t *self, const char *str, uint len) {
return true;
}
void uart_tx_strn_cooked(pyb_uart_obj_t *self, const char *str, uint len) {
for (const char *top = str + len; str < top; str++) {
if (*str == '\n') {
uart_tx_char(self, '\r');
}
uart_tx_char(self, *str);
}
}
mp_obj_t uart_callback_new (pyb_uart_obj_t *self, mp_obj_t handler, uint rxbuffer_size, mp_int_t priority) {
// disable the uart interrupts before updating anything
uart_callback_disable (self);
if (self->uart_id == PYB_UART_0) {
MAP_IntPrioritySet(INT_UARTA0, priority);
MAP_UARTIntRegister(self->reg, UART0IntHandler);
}
else {
MAP_IntPrioritySet(INT_UARTA1, priority);
MAP_UARTIntRegister(self->reg, UART1IntHandler);
}
// check the rx buffer size
if (rxbuffer_size > 0) {
// allocate the read buffer
self->read_buf_len = rxbuffer_size;
self->read_buf = m_new(byte, rxbuffer_size);
}
// create the callback
mp_obj_t _callback = mpcallback_new ((mp_obj_t)self, handler, &uart_cb_methods);
// enable the interrupts now
uart_callback_enable (self);
return _callback;
}
void uart_disable_all (void) {
for (int i = 0; i < PYB_NUM_UARTS; i++) {
// in case it's not clocked
MAP_PRCMPeripheralClkEnable(pyb_uart_obj[i].peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
pyb_uart_deinit(&pyb_uart_obj[i]);
}
}
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
@@ -230,6 +180,12 @@ STATIC void uart_init (pyb_uart_obj_t *self) {
// Reset the uart
MAP_PRCMPeripheralReset(self->peripheral);
// re-allocate the read buffer after resetting the uart (which automatically disables any irqs)
self->read_buf_head = 0;
self->read_buf_tail = 0;
self->read_buf = MP_OBJ_NULL; // free the read buffer before allocating again
self->read_buf = m_new(byte, PYBUART_RX_BUFFER_LEN);
// Initialize the UART
MAP_UARTConfigSetExpClk(self->reg, MAP_PRCMPeripheralClockGet(self->peripheral),
self->baudrate, self->config);
@@ -244,16 +200,17 @@ STATIC void uart_init (pyb_uart_obj_t *self) {
UARTFlowControlSet(self->reg, self->flowcontrol);
}
// Waits at most timeout milliseconds for at least 1 char to become ready for
// Waits at most timeout microseconds for at least 1 char to become ready for
// reading (from buf or for direct reading).
// Returns true if something available, false if not.
STATIC bool uart_rx_wait (pyb_uart_obj_t *self, uint32_t timeout) {
STATIC bool uart_rx_wait (pyb_uart_obj_t *self) {
int timeout = PYBUART_RX_TIMEOUT_US(self->baudrate);
for ( ; ; ) {
if (uart_rx_any(self)) {
return true; // have at least 1 char ready for reading
return true; // we have at least 1 char ready for reading
}
if (timeout > 0) {
HAL_Delay (1);
UtilsDelay(UTILS_DELAY_US_TO_COUNT(1));
timeout--;
}
else {
@@ -262,6 +219,27 @@ STATIC bool uart_rx_wait (pyb_uart_obj_t *self, uint32_t timeout) {
}
}
STATIC mp_obj_t uart_irq_new (pyb_uart_obj_t *self, byte trigger, mp_int_t priority, mp_obj_t handler) {
// disable the uart interrupts before updating anything
uart_irq_disable (self);
if (self->uart_id == PYB_UART_0) {
MAP_IntPrioritySet(INT_UARTA0, priority);
MAP_UARTIntRegister(self->reg, UART0IntHandler);
} else {
MAP_IntPrioritySet(INT_UARTA1, priority);
MAP_UARTIntRegister(self->reg, UART1IntHandler);
}
// create the callback
mp_obj_t _irq = mp_irq_new ((mp_obj_t)self, handler, &uart_irq_methods);
// enable the interrupts now
self->irq_trigger = trigger;
uart_irq_enable (self);
return _irq;
}
STATIC void UARTGenericIntHandler(uint32_t uart_id) {
pyb_uart_obj_t *self;
uint32_t status;
@@ -270,15 +248,16 @@ STATIC void UARTGenericIntHandler(uint32_t uart_id) {
status = MAP_UARTIntStatus(self->reg, true);
// receive interrupt
if (status & (UART_INT_RX | UART_INT_RT)) {
// set the flags
self->irq_flags = UART_TRIGGER_RX_ANY;
MAP_UARTIntClear(self->reg, UART_INT_RX | UART_INT_RT);
while (UARTCharsAvail(self->reg)) {
int data = MAP_UARTCharGetNonBlocking(self->reg);
if (pyb_stdio_uart == self && data == user_interrupt_char) {
if (MP_STATE_PORT(os_term_dup_obj) && MP_STATE_PORT(os_term_dup_obj)->stream_o == self && data == user_interrupt_char) {
// raise an exception when interrupts are finished
mpexception_keyboard_nlr_jump();
}
else if (self->read_buf_len != 0) {
uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len;
} else { // there's always a read buffer available
uint16_t next_head = (self->read_buf_head + 1) % PYBUART_RX_BUFFER_LEN;
if (next_head != self->read_buf_tail) {
// only store data if room in buf
self->read_buf[self->read_buf_head] = data;
@@ -286,9 +265,22 @@ STATIC void UARTGenericIntHandler(uint32_t uart_id) {
}
}
}
}
// check the flags to see if the user handler should be called
if ((self->irq_trigger & self->irq_flags) && self->irq_enabled) {
// call the user defined handler
mp_obj_t _callback = mpcallback_find(self);
mpcallback_handler(_callback);
mp_irq_handler(mp_irq_find(self));
}
// clear the flags
self->irq_flags = 0;
}
STATIC void uart_check_init(pyb_uart_obj_t *self) {
// not initialized
if (!self->baudrate) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
}
@@ -300,15 +292,24 @@ STATIC void UART1IntHandler(void) {
UARTGenericIntHandler(1);
}
STATIC void uart_callback_enable (mp_obj_t self_in) {
STATIC void uart_irq_enable (mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
MAP_UARTIntClear(self->reg, UART_INT_RX | UART_INT_RT);
MAP_UARTIntEnable(self->reg, UART_INT_RX | UART_INT_RT);
// check for any of the rx interrupt types
if (self->irq_trigger & (UART_TRIGGER_RX_ANY | UART_TRIGGER_RX_HALF | UART_TRIGGER_RX_FULL)) {
MAP_UARTIntClear(self->reg, UART_INT_RX | UART_INT_RT);
MAP_UARTIntEnable(self->reg, UART_INT_RX | UART_INT_RT);
}
self->irq_enabled = true;
}
STATIC void uart_callback_disable (mp_obj_t self_in) {
STATIC void uart_irq_disable (mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
MAP_UARTIntDisable(self->reg, UART_INT_RX | UART_INT_RT);
self->irq_enabled = false;
}
STATIC int uart_irq_flags (mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
return self->irq_flags;
}
/******************************************************************************/
@@ -317,7 +318,7 @@ STATIC void uart_callback_disable (mp_obj_t self_in) {
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 = self_in;
if (self->baudrate > 0) {
mp_printf(print, "<UART%u, baudrate=%u, bits=", (self->uart_id + 1), self->baudrate);
mp_printf(print, "UART(%u, baudrate=%u, bits=", self->uart_id, self->baudrate);
switch (self->config & UART_CONFIG_WLEN_MASK) {
case UART_CONFIG_WLEN_5:
mp_print_str(print, "5");
@@ -337,100 +338,96 @@ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k
if ((self->config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_NONE) {
mp_print_str(print, ", parity=None");
} else {
mp_printf(print, ", parity=%u", (self->config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_EVEN ? 0 : 1);
mp_printf(print, ", parity=UART.%q", (self->config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_EVEN ? MP_QSTR_EVEN : MP_QSTR_ODD);
}
mp_printf(print, ", stop=%u, timeout=%u, timeout_char=%u, read_buf_len=%u>",
(self->config & UART_CONFIG_STOP_MASK) == UART_CONFIG_STOP_ONE ? 1 : 2,
self->timeout, self->timeout_char, self->read_buf_len);
mp_printf(print, ", stop=%u)", (self->config & UART_CONFIG_STOP_MASK) == UART_CONFIG_STOP_ONE ? 1 : 2);
}
else {
mp_printf(print, "<UART%u>", (self->uart_id + 1));
mp_printf(print, "UART(%u)", self->uart_id);
}
}
/// \method init(baudrate, bits=8, parity=None, stop=1, *, timeout=1000, timeout_char=0)
///
/// Initialise the UART bus with the given parameters:
///
/// - `baudrate` is the clock rate.
/// - `bits` is the number of bits per byte, 5, 6, 7, 8
/// - `parity` is the parity, `None`, 0 (even) or 1 (odd).
/// - `stop` is the number of stop bits, 1 or 2.
/// - `flow` is the flow control mode, `None`, `UART.RTS`,
/// `UART.CTS', or `UART.CTS | UART.RTS`
/// - `timeout` is the timeout (in milliseconds) when waiting for the first character.
/// - `timeout_char` is the timeout (in milliseconds) between characters.
STATIC const mp_arg_t pyb_uart_init_args[] = {
{ MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
{ MP_QSTR_parity, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_flow, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_int = UART_FLOWCONTROL_NONE} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000} },
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
};
STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_uart_init_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(pyb_uart_init_args), pyb_uart_init_args, args);
// set timeouts
self->timeout = args[5].u_int;
self->timeout_char = args[6].u_int;
// no read buffer for the moment
self->read_buf_head = 0;
self->read_buf_tail = 0;
self->read_buf_len = 0;
self->read_buf = NULL;
STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, const mp_arg_val_t *args) {
// get the baudrate
self->baudrate = args[0].u_int;
if (args[0].u_int <= 0) {
goto error;
}
uint baudrate = args[0].u_int;
uint config;
switch (args[1].u_int) {
case 5:
config = UART_CONFIG_WLEN_5;
break;
case 6:
config = UART_CONFIG_WLEN_6;
break;
case 7:
config = UART_CONFIG_WLEN_7;
break;
case 8:
config = UART_CONFIG_WLEN_8;
break;
default:
goto error;
break;
}
// parity
if (args[2].u_obj == mp_const_none) {
config |= UART_CONFIG_PAR_NONE;
} else {
uint parity = mp_obj_get_int(args[2].u_obj);
if (parity != UART_CONFIG_PAR_ODD && parity != UART_CONFIG_PAR_EVEN) {
goto error;
}
config |= parity;
}
// stop bits
config |= (args[3].u_int == 1 ? UART_CONFIG_STOP_ONE : UART_CONFIG_STOP_TWO);
// set the UART configuration values
if (n_args > 1) {
switch (args[1].u_int) {
case 5:
self->config = UART_CONFIG_WLEN_5;
break;
case 6:
self->config = UART_CONFIG_WLEN_6;
break;
case 7:
self->config = UART_CONFIG_WLEN_7;
break;
case 8:
self->config = UART_CONFIG_WLEN_8;
break;
default:
goto error;
break;
}
// Parity
if (args[2].u_obj == mp_const_none) {
self->config |= UART_CONFIG_PAR_NONE;
// assign the pins
mp_obj_t pins_o = args[4].u_obj;
uint flowcontrol = UART_FLOWCONTROL_NONE;
if (pins_o != mp_const_none) {
mp_obj_t *pins;
mp_uint_t n_pins = 2;
if (pins_o == MP_OBJ_NULL) {
// use the default pins
pins = (mp_obj_t *)pyb_uart_def_pin[self->uart_id];
} else {
self->config |= ((mp_obj_get_int(args[2].u_obj) & 1) ? UART_CONFIG_PAR_ODD : UART_CONFIG_PAR_EVEN);
mp_obj_get_array(pins_o, &n_pins, &pins);
if (n_pins != 2 && n_pins != 4) {
goto error;
}
if (n_pins == 4) {
if (pins[PIN_TYPE_UART_RTS] != mp_const_none && pins[PIN_TYPE_UART_RX] == mp_const_none) {
goto error; // RTS pin given in TX only mode
} else if (pins[PIN_TYPE_UART_CTS] != mp_const_none && pins[PIN_TYPE_UART_TX] == mp_const_none) {
goto error; // CTS pin given in RX only mode
} else {
if (pins[PIN_TYPE_UART_RTS] != mp_const_none) {
flowcontrol |= UART_FLOWCONTROL_RX;
}
if (pins[PIN_TYPE_UART_CTS] != mp_const_none) {
flowcontrol |= UART_FLOWCONTROL_TX;
}
}
}
}
// Stop bits
self->config |= (args[3].u_int == 1 ? UART_CONFIG_STOP_ONE : UART_CONFIG_STOP_TWO);
// Flow control
if (args[4].u_int != UART_FLOWCONTROL_NONE || args[4].u_int != UART_FLOWCONTROL_TX ||
args[4].u_int != UART_FLOWCONTROL_RX || args[4].u_int != (UART_FLOWCONTROL_TX | UART_FLOWCONTROL_RX)) {
goto error;
}
self->flowcontrol = args[4].u_int;
}
else {
self->config = UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE;
self->flowcontrol = UART_FLOWCONTROL_NONE;
pin_assign_pins_af (pins, n_pins, PIN_TYPE_STD_PU, PIN_FN_UART, self->uart_id);
}
self->baudrate = baudrate;
self->config = config;
self->flowcontrol = flowcontrol;
// initialize and enable the uart
uart_init (self);
// register it with the sleep module
pybsleep_add ((const mp_obj_t)self, (WakeUpCB_t)uart_init);
pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)uart_init);
// enable the callback
uart_irq_new (self, UART_TRIGGER_RX_ANY, INT_PRIORITY_LVL_3, mp_const_none);
// disable the irq (from the user point of view)
uart_irq_disable(self);
return mp_const_none;
@@ -438,27 +435,43 @@ error:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
/// \classmethod \constructor(bus, ...)
///
/// Construct a UART object on the given bus id. `bus id` can be 1 or 2
/// With no additional parameters, the UART object is created but not
/// initialised (it has the settings from the last initialisation of
/// the bus, if any).
/// When only the baud rate is given the UART object is created and
/// initialized with the default configuration of: 8 bit transfers,
/// 1 stop bit, no parity and flow control disabled.
/// See `init` for parameters of initialisation.
/// If extra arguments are given, the bus is initialised with these arguments
/// See `init` for parameters of initialisation.
///
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 *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_ARRAY_SIZE(pyb_uart_init_args), true);
STATIC const mp_arg_t pyb_uart_init_args[] = {
{ MP_QSTR_id, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_baudrate, 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_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) {
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_uart_init_args)];
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_uart_init_args, args);
// work out the uart id
int32_t uart_id = mp_obj_get_int(args[0]) - 1;
uint uart_id;
if (args[0].u_obj == MP_OBJ_NULL) {
if (args[5].u_obj != MP_OBJ_NULL) {
mp_obj_t *pins;
mp_uint_t n_pins = 2;
mp_obj_get_array(args[5].u_obj, &n_pins, &pins);
// check the Tx pin (or the Rx if Tx is None)
if (pins[0] == mp_const_none) {
uart_id = pin_find_peripheral_unit(pins[1], PIN_FN_UART, PIN_TYPE_UART_RX);
} else {
uart_id = pin_find_peripheral_unit(pins[0], PIN_FN_UART, PIN_TYPE_UART_TX);
}
} else {
// default id
uart_id = 0;
}
} else {
uart_id = mp_obj_get_int(args[0].u_obj);
}
if (uart_id < PYB_UART_0 || uart_id > PYB_UART_1) {
if (uart_id > PYB_UART_1) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
@@ -467,30 +480,29 @@ STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
self->base.type = &pyb_uart_type;
self->uart_id = uart_id;
if (n_args > 1 || n_kw > 0) {
// start 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);
}
// start the peripheral
pyb_uart_init_helper(self, &args[1]);
return self;
}
STATIC mp_obj_t pyb_uart_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
return pyb_uart_init_helper(args[0], n_args - 1, args + 1, kw_args);
STATIC mp_obj_t pyb_uart_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_uart_init_args) - 1];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_uart_init_args[1], args);
return pyb_uart_init_helper(pos_args[0], args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init);
/// \method deinit()
/// Turn off the UART bus.
STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
// unregister it with the sleep module
pybsleep_remove (self);
pyb_sleep_remove (self);
// invalidate the baudrate
self->baudrate = 0;
// free the read buffer
m_del(byte, self->read_buf, PYBUART_RX_BUFFER_LEN);
MAP_UARTIntDisable(self->reg, UART_INT_RX | UART_INT_RT);
MAP_UARTDisable(self->reg);
MAP_PRCMPeripheralClkDisable(self->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
@@ -498,95 +510,63 @@ STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_deinit_obj, pyb_uart_deinit);
/// \method any()
/// Return `True` if any characters waiting, else `False`.
STATIC mp_obj_t pyb_uart_any(mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
if (uart_rx_any(self)) {
return mp_const_true;
} else {
return mp_const_false;
}
uart_check_init(self);
return mp_obj_new_int(uart_rx_any(self));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_any_obj, pyb_uart_any);
/// \method callback(handler, value, priority)
/// Creates a callback object associated with the uart
/// min num of arguments is 1 (value). The value is the size of the rx buffer
STATIC mp_obj_t pyb_uart_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_arg_val_t args[mpcallback_INIT_NUM_ARGS];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mpcallback_INIT_NUM_ARGS, mpcallback_init_args, args);
// check if any parameters were passed
pyb_uart_obj_t *self = pos_args[0];
mp_obj_t _callback = mpcallback_find((mp_obj_t)self);
if (kw_args->used > 0 || !_callback) {
// convert the priority to the correct value
uint priority = mpcallback_translate_priority (args[2].u_int);
// check the power mode
if (PYB_PWR_MODE_ACTIVE != args[4].u_int) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
// register a new callback
return uart_callback_new (self, args[1].u_obj, args[3].u_int, priority);
}
return _callback;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_callback_obj, 1, pyb_uart_callback);
/// \method writechar(char)
/// Write a single character on the bus. `char` is an integer to write.
/// Return value: `None`.
STATIC mp_obj_t pyb_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) {
pyb_uart_obj_t *self = self_in;
// get the character to write
uint8_t data = mp_obj_get_int(char_in);
// send the character
if (!uart_tx_char(self, data)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_uart_writechar_obj, pyb_uart_writechar);
/// \method readchar()
/// Receive a single character on the bus.
/// Return value: The character read, as an integer. Returns -1 on timeout.
STATIC mp_obj_t pyb_uart_readchar(mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
if (uart_rx_wait(self, self->timeout)) {
return mp_obj_new_int(uart_rx_char(self));
} else {
// return -1 on timeout
return MP_OBJ_NEW_SMALL_INT(-1);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar);
/// \method sendbreak()
STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
uart_check_init(self);
// send a break signal for at least 2 complete frames
MAP_UARTBreakCtl(self->reg, true);
UtilsDelay(UTILS_DELAY_US_TO_COUNT((22 * 1000000) / self->baudrate));
UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBUART_2_FRAMES_TIME_US(self->baudrate)));
MAP_UARTBreakCtl(self->reg, false);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_sendbreak_obj, pyb_uart_sendbreak);
/// \method irq(trigger, priority, handler, wake)
STATIC mp_obj_t pyb_uart_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);
// check if any parameters were passed
pyb_uart_obj_t *self = pos_args[0];
uart_check_init(self);
// convert the priority to the correct value
uint priority = mp_irq_translate_priority (args[1].u_int);
// check the power mode
uint8_t pwrmode = (args[3].u_obj == mp_const_none) ? PYB_PWR_MODE_ACTIVE : mp_obj_get_int(args[3].u_obj);
if (PYB_PWR_MODE_ACTIVE != pwrmode) {
goto invalid_args;
}
// check the trigger
uint trigger = mp_obj_get_int(args[0].u_obj);
if (!trigger || trigger > (UART_TRIGGER_RX_ANY | UART_TRIGGER_RX_HALF | UART_TRIGGER_RX_FULL | UART_TRIGGER_TX_DONE)) {
goto invalid_args;
}
// register a new callback
return uart_irq_new (self, trigger, priority, args[2].u_obj);
invalid_args:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_irq_obj, 1, pyb_uart_irq);
STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_uart_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_uart_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&pyb_uart_any_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pyb_uart_callback_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendbreak), (mp_obj_t)&pyb_uart_sendbreak_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_uart_irq_obj },
/// \method read([nbytes])
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
@@ -599,13 +579,10 @@ STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
/// \method write(buf)
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_writechar), (mp_obj_t)&pyb_uart_writechar_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readchar), (mp_obj_t)&pyb_uart_readchar_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendbreak), (mp_obj_t)&pyb_uart_sendbreak_obj },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_CTS), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_TX) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RTS), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_RX) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_EVEN), MP_OBJ_NEW_SMALL_INT(UART_CONFIG_PAR_EVEN) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ODD), MP_OBJ_NEW_SMALL_INT(UART_CONFIG_PAR_ODD) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RX_ANY), MP_OBJ_NEW_SMALL_INT(UART_TRIGGER_RX_ANY) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table);
@@ -613,6 +590,7 @@ 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) {
pyb_uart_obj_t *self = self_in;
byte *buf = buf_in;
uart_check_init(self);
// make sure we want at least 1 char
if (size == 0) {
@@ -620,17 +598,17 @@ STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, i
}
// wait for first char to become available
if (!uart_rx_wait(self, self->timeout)) {
// we can either return 0 to indicate EOF (then read() method returns b'')
// or return EAGAIN error to indicate non-blocking (then read() method returns None)
return 0;
if (!uart_rx_wait(self)) {
// return EAGAIN error to indicate non-blocking (then read() method returns None)
*errcode = EAGAIN;
return MP_STREAM_ERROR;
}
// read the data
byte *orig_buf = buf;
for ( ; ; ) {
*buf++ = uart_rx_char(self);
if (--size == 0 || !uart_rx_wait(self, self->timeout_char)) {
if (--size == 0 || !uart_rx_wait(self)) {
// return number of bytes read
return buf - orig_buf;
}
@@ -640,6 +618,7 @@ STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, i
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 = self_in;
const char *buf = buf_in;
uart_check_init(self);
// write the data
if (!uart_tx_strn(self, buf, size)) {
@@ -651,6 +630,8 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t
STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
pyb_uart_obj_t *self = self_in;
mp_uint_t ret;
uart_check_init(self);
if (request == MP_IOCTL_POLL) {
mp_uint_t flags = arg;
ret = 0;
@@ -674,10 +655,11 @@ STATIC const mp_stream_p_t uart_stream_p = {
.is_text = false,
};
STATIC const mp_cb_methods_t uart_cb_methods = {
.init = pyb_uart_callback,
.enable = uart_callback_enable,
.disable = uart_callback_disable,
STATIC const mp_irq_methods_t uart_irq_methods = {
.init = pyb_uart_irq,
.enable = uart_irq_enable,
.disable = uart_irq_disable,
.flags = uart_irq_flags
};
const mp_obj_type_t pyb_uart_type = {

View File

@@ -38,12 +38,9 @@ typedef struct _pyb_uart_obj_t pyb_uart_obj_t;
extern const mp_obj_type_t pyb_uart_type;
void uart_init0(void);
bool uart_rx_any(pyb_uart_obj_t *uart_obj);
uint32_t uart_rx_any(pyb_uart_obj_t *uart_obj);
int uart_rx_char(pyb_uart_obj_t *uart_obj);
bool uart_tx_char(pyb_uart_obj_t *self, int c);
bool uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len);
void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len);
mp_obj_t uart_callback_new (pyb_uart_obj_t *self, mp_obj_t handler, uint rxbuffer_size, mp_int_t priority);
void uart_disable_all (void);
#endif // PYBUART_H_

View File

@@ -53,17 +53,17 @@
DECLARE TYPES
******************************************************************************/
typedef struct {
mp_obj_base_t base;
bool servers;
bool servers_sleeping;
bool simplelink;
bool running;
} pybwdt_data_t;
} pyb_wdt_obj_t;
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC pybwdt_data_t pybwdt_data = {.servers = false, .servers_sleeping = false, .simplelink = false, .running = false};
STATIC const mp_obj_base_t pyb_wdt_obj = {&pyb_wdt_type};
STATIC pyb_wdt_obj_t pyb_wdt_obj = {.servers = false, .servers_sleeping = false, .simplelink = false, .running = false};
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
@@ -74,73 +74,79 @@ void pybwdt_init0 (void) {
}
void pybwdt_srv_alive (void) {
pybwdt_data.servers = true;
pyb_wdt_obj.servers = true;
}
void pybwdt_srv_sleeping (bool state) {
pybwdt_data.servers_sleeping = state;
pyb_wdt_obj.servers_sleeping = state;
}
void pybwdt_sl_alive (void) {
pybwdt_data.simplelink = true;
pyb_wdt_obj.simplelink = true;
}
/******************************************************************************/
// Micro Python bindings
/// \function constructor('msec')
/// Enables the watchdog timer with msec timeout value
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 *args) {
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) {
// check the arguments
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_wdt_init_args)];
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_wdt_init_args, args);
if (n_args > 0) {
mp_int_t msec = mp_obj_get_int(args[0]);
if (msec < PYBWDT_MIN_TIMEOUT_MS) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
if (pybwdt_data.running) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
// Enable the WDT peripheral clock
MAP_PRCMPeripheralClkEnable(PRCM_WDT, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
// Unlock to be able to configure the registers
MAP_WatchdogUnlock(WDT_BASE);
#ifdef DEBUG
// make the WDT stall when the debugger stops on a breakpoint
MAP_WatchdogStallEnable (WDT_BASE);
#endif
// set the watchdog timer reload value
// the WDT trigger a system reset after the second timeout
// so, divide by 2 the timeout value received
MAP_WatchdogReloadSet(WDT_BASE, PYBWDT_MILLISECONDS_TO_TICKS(msec / 2));
// start the timer. Once it's started, it cannot be disabled.
MAP_WatchdogEnable(WDT_BASE);
pybwdt_data.running = true;
if (args[0].u_obj != mp_const_none && mp_obj_get_int(args[0].u_obj) > 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
uint timeout_ms = args[1].u_int;
if (timeout_ms < PYBWDT_MIN_TIMEOUT_MS) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
if (pyb_wdt_obj.running) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
// Enable the WDT peripheral clock
MAP_PRCMPeripheralClkEnable(PRCM_WDT, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
// Unlock to be able to configure the registers
MAP_WatchdogUnlock(WDT_BASE);
#ifdef DEBUG
// make the WDT stall when the debugger stops on a breakpoint
MAP_WatchdogStallEnable (WDT_BASE);
#endif
// set the watchdog timer reload value
// the WDT trigger a system reset after the second timeout
// so, divide by 2 the timeout value received
MAP_WatchdogReloadSet(WDT_BASE, PYBWDT_MILLISECONDS_TO_TICKS(timeout_ms / 2));
// start the timer. Once it's started, it cannot be disabled.
MAP_WatchdogEnable(WDT_BASE);
pyb_wdt_obj.base.type = &pyb_wdt_type;
pyb_wdt_obj.running = true;
return (mp_obj_t)&pyb_wdt_obj;
}
/// \function wdt_kick()
/// Kicks the watchdog timer
STATIC mp_obj_t pyb_kick_wdt(mp_obj_t self) {
if ((pybwdt_data.servers || pybwdt_data.servers_sleeping) && pybwdt_data.simplelink && pybwdt_data.running) {
pybwdt_data.servers = false;
pybwdt_data.simplelink = false;
STATIC mp_obj_t pyb_wdt_feed(mp_obj_t self_in) {
pyb_wdt_obj_t *self = self_in;
if ((self->servers || self->servers_sleeping) && self->simplelink && self->running) {
self->servers = false;
self->simplelink = false;
MAP_WatchdogIntClear(WDT_BASE);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_kick_wdt_obj, pyb_kick_wdt);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_wdt_feed_obj, pyb_wdt_feed);
STATIC const mp_map_elem_t pybwdt_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_kick), (mp_obj_t)&pyb_kick_wdt_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_feed), (mp_obj_t)&pyb_wdt_feed_obj },
};
STATIC MP_DEFINE_CONST_DICT(pybwdt_locals_dict, pybwdt_locals_dict_table);

View File

@@ -43,12 +43,17 @@
#define MICROPY_HELPER_REPL (1)
#define MICROPY_ENABLE_SOURCE_LINE (1)
#define MICROPY_ENABLE_DOC_STRING (0)
#define MICROPY_REPL_AUTO_INDENT (1)
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
#define MICROPY_OPT_COMPUTED_GOTO (0)
#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0)
#ifndef DEBUG // we need ram on the launchxl while debugging
#define MICROPY_CPYTHON_COMPAT (1)
#else
#define MICROPY_CPYTHON_COMPAT (0)
#endif
#define MICROPY_QSTR_BYTES_IN_HASH (1)
/* Enable FatFS LFNs
@@ -62,15 +67,26 @@
#define MICROPY_STREAMS_NON_BLOCK (1)
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
#define MICROPY_PY_BUILTINS_TIMEOUTERROR (1)
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
#ifndef DEBUG
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
#define MICROPY_PY_BUILTINS_FROZENSET (1)
#define MICROPY_PY_BUILTINS_EXECFILE (1)
#define MICROPY_PY_BUILTINS_TIMEOUTERROR (1)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (0)
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
#else
#define MICROPY_PY_BUILTINS_STR_UNICODE (0)
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (0)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (0)
#define MICROPY_PY_BUILTINS_FROZENSET (0)
#define MICROPY_PY_BUILTINS_EXECFILE (0)
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (0)
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0)
#endif
#define MICROPY_PY_MICROPYTHON_MEM_INFO (0)
#define MICROPY_PY_SYS_MAXSIZE (1)
#define MICROPY_PY_SYS_EXIT (1)
#define MICROPY_PY_SYS_STDFILES (1)
@@ -82,7 +98,7 @@
#define MICROPY_PY_UZLIB (0)
#define MICROPY_PY_UJSON (1)
#define MICROPY_PY_URE (1)
#define MICROPY_PY_UHEAPQ (1)
#define MICROPY_PY_UHEAPQ (0)
#define MICROPY_PY_UHASHLIB (0)
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
@@ -98,27 +114,26 @@ extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, \
// extra built in modules to add to the list of known ones
extern const struct _mp_obj_module_t pyb_module;
extern const struct _mp_obj_module_t machine_module;
extern const struct _mp_obj_module_t wipy_module;
extern const struct _mp_obj_module_t mp_module_ure;
extern const struct _mp_obj_module_t mp_module_ujson;
extern const struct _mp_obj_module_t mp_module_uheapq;
extern const struct _mp_obj_module_t mp_module_uos;
extern const struct _mp_obj_module_t mp_module_utime;
extern const struct _mp_obj_module_t mp_module_uselect;
extern const struct _mp_obj_module_t mp_module_usocket;
extern const struct _mp_obj_module_t mp_module_network;
extern const struct _mp_obj_module_t mp_module_uhashlib;
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_pyb), (mp_obj_t)&pyb_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_machine), (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 }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_uselect), (mp_obj_t)&mp_module_uselect }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_ubinascii), (mp_obj_t)&mp_module_ubinascii }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_ussl), (mp_obj_t)&mp_module_ussl }, \
@@ -126,28 +141,29 @@ extern const struct _mp_obj_module_t mp_module_ussl;
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&mp_module_ustruct }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_re), (mp_obj_t)&mp_module_ure }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_heapq), (mp_obj_t)&mp_module_uheapq }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&mp_module_uos }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&mp_module_utime }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_select), (mp_obj_t)&mp_module_uselect }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&mp_module_usocket }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_hashlib), (mp_obj_t)&mp_module_uhashlib }, \
{ 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 }, \
// extra constants
#define MICROPY_PORT_CONSTANTS \
{ MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&machine_module }, \
// vm state and root pointers for the gc
#define MP_STATE_PORT MP_STATE_VM
#define MICROPY_PORT_ROOT_POINTERS \
const char *readline_hist[8]; \
mp_obj_t mp_const_user_interrupt; \
mp_obj_t pyb_config_main; \
mp_obj_list_t pybsleep_obj_list; \
mp_obj_list_t mpcallback_obj_list; \
mp_obj_t machine_config_main; \
mp_obj_list_t pyb_sleep_obj_list; \
mp_obj_list_t mp_irq_obj_list; \
mp_obj_list_t pyb_timer_channel_obj_list; \
mp_obj_list_t mount_obj_list; \
struct _pyb_uart_obj_t *pyb_uart_objs[2]; \
struct _os_term_dup_obj_t *os_term_dup_obj; \
// type definitions for the specific machine
@@ -191,7 +207,6 @@ void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len);
#define MICROPY_HAL_H "cc3200_hal.h"
#define MICROPY_PORT_HAS_TELNET (1)
#define MICROPY_PORT_HAS_FTP (1)
#define MICROPY_PORT_WLAN_URN (0)
#define MICROPY_PY_SYS_PLATFORM "WiPy"
#define MICROPY_PORT_WLAN_AP_SSID "wipy-wlan"

View File

@@ -61,13 +61,14 @@
#include "mpexception.h"
#include "random.h"
#include "pybi2c.h"
#include "pybsd.h"
#include "pins.h"
#include "pybsleep.h"
#include "pybtimer.h"
#include "mpcallback.h"
#include "cryptohash.h"
#include "mpirq.h"
#include "updater.h"
#include "moduos.h"
#include "antenna.h"
/******************************************************************************
DECLARE PRIVATE CONSTANTS
@@ -126,36 +127,18 @@ soft_reset:
// execute all basic initializations
mpexception_init0();
mpcallback_init0();
pybsleep_init0();
mp_irq_init0();
pyb_sleep_init0();
pin_init0();
mperror_init0();
uart_init0();
pin_init0();
timer_init0();
readline_init0();
mod_network_init0();
#if MICROPY_HW_ENABLE_RNG
moduos_init0();
rng_init0();
#endif
#ifdef LAUNCHXL
// configure the stdio uart pins with the correct alternate functions
// param 3 ("mode") is DON'T CARE" for AFs others than GPIO
pin_config ((pin_obj_t *)&MICROPY_STDIO_UART_TX_PIN, MICROPY_STDIO_UART_TX_PIN_AF, 0, PIN_TYPE_STD_PU, PIN_STRENGTH_2MA);
pin_config ((pin_obj_t *)&MICROPY_STDIO_UART_RX_PIN, MICROPY_STDIO_UART_RX_PIN_AF, 0, PIN_TYPE_STD_PU, PIN_STRENGTH_2MA);
// instantiate the stdio uart
mp_obj_t args[2] = {
mp_obj_new_int(MICROPY_STDIO_UART),
mp_obj_new_int(MICROPY_STDIO_UART_BAUD),
};
pyb_stdio_uart = pyb_uart_type.make_new((mp_obj_t)&pyb_uart_type, MP_ARRAY_SIZE(args), 0, args);
// create a callback for the uart, in order to enable the rx interrupts
uart_callback_new (pyb_stdio_uart, mp_const_none, MICROPY_STDIO_UART_RX_BUF_SIZE, INT_PRIORITY_LVL_3);
#else
pyb_stdio_uart = MP_OBJ_NULL;
#endif
pybsleep_reset_cause_t rstcause = pybsleep_get_reset_cause();
pybsleep_reset_cause_t rstcause = pyb_sleep_get_reset_cause();
if (rstcause < PYB_SLP_SOFT_RESET) {
if (rstcause == PYB_SLP_HIB_RESET) {
// when waking up from hibernate we just want
@@ -179,7 +162,7 @@ soft_reset:
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash_slash_lib));
// reset config variables; they should be set by boot.py
MP_STATE_PORT(pyb_config_main) = MP_OBJ_NULL;
MP_STATE_PORT(machine_config_main) = MP_OBJ_NULL;
if (!safeboot) {
// run boot.py
@@ -203,10 +186,10 @@ soft_reset:
// run the main script from the current directory.
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
const char *main_py;
if (MP_STATE_PORT(pyb_config_main) == MP_OBJ_NULL) {
if (MP_STATE_PORT(machine_config_main) == MP_OBJ_NULL) {
main_py = "main.py";
} else {
main_py = mp_obj_str_get_str(MP_STATE_PORT(pyb_config_main));
main_py = mp_obj_str_get_str(MP_STATE_PORT(machine_config_main));
}
int ret = pyexec_file(main_py);
if (ret & PYEXEC_FORCED_EXIT) {
@@ -236,13 +219,15 @@ soft_reset:
soft_reset_exit:
// soft reset
pybsleep_signal_soft_reset();
pyb_sleep_signal_soft_reset();
mp_printf(&mp_plat_print, "PYB: soft reboot\n");
// disable all peripherals that could trigger a callback
pyb_rtc_callback_disable(NULL);
timer_disable_all();
uart_disable_all();
// disable all callbacks to avoid undefined behaviour
// when coming out of a soft reset
mp_irq_disable_all();
// cancel the RTC alarm which might be running independent of the irq state
pyb_rtc_disable_alarm();
// flush the serial flash buffer
sflash_disk_flush();
@@ -250,10 +235,6 @@ soft_reset_exit:
// clean-up the user socket space
modusocket_close_all_user_sockets();
#if MICROPY_HW_HAS_SDCARD
pybsd_deinit();
#endif
// wait for pending transactions to complete
HAL_Delay(20);
@@ -265,9 +246,8 @@ soft_reset_exit:
******************************************************************************/
__attribute__ ((section (".boot")))
STATIC void mptask_pre_init (void) {
#if MICROPY_HW_ENABLE_RTC
pybrtc_init();
#endif
// this one only makes sense after a poweron reset
pyb_rtc_pre_init();
// Create the simple link spawn task
ASSERT (OSI_OK == VStartSimpleLinkSpawnTask(SIMPLELINK_SPAWN_TASK_PRIORITY));
@@ -276,7 +256,7 @@ STATIC void mptask_pre_init (void) {
ASSERT ((sflash_fatfs = mem_Malloc(sizeof(FATFS))) != NULL);
// this one allocates memory for the nvic vault
pybsleep_pre_init();
pyb_sleep_pre_init();
// this one allocates memory for the WLAN semaphore
wlan_pre_init();
@@ -284,14 +264,10 @@ STATIC void mptask_pre_init (void) {
// this one allocates memory for the updater semaphore
updater_pre_init();
// this one allocates memory for the Socket semaphore
// this one allocates memory for the socket semaphore
modusocket_pre_init();
#if MICROPY_HW_HAS_SDCARD
pybsd_init0();
#endif
CRYPTOHASH_Init();
//CRYPTOHASH_Init();
#ifdef DEBUG
ASSERT (OSI_OK == osi_TaskCreate(TASK_Servers,
@@ -374,11 +350,11 @@ STATIC void mptask_init_sflash_filesystem (void) {
STATIC void mptask_enter_ap_mode (void) {
// append the mac only if it's not the first boot
bool append_mac = !PRCMGetSpecialBit(PRCM_FIRST_BOOT_BIT);
bool add_mac = !PRCMGetSpecialBit(PRCM_FIRST_BOOT_BIT);
// enable simplelink in ap mode (use the MAC address to make the ssid unique)
wlan_sl_enable (ROLE_AP, MICROPY_PORT_WLAN_AP_SSID, strlen(MICROPY_PORT_WLAN_AP_SSID), MICROPY_PORT_WLAN_AP_SECURITY,
MICROPY_PORT_WLAN_AP_KEY, strlen(MICROPY_PORT_WLAN_AP_KEY), MICROPY_PORT_WLAN_AP_CHANNEL, append_mac);
wlan_sl_init (ROLE_AP, MICROPY_PORT_WLAN_AP_SSID, strlen(MICROPY_PORT_WLAN_AP_SSID),
MICROPY_PORT_WLAN_AP_SECURITY, MICROPY_PORT_WLAN_AP_KEY, strlen(MICROPY_PORT_WLAN_AP_KEY),
MICROPY_PORT_WLAN_AP_CHANNEL, ANTENNA_TYPE_INTERNAL, add_mac);
}
STATIC void mptask_create_main_py (void) {
@@ -390,10 +366,3 @@ STATIC void mptask_create_main_py (void) {
f_close(&fp);
}
STATIC mp_obj_t pyb_main(mp_obj_t main) {
if (MP_OBJ_IS_STR(main)) {
MP_STATE_PORT(pyb_config_main) = main;
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(pyb_main_obj, pyb_main);

View File

@@ -25,49 +25,46 @@
* THE SOFTWARE.
*/
// qstrs specific to this port
Q(__name__)
Q(help)
Q(pyb)
// for machine module
Q(machine)
#ifdef DEBUG
Q(info)
#endif
Q(reset)
Q(main)
Q(sync)
Q(gc)
Q(rng)
Q(delay)
Q(time)
Q(open)
Q(on)
Q(off)
Q(toggle)
Q(write)
Q(read)
Q(readall)
Q(readline)
Q(input)
Q(os)
Q(freq)
Q(unique_id)
Q(repl_info)
Q(disable_irq)
Q(enable_irq)
Q(millis)
Q(micros)
Q(elapsed_millis)
Q(elapsed_micros)
Q(udelay)
Q(flush)
Q(FileIO)
Q(enable)
Q(disable)
// Entries for sys.path
Q(idle)
Q(sleep)
Q(deepsleep)
Q(reset_cause)
Q(wake_reason)
Q(IDLE)
Q(SLEEP)
Q(DEEPSLEEP)
Q(POWER_ON)
Q(HARD_RESET)
Q(WDT_RESET)
Q(DEEPSLEEP_RESET)
Q(SOFT_RESET)
Q(WLAN_WAKE)
Q(PIN_WAKE)
Q(RTC_WAKE)
// for wipy module
Q(wipy)
Q(heartbeat)
// entries for sys.path
Q(/flash)
Q(/flash/lib)
#if MICROPY_HW_HAS_SDCARD
Q(/sd)
Q(/sd/lib)
#endif
// interactive help
Q(help)
// for module weak links
Q(struct)
@@ -75,11 +72,11 @@ Q(binascii)
Q(re)
Q(json)
Q(heapq)
Q(hashlib)
//Q(hashlib)
// for os module
Q(uos)
Q(os)
Q(uos)
Q(sysname)
Q(nodename)
Q(release)
@@ -88,9 +85,6 @@ Q(machine)
Q(uname)
Q(/)
Q(flash)
#if MICROPY_HW_HAS_SDCARD
Q(sd)
#endif
Q(chdir)
Q(getcwd)
Q(listdir)
@@ -103,105 +97,129 @@ Q(sep)
Q(stat)
Q(urandom)
Q(mkfs)
Q(mount)
Q(unmount)
Q(dupterm)
Q(readonly)
Q(readblocks)
Q(writeblocks)
Q(sync)
Q(count)
// for file class
Q(seek)
Q(tell)
Q(input)
Q(flush)
// for Pin class
Q(Pin)
Q(cpu)
Q(board)
Q(init)
Q(value)
Q(low)
Q(high)
Q(toggle)
Q(info)
Q(name)
Q(af)
Q(id)
Q(mode)
Q(type)
Q(strength)
Q(pull)
Q(drive)
Q(alt)
Q(alt_list)
Q(IN)
Q(OUT)
Q(STD)
Q(STD_PU)
Q(STD_PD)
Q(OD)
Q(OD_PU)
Q(OD_PD)
Q(INT_RISING)
Q(INT_FALLING)
Q(INT_RISING_FALLING)
Q(INT_LOW_LEVEL)
Q(INT_HIGH_LEVEL)
Q(S2MA)
Q(S4MA)
Q(S6MA)
Q(OPEN_DRAIN)
Q(ALT)
Q(ALT_OPEN_DRAIN)
Q(PULL_UP)
Q(PULL_DOWN)
Q(LOW_POWER)
Q(MED_POWER)
Q(HIGH_POWER)
Q(IRQ_RISING)
Q(IRQ_FALLING)
Q(IRQ_LOW_LEVEL)
Q(IRQ_HIGH_LEVEL)
// for UART class
Q(UART)
Q(init)
Q(deinit)
Q(any)
Q(sendbreak)
Q(id)
Q(baudrate)
Q(bits)
Q(stop)
Q(parity)
Q(init)
Q(deinit)
Q(all)
Q(writechar)
Q(readchar)
Q(sendbreak)
Q(readinto)
Q(read_buf_len)
Q(timeout)
Q(timeout_char)
Q(repl_uart)
Q(flow)
Q(RTS)
Q(CTS)
Q(pins)
Q(EVEN)
Q(ODD)
Q(RX_ANY)
// for I2C class
Q(I2C)
Q(id)
Q(mode)
Q(baudrate)
Q(pins)
Q(addr)
Q(data)
Q(timeout)
Q(nbytes)
Q(buf)
Q(stop)
Q(memaddr)
Q(addr_size)
Q(addrsize)
Q(init)
Q(deinit)
Q(is_ready)
Q(scan)
Q(send)
Q(recv)
Q(mem_read)
Q(mem_write)
Q(readfrom)
Q(readfrom_into)
Q(writeto)
Q(readfrom_mem)
Q(readfrom_mem_into)
Q(writeto_mem)
Q(MASTER)
// for ADC class
Q(ADC)
Q(read)
Q(ADCChannel)
Q(value)
Q(init)
Q(deinit)
Q(channel)
Q(id)
Q(pin)
#if MICROPY_HW_HAS_SDCARD
// for SD class
Q(SD)
Q(enable)
Q(disable)
#endif
Q(init)
Q(deinit)
Q(id)
Q(pins)
// for RTC class
Q(RTC)
Q(id)
Q(init)
Q(alarm)
Q(alarm_left)
Q(alarm_cancel)
Q(now)
Q(deinit)
Q(datetime)
Q(repeat)
Q(ALARM0)
// for time class
Q(time)
Q(utime)
Q(localtime)
Q(mktime)
Q(sleep)
Q(time)
Q(sleep_ms)
Q(sleep_us)
Q(ticks_ms)
Q(ticks_us)
Q(ticks_cpu)
Q(ticks_diff)
// for select class
Q(select)
@@ -234,14 +252,11 @@ Q(protocol)
Q(error)
Q(timeout)
Q(AF_INET)
Q(AF_INET6)
Q(SOCK_STREAM)
Q(SOCK_DGRAM)
Q(SOCK_RAW)
Q(IPPROTO_SEC)
Q(IPPROTO_TCP)
Q(IPPROTO_UDP)
Q(IPPROTO_RAW)
// for ssl class
Q(ssl)
@@ -260,101 +275,79 @@ Q(CERT_REQUIRED)
// for network class
Q(network)
Q(server_running)
Q(server_login)
Q(server_timeout)
Q(server)
Q(init)
Q(deinit)
Q(login)
Q(timeout)
Q(isrunning)
// for WLAN class
Q(WLAN)
Q(iwconfig)
Q(key)
Q(security)
Q(id)
Q(init)
Q(mode)
Q(auth)
Q(ssid)
Q(bssid)
Q(mac)
Q(antenna)
Q(scan)
Q(connect)
Q(isconnected)
Q(disconnect)
Q(sec)
Q(channel)
Q(rssi)
Q(ifconfig)
Q(info)
Q(connections)
#if MICROPY_PORT_WLAN_URN
Q(urn)
#endif
Q(mode)
Q(ip)
Q(subnet)
Q(gateway)
Q(dns)
Q(mac)
Q(antenna)
Q(config)
//Q(connections)
//Q(urn)
Q(STA)
Q(AP)
Q(OPEN)
Q(WEP)
Q(WPA)
Q(WPA2)
Q(INTERNAL)
Q(EXTERNAL)
Q(INT_ANT)
Q(EXT_ANT)
Q(ANY_EVENT)
// for WDT class
Q(WDT)
Q(kick)
Q(feed)
Q(timeout)
// for HeartBeat class
Q(HeartBeat)
Q(enable)
Q(disable)
// for callback class
// for irq class
Q(irq)
Q(init)
Q(enable)
Q(disable)
Q(callback)
Q(flags)
Q(trigger)
Q(handler)
Q(mode)
Q(value)
Q(priority)
Q(wakes)
// for Sleep class
Q(Sleep)
Q(idle)
Q(suspend)
Q(hibernate)
Q(reset_cause)
Q(wake_reason)
Q(ACTIVE)
Q(SUSPENDED)
Q(HIBERNATING)
Q(POWER_ON)
Q(HARD_RESET)
Q(WDT_RESET)
Q(HIB_RESET)
Q(SOFT_RESET)
Q(WLAN_WAKE)
Q(PIN_WAKE)
Q(RTC_WAKE)
Q(wake)
// for SPI class
Q(SPI)
Q(id)
Q(mode)
Q(baudrate)
Q(bits)
Q(polarity)
Q(phase)
Q(nss)
Q(firstbit)
Q(init)
Q(deinit)
Q(send)
Q(recv)
Q(send_recv)
Q(timeout)
Q(write)
Q(read)
Q(readinto)
Q(write_readinto)
Q(nbytes)
Q(buf)
Q(MASTER)
Q(ACTIVE_LOW)
Q(ACTIVE_HIGH)
Q(MSB)
// for Timer class
Q(Timer)
@@ -382,12 +375,12 @@ Q(POSITIVE)
Q(NEGATIVE)
// for uhashlib module
Q(uhashlib)
Q(update)
Q(digest)
//Q(uhashlib)
//Q(update)
//Q(digest)
//Q(md5)
Q(sha1)
Q(sha256)
//Q(sha1)
//Q(sha256)
// for ubinascii module
Q(ubinascii)

View File

@@ -30,6 +30,7 @@
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/misc.h"
#include "py/nlr.h"
#include "serverstask.h"
#include "simplelink.h"
#include "debug.h"
@@ -37,17 +38,9 @@
#include "ftp.h"
#include "pybwdt.h"
#include "modusocket.h"
#include "mpexception.h"
/******************************************************************************
DECLARE PRIVATE DEFINITIONS
******************************************************************************/
#define SERVERS_DEF_USER "micro"
#define SERVERS_DEF_PASS "python"
#define SERVERS_DEF_TIMEOUT_MS 300000 // 5 minutes
#define SERVERS_MIN_TIMEOUT_MS 5000 // 5 seconds
/******************************************************************************
DEFINE PRIVATE TYPES
******************************************************************************/
@@ -144,7 +137,7 @@ void TASK_Servers (void *pvParameters) {
void servers_start (void) {
servers_data.do_enable = true;
HAL_Delay (SERVERS_CYCLE_TIME_MS * 5);
HAL_Delay (SERVERS_CYCLE_TIME_MS * 3);
}
void servers_stop (void) {
@@ -152,7 +145,7 @@ void servers_stop (void) {
do {
HAL_Delay (SERVERS_CYCLE_TIME_MS);
} while (servers_are_enabled());
HAL_Delay (SERVERS_CYCLE_TIME_MS * 5);
HAL_Delay (SERVERS_CYCLE_TIME_MS * 3);
}
void servers_reset (void) {
@@ -177,16 +170,19 @@ void servers_close_socket (int16_t *sd) {
}
void servers_set_login (char *user, char *pass) {
if (strlen(user) > SERVERS_USER_PASS_LEN_MAX || strlen(pass) > SERVERS_USER_PASS_LEN_MAX) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
memcpy(servers_user, user, SERVERS_USER_PASS_LEN_MAX);
memcpy(servers_pass, pass, SERVERS_USER_PASS_LEN_MAX);
}
bool servers_set_timeout (uint32_t timeout) {
void servers_set_timeout (uint32_t timeout) {
if (timeout < SERVERS_MIN_TIMEOUT_MS) {
return false;
// timeout is too low
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
servers_data.timeout = timeout;
return true;
}
uint32_t servers_get_timeout (void) {

View File

@@ -31,14 +31,19 @@
DEFINE CONSTANTS
******************************************************************************/
#define SERVERS_PRIORITY 2
#define SERVERS_STACK_SIZE 1072
#define SERVERS_STACK_SIZE 1024
#define SERVERS_SSID_LEN_MAX 16
#define SERVERS_KEY_LEN_MAX 16
#define SERVERS_USER_PASS_LEN_MAX 16
#define SERVERS_USER_PASS_LEN_MAX 32
#define SERVERS_CYCLE_TIME_MS 5
#define SERVERS_CYCLE_TIME_MS 2
#define SERVERS_DEF_USER "micro"
#define SERVERS_DEF_PASS "python"
#define SERVERS_DEF_TIMEOUT_MS 300000 // 5 minutes
#define SERVERS_MIN_TIMEOUT_MS 5000 // 5 seconds
/******************************************************************************
DEFINE TYPES
@@ -61,7 +66,7 @@ extern bool servers_are_enabled (void);
extern void servers_close_socket (int16_t *sd);
extern void servers_set_login (char *user, char *pass);
extern void server_sleep_sockets (void);
extern bool servers_set_timeout (uint32_t timeout);
extern void servers_set_timeout (uint32_t timeout);
extern uint32_t servers_get_timeout (void);
#endif /* SERVERSTASK_H_ */

View File

@@ -457,7 +457,7 @@ OsiReturnVal_e VStartSimpleLinkSpawnTask(unsigned portBASE_TYPE uxPriority)
ASSERT (xSimpleLinkSpawnQueue != NULL);
ASSERT (pdPASS == xTaskCreate( vSimpleLinkSpawnTask, ( portCHAR * ) "SLSPAWN",\
736 / sizeof(portSTACK_TYPE), NULL, uxPriority, &xSimpleLinkSpawnTaskHndl ));
896 / sizeof(portSTACK_TYPE), NULL, uxPriority, &xSimpleLinkSpawnTaskHndl ));
return OSI_OK;
}

View File

@@ -108,7 +108,7 @@ typedef struct {
DECLARE PRIVATE DATA
******************************************************************************/
static telnet_data_t telnet_data;
static const char* telnet_welcome_msg = "Micro Python " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n";
static const char* telnet_welcome_msg = "MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n";
static const char* telnet_request_user = "Login as: ";
static const char* telnet_request_password = "Password: ";
static const char* telnet_invalid_loggin = "\r\nInvalid credentials, try again.\r\n";
@@ -244,34 +244,14 @@ void telnet_run (void) {
}
void telnet_tx_strn (const char *str, int len) {
if (len > 0 && telnet_data.n_sd > 0) {
if (telnet_data.n_sd > 0 && telnet_data.state == E_TELNET_STE_LOGGED_IN && len > 0) {
telnet_send_with_retries(telnet_data.n_sd, str, len);
}
}
void telnet_tx_strn_cooked (const char *str, uint len) {
int32_t nslen = 0;
const char *_str = str;
for (int i = 0; i < len; i++) {
if (str[i] == '\n') {
telnet_send_with_retries(telnet_data.n_sd, _str, nslen);
telnet_send_with_retries(telnet_data.n_sd, "\r\n", 2);
_str += nslen + 1;
nslen = 0;
}
else {
nslen++;
}
}
if (_str < str + len) {
telnet_send_with_retries(telnet_data.n_sd, _str, nslen);
}
}
bool telnet_rx_any (void) {
return (telnet_data.n_sd > 0) ? ((telnet_data.rxRindex != telnet_data.rxWindex) &&
(telnet_data.state == E_TELNET_STE_LOGGED_IN)) : false;
return (telnet_data.n_sd > 0) ? (telnet_data.rxRindex != telnet_data.rxWindex &&
telnet_data.state == E_TELNET_STE_LOGGED_IN) : false;
}
int telnet_rx_char (void) {
@@ -300,14 +280,6 @@ void telnet_reset (void) {
telnet_data.state = E_TELNET_STE_START;
}
bool telnet_is_enabled (void) {
return telnet_data.enabled;
}
bool telnet_is_active (void) {
return (telnet_data.state == E_TELNET_STE_LOGGED_IN);
}
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/

View File

@@ -33,13 +33,10 @@
extern void telnet_init (void);
extern void telnet_run (void);
extern void telnet_tx_strn (const char *str, int len);
extern void telnet_tx_strn_cooked (const char *str, uint len);
extern bool telnet_rx_any (void);
extern int telnet_rx_char (void);
extern void telnet_enable (void);
extern void telnet_disable (void);
extern void telnet_reset (void);
extern bool telnet_is_enabled (void);
extern bool telnet_is_active (void);
#endif /* TELNET_H_ */

View File

@@ -1,4 +1,6 @@
import pyb
from machine import Pin
from machine import RTC
import time
import os
"""
@@ -7,51 +9,51 @@ Execute it like this:
python3 run-tests --target wipy --device 192.168.1.1 ../cc3200/tools/smoke.py
"""
pin_map = [2, 1, 23, 24, 11, 12, 13, 14, 15, 16, 17, 22, 28, 10, 9, 8, 7, 6, 30, 31, 3, 0, 4, 5]
test_bytes = os.urandom(2048)
pin_map = [23, 24, 11, 12, 13, 14, 15, 16, 17, 22, 28, 10, 9, 8, 7, 6, 30, 31, 3, 0, 4, 5]
test_bytes = os.urandom(1024)
def test_pin_read (type):
def test_pin_read (pull):
# enable the pull resistor on all pins, then read the value
for p in pin_map:
pin = pyb.Pin('GP' + str(p), af= 0, mode=pyb.Pin.IN, type=type)
pin = Pin('GP' + str(p), mode=Pin.IN, pull=pull)
# read the pin value
print (pin.value())
print(pin())
def test_pin_shorts (type):
if type == pyb.Pin.STD_PU:
type_inverted = pyb.Pin.STD_PD
def test_pin_shorts (pull):
if pull == Pin.PULL_UP:
pull_inverted = Pin.PULL_DOWN
else:
type_inverted = pyb.Pin.STD_PU
pull_inverted = Pin.PULL_UP
# enable all pulls of the specified type
for p in pin_map:
pin = pyb.Pin('GP' + str(p), af= 0, mode=pyb.Pin.IN, type=type_inverted)
pin = Pin('GP' + str(p), mode=Pin.IN, pull=pull_inverted)
# then change the pull one pin at a time and read its value
i = 0
while i < len(pin_map):
pin = pyb.Pin('GP' + str(pin_map[i]), af= 0, mode=pyb.Pin.IN, type=type)
pyb.Pin('GP' + str(pin_map[i - 1]), af= 0, mode=pyb.Pin.IN, type=type_inverted)
pin = Pin('GP' + str(pin_map[i]), mode=Pin.IN, pull=pull)
Pin('GP' + str(pin_map[i - 1]), mode=Pin.IN, pull=pull_inverted)
i += 1
# read the pin value
print (pin.value())
print(pin())
test_pin_read(pyb.Pin.STD_PU)
test_pin_read(pyb.Pin.STD_PD)
test_pin_shorts(pyb.Pin.STD_PU)
test_pin_shorts(pyb.Pin.STD_PD)
test_pin_read(Pin.PULL_UP)
test_pin_read(Pin.PULL_DOWN)
test_pin_shorts(Pin.PULL_UP)
test_pin_shorts(Pin.PULL_DOWN)
# create a test directory
os.mkdir('/flash/test')
os.chdir('/flash/test')
print(os.getcwd())
# create a new file
f = open ('test.txt', 'w')
n_w = f.write (test_bytes)
print (n_w == len(test_bytes))
f = open('test.txt', 'w')
n_w = f.write(test_bytes)
print(n_w == len(test_bytes))
f.close()
f = open('test.txt', 'r')
r = bytes(f.readall(), 'ascii')
# check that we can write and read it correctly
print (r == test_bytes)
print(r == test_bytes)
f.close()
os.remove('test.txt')
os.chdir('..')
@@ -61,3 +63,14 @@ ls = os.listdir()
print('test' not in ls)
print(ls)
# test the real time clock
rtc = RTC()
while rtc.now()[6] > 800:
pass
time1 = rtc.now()
time.sleep_ms(1000)
time2 = rtc.now()
print(time2[5] - time1[5] == 1)
print(time2[6] - time1[6] < 5000) # microseconds

View File

@@ -20,10 +20,6 @@
1
1
1
1
1
0
0
0
0
0
@@ -68,8 +64,6 @@
1
1
1
1
1
0
0
0
@@ -92,10 +86,10 @@
0
0
0
0
0
/flash
/flash/test
True
True
True
['main.py', 'sys', 'lib', 'cert', 'boot.py']
True
True

View File

@@ -22,6 +22,27 @@ def print_exception(e):
print ('Exception: {}, on line {}'.format(e, sys.exc_info()[-1].tb_lineno))
def execute(command):
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
cmd_log = ""
# Poll process for new output until finished
while True:
nextline = process.stdout.readline()
if nextline == '' and process.poll() != None:
break
sys.stdout.write(nextline)
sys.stdout.flush()
cmd_log += nextline
output = process.communicate()[0]
exitCode = process.returncode
if exitCode == 0:
return cmd_log
else:
raise ProcessException(command, exitCode, output)
def main():
cmd_parser = argparse.ArgumentParser(description='Flash the WiPy and optionally run a small test on it.')
cmd_parser.add_argument('-u', '--uniflash', default=None, help='the path to the uniflash cli executable')
@@ -30,7 +51,7 @@ def main():
cmd_parser.add_argument('-s', '--servicepack', default=None, help='the path to the servicepack file')
args = cmd_parser.parse_args()
result = 1
output = ""
com_port = 'com=' + str(args.port)
servicepack_path = 'spPath=' + args.servicepack
@@ -38,19 +59,23 @@ def main():
if args.uniflash == None or args.config == None:
raise ValueError('uniflash path and config path are mandatory')
if args.servicepack == None:
subprocess.check_call([args.uniflash, '-config', args.config, '-setOptions', com_port, '-operations', 'format', 'program'], stderr=subprocess.STDOUT)
output += execute([args.uniflash, '-config', args.config, '-setOptions', com_port, '-operations', 'format', 'program'])
else:
subprocess.check_call([args.uniflash, '-config', args.config, '-setOptions', com_port, servicepack_path, '-operations', 'format', 'servicePackUpdate', 'program'], stderr=subprocess.STDOUT)
result = 0
output += execute([args.uniflash, '-config', args.config, '-setOptions', com_port, servicepack_path, '-operations', 'format', 'servicePackUpdate', 'program'])
except Exception as e:
print_exception(e)
output = ""
finally:
if result:
print ("ERROR: Programming failed!")
if "Finish Executing operation: program" in output:
print("======================================")
print("Board programmed OK")
print("======================================")
sys.exit(0)
else:
print ("Board programmed OK")
sys.exit(result)
print("======================================")
print("ERROR: Programming failed!")
print("======================================")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@@ -17,6 +17,7 @@ Or:
import sys
import argparse
import time
import socket
from ftplib import FTP
from telnetlib import Telnet
@@ -89,9 +90,9 @@ def reset_board(args):
time.sleep(1)
tn.write(b'\r\x02') # ctrl-B: enter friendly REPL
if b'Type "help()" for more information.' in tn.read_until(b'Type "help()" for more information.', timeout=5):
tn.write(b"import pyb\r\n")
tn.write(b"pyb.reset()\r\n")
time.sleep(1)
tn.write(b"import machine\r\n")
tn.write(b"machine.reset()\r\n")
time.sleep(2)
print("Reset performed")
success = True
else:
@@ -121,12 +122,23 @@ def verify_update(args):
print("Error: verification failed, the git tag doesn't match")
return False
try:
# Specify a longer time out value here because the board has just been
# reset and the wireless connection might not be fully established yet
tn = Telnet(args.ip, timeout=15)
print("Connected via telnet again, lets check the git tag")
retries = 0
while True:
try:
# Specify a longer time out value here because the board has just been
# reset and the wireless connection might not be fully established yet
tn = Telnet(args.ip, timeout=10)
print("Connected via telnet again, lets check the git tag")
break
except socket.timeout:
if retries < 5:
print("Timeout while connecting via telnet, retrying...")
retries += 1
else:
print('Error: Telnet connection timed out!')
return False
try:
firmware_tag = tn.read_until (b'with CC3200')
tag_file_path = args.file.rstrip('mcuimg.bin') + 'genhdr/mpversion.h'
@@ -170,10 +182,9 @@ def main():
if reset_board(args):
if args.verify:
print ('Waiting for the WiFi connection to come up again...')
# this time is to allow the system's wireless network card to connect to the
# WiPy again. Sometimes it might only take a couple of seconds, but let's
# leave 15s to be on the safe side
time.sleep(15)
# this time is to allow the system's wireless network card to
# connect to the WiPy again.
time.sleep(5)
if verify_update(args):
result = 0
else:

View File

@@ -41,7 +41,6 @@
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
__attribute__ ((section (".boot")))
void CRYPTOHASH_Init (void) {
// Enable the Data Hashing and Transform Engine
MAP_PRCMPeripheralClkEnable(PRCM_DTHE, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);

View File

@@ -32,22 +32,21 @@
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "rom_map.h"
#include "prcm.h"
#include "pybrtc.h"
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
#include "random.h"
#include "debug.h"
/******************************************************************************
* LOCAL TYPES
******************************************************************************/
typedef union Id_t {
typedef union _rng_id_t {
uint32_t id32;
uint16_t id16[3];
uint8_t id8[6];
} Id_t;
} rng_id_t;
/******************************************************************************
* LOCAL VARIABLES
@@ -57,45 +56,38 @@ static uint32_t s_seed;
/******************************************************************************
* LOCAL FUNCTION DECLARATIONS
******************************************************************************/
static uint32_t lfsr (uint32_t input);
STATIC uint32_t lfsr (uint32_t input);
/******************************************************************************
* PRIVATE FUNCTIONS
******************************************************************************/
static uint32_t lfsr (uint32_t input) {
STATIC uint32_t lfsr (uint32_t input) {
assert( input != 0 );
/*lint -save -e501*/
return (input >> 1) ^ (-(input & 0x01) & 0x00E10000);
/*lint -restore*/
}
#if MICROPY_HW_ENABLE_RNG
/// \moduleref rng
/******************************************************************************/
// Micro Python bindings;
/// \function rng()
/// Return a 24-bit hardware generated random number.
STATIC mp_obj_t pyb_rng_get(void) {
STATIC mp_obj_t machine_rng_get(void) {
return mp_obj_new_int(rng_get());
}
MP_DEFINE_CONST_FUN_OBJ_0(pyb_rng_get_obj, pyb_rng_get);
#endif
MP_DEFINE_CONST_FUN_OBJ_0(machine_rng_get_obj, machine_rng_get);
/******************************************************************************
* PUBLIC FUNCTIONS
******************************************************************************/
void rng_init0 (void) {
Id_t juggler;
rng_id_t juggler;
uint32_t seconds;
uint16_t mseconds;
// get the seconds and the milliseconds from the RTC
MAP_PRCMRTCGet(&seconds, &mseconds);
pyb_rtc_get_time(&seconds, &mseconds);
wlan_get_mac (juggler.id8);
// Flatten the 48-bit board identification to 24 bits
// flatten the 48-bit board identification to 24 bits
juggler.id16[0] ^= juggler.id16[2];
juggler.id8[0] ^= juggler.id8[3];
@@ -104,7 +96,8 @@ void rng_init0 (void) {
s_seed = juggler.id32 & 0x00FFFFFF;
s_seed += (seconds & 0x000FFFFF) + mseconds;
// The seed must not be zero
// the seed must not be zero
if (s_seed == 0) {
s_seed = 1;
}

View File

@@ -30,8 +30,6 @@
void rng_init0 (void);
uint32_t rng_get (void);
#if MICROPY_HW_ENABLE_RNG
MP_DECLARE_CONST_FUN_OBJ(pyb_rng_get_obj);
#endif
MP_DECLARE_CONST_FUN_OBJ(machine_rng_get_obj);
#endif // __RANDOM_H

View File

@@ -7,7 +7,7 @@
@ global variable with the backup registers
.extern vault_arm_registers
@ global function that performs the wake up actions
.extern pybsleep_suspend_exit
.extern pyb_sleep_suspend_exit
@ uint sleep_store(void)
.global sleep_store
@@ -58,4 +58,4 @@ sleep_restore:
msr basepri, r0
dsb
isb
bl pybsleep_suspend_exit
bl pyb_sleep_suspend_exit

View File

@@ -27,6 +27,6 @@
#ifndef VERSION_H_
#define VERSION_H_
#define WIPY_SW_VERSION_NUMBER "0.9.1"
#define WIPY_SW_VERSION_NUMBER "1.1.0"
#endif /* VERSION_H_ */

View File

@@ -58,9 +58,9 @@ copyright = '2014, Damien P. George'
# built documents.
#
# The short X.Y version.
version = '1.4'
version = '1.5'
# The full version, including alpha/beta/rc tags.
release = '1.4.5'
release = '1.5'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -300,6 +300,11 @@ html_context = {
# 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'

View File

@@ -10,18 +10,12 @@ The ``esp`` module contains specific functions related to the ESP8266 module.
Functions
---------
.. function:: status()
.. function:: mac([address])
Return the current status of the wireless connection.
Get or set the network interface's MAC address.
The possible statuses are defined as constants:
* ``STAT_IDLE`` -- no connection and no activity,
* ``STAT_CONNECTING`` -- connecting in progress,
* ``STAT_WRONG_PASSWORD`` -- failed due to incorrect password,
* ``STAT_NO_AP_FOUND`` -- failed because no access point replied,
* ``STAT_CONNECT_FAIL`` -- failed due to other problems,
* ``STAT_GOT_IP`` -- connection susccessful.
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))
@@ -31,6 +25,61 @@ Functions
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.
If the ``sleep_type`` parameter is provided, sets the sleep type to its
value. If the function is called wihout parameters, returns the current
sleep type.
The possible sleep types are defined as constants:
* ``SLEEP_NONE`` -- all functions enabled,
* ``SLEEP_MODEM`` -- modem sleep, shuts down the WiFi Modem circuit.
* ``SLEEP_LIGHT`` -- light sleep, shuts down the WiFi Modem circuit
and suspends the processor periodically.
The system enters the set sleep mode automatically when possible.
.. function:: deepsleep(time=0)
Enter deep sleep.
The whole module powers down, except for the RTC clock circuit, which can
be used to restart the module after the specified time if the pin 16 is
connected to the reset pin. Otherwise the module will sleep until manually
reset.
.. function:: flash_id()
Read the device ID of the flash memory.
Classes
-------

View File

@@ -74,12 +74,12 @@ it will fallback to loading the built-in ``ujson`` module.
Libraries specific to the pyboard
---------------------------------
The following libraries are specific to the pyboard.
.. toctree::
:maxdepth: 2
pyb.rst
network.rst
@@ -87,13 +87,12 @@ it will fallback to loading the built-in ``ujson`` module.
.. toctree::
:maxdepth: 1
ubinascii.rst
uhashlib.rst
uheapq.rst
ujson.rst
ure.rst
usocket.rst
ussl.rst
.. only:: port_wipy
@@ -105,8 +104,9 @@ it will fallback to loading the built-in ``ujson`` module.
.. toctree::
:maxdepth: 2
pyb.rst
machine.rst
network.rst
wipy.rst
.. only:: port_esp8266

View File

@@ -0,0 +1,73 @@
.. _machine.ADC:
class ADC -- analog to digital conversion
=========================================
Usage::
import machine
adc = machine.ADC() # create an ADC object
apin = adc.channel(pin='GP3') # create an analog pin on GP3
val = apin() # read an analog value
Constructors
------------
.. class:: machine.ADC(id=0, \*, bits=12)
Create an ADC object associated with the given pin.
This allows you to then read analog values on that pin.
For more info check the `pinout and alternate functions
table. <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
.. warning::
ADC pin input range is 0-1.4V (being 1.8V the absolute maximum that it
can withstand). When GP2, GP3, GP4 or GP5 are remapped to the
ADC block, 1.8 V is the maximum. If these pins are used in digital mode,
then the maximum allowed input is 3.6V.
Methods
-------
.. method:: adc.channel(id, \*, pin)
Create an analog pin. If only channel ID is given, the correct pin will
be selected. Alternatively, only the pin can be passed and the correct
channel will be selected. Examples::
# all of these are equivalent and enable ADC channel 1 on GP3
apin = adc.channel(1)
apin = adc.channel(pin='GP3')
apin = adc.channel(id=1, pin='GP3')
.. method:: adc.init()
Enable the ADC block.
.. method:: adc.deinit()
Disable the ADC block.
class ADCChannel --- read analog values from internal or external sources
=========================================================================
ADC channels can be connected to internal points of the MCU or to GPIO pins.
ADC channels are created using the ADC.channel method.
.. method:: adcchannel()
Fast method to read the channel value.
.. method:: adcchannel.value()
Read the channel value.
.. method:: adcchannel.init()
Re-init (and effectively enable) the ADC channel.
.. method:: adcchannel.deinit()
Disable the ADC channel.

View File

@@ -0,0 +1,117 @@
.. _machine.I2C:
class I2C -- a two-wire serial protocol
=======================================
I2C is a two-wire protocol for communicating between devices. At the physical
level it consists of 2 wires: SCL and SDA, the clock and data lines respectively.
I2C objects are created attached to a specific bus. They can be initialised
when created, or initialised later on.
.. only:: port_wipy
Example::
from machine import I2C
i2c = I2C(0) # create on bus 0
i2c = I2C(0, I2C.MASTER) # create and init as a master
i2c.init(I2C.MASTER, baudrate=20000) # init as a master
i2c.deinit() # turn off the peripheral
Printing the i2c object gives you information about its configuration.
.. only:: port_wipy
A master must specify the recipient's address::
i2c.init(I2C.MASTER)
i2c.writeto(0x42, '123') # send 3 bytes to slave with address 0x42
i2c.writeto(addr=0x42, b'456') # keyword for address
Master also has other methods::
i2c.scan() # scan for slaves on the bus, returning
# a list of valid addresses
i2c.readfrom_mem(0x42, 2, 3) # read 3 bytes from memory of slave 0x42,
# starting at address 2 in the slave
i2c.writeto_mem(0x42, 2, 'abc') # write 'abc' (3 bytes) to memory of slave 0x42
# starting at address 2 in the slave, timeout after 1 second
Constructors
------------
.. only:: port_wipy
.. class:: machine.I2C(bus, ...)
Construct an I2C object on the given bus. `bus` can only be 0.
If the bus is not given, the default one will be selected (0).
Methods
-------
.. method:: i2c.deinit()
Turn off the I2C bus.
.. only:: port_wipy
.. method:: i2c.init(mode, \*, baudrate=100000, pins=(SDA, SCL))
Initialise the I2C bus with the given parameters:
- ``mode`` must be ``I2C.MASTER``
- ``baudrate`` is the SCL clock rate
- ``pins`` is an optional tuple with the pins to assign to the I2C bus.
.. method:: i2c.readfrom(addr, nbytes)
Read ``nbytes`` from the slave specified by ``addr``.
Returns a ``bytes`` object with the data read.
.. method:: i2c.readfrom_into(addr, buf)
Read into ``buf`` from the slave specified by ``addr``.
Returns the number of bytes read.
.. method:: i2c.writeto(addr, buf, \*, stop=True)
Write ``buf`` to the slave specified by ``addr``. Set ``stop`` to ``False``
if the transfer should be continued.
Returns the number of bytes written.
.. method:: i2c.readfrom_mem(addr, memaddr, nbytes, \*, addrsize=8)
Read ``nbytes`` from the slave specified by ``addr`` starting from the memory
address specified by ``memaddr``.
Param ``addrsize`` specifies the address size in bits.
Returns a ``bytes`` object with the data read.
.. method:: i2c.readfrom_mem_into(addr, memaddr, buf, \*, addrsize=8)
Read into ``buf`` from the slave specified by ``addr`` starting from the memory
address specified by ``memaddr``.
Param ``addrsize`` specifies the address size in bits.
Returns the number of bytes read.
.. method:: i2c.writeto_mem(addr, memaddr, buf, \*, addrsize=8)
Write ``buf`` to the slave specified by ``addr`` starting from the
memory address specified by ``memaddr``. Param ``addrsize`` specifies the
address size in bits.
Set ``stop`` to ``False`` if the transfer should be continued.
Returns the number of bytes written.
.. method:: i2c.scan()
Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond.
Only valid when in master mode.
Constants
---------
.. data:: I2C.MASTER
for initialising the bus to master mode

View File

@@ -0,0 +1,209 @@
.. _machine.Pin:
class Pin -- control I/O pins
=============================
A pin is the basic object to control I/O pins. It has methods to set
the mode of the pin (input, output, etc) and methods to get and set the
digital logic level. For analog control of a pin, see the ADC class.
Usage Model:
.. only:: port_wipy
Board pins are identified by their string id::
from machine import Pin
g = machine.Pin('GP9', mode=Pin.OUT, pull=None, drive=Pin.MED_POWER, alt=-1)
You can also configure the Pin to generate interrupts. For instance::
from machine import Pin
def pincb(pin):
print(pin.id())
pin_int = Pin('GP10', mode=Pin.IN, pull=Pin.PULL_DOWN)
pin_int.irq(mode=Pin.IRQ_RISING, handler=pincb)
# the callback can be triggered manually
pin_int.irq()()
# to disable the callback
pin_int.irq().disable()
Now every time a falling edge is seen on the gpio pin, the callback will be
executed. Caution: mechanical push buttons have "bounce" and pushing or
releasing a switch will often generate multiple edges.
See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed
explanation, along with various techniques for debouncing.
All pin objects go through the pin mapper to come up with one of the
gpio pins.
Constructors
------------
.. class:: machine.Pin(id, ...)
Create a new Pin object associated with the id. If additional arguments are given,
they are used to initialise the pin. See :meth:`pin.init`.
Methods
-------
.. only:: port_wipy
.. method:: pin.init(mode, pull, \*, drive, alt)
Initialise the pin:
- ``mode`` can be one of:
- ``Pin.IN`` - input pin.
- ``Pin.OUT`` - output pin in push-pull mode.
- ``Pin.OPEN_DRAIN`` - output pin in open-drain mode.
- ``Pin.ALT`` - pin mapped to an alternate function.
- ``Pin.ALT_OPEN_DRAIN`` - pin mapped to an alternate function in open-drain mode.
- ``pull`` can be one of:
- ``None`` - no pull up or down resistor.
- ``Pin.PULL_UP`` - pull up resistor enabled.
- ``Pin.PULL_DOWN`` - pull down resitor enabled.
- ``drive`` can be one of:
- ``Pin.LOW_POWER`` - 2mA drive capability.
- ``Pin.MED_POWER`` - 4mA drive capability.
- ``Pin.HIGH_POWER`` - 6mA drive capability.
- ``alt`` is the number of the alternate function. Please refer to the
`pinout and alternate functions table. <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
for the specific alternate functions that each pin supports.
Returns: ``None``.
.. method:: pin.id()
Get the pin id.
.. method:: pin.value([value])
Get or set the digital logic level of the pin:
- With no argument, return 0 or 1 depending on the logic level of the pin.
- With ``value`` given, set the logic level of the pin. ``value`` can be
anything that converts to a boolean. If it converts to ``True``, the pin
is set high, otherwise it is set low.
.. method:: pin.alt_list()
Returns a list of the alternate functions supported by the pin. List items are
a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
.. only:: port_wipy
.. method:: pin([value])
Pin objects are callable. The call method provides a (fast) shortcut to set and get the value of the pin.
See **pin.value** for more details.
.. method:: pin.toggle()
Toggle the value of the pin.
.. method:: pin.mode([mode])
Get or set the pin mode.
.. method:: pin.pull([pull])
Get or set the pin pull.
.. method:: pin.drive([drive])
Get or set the pin drive strength.
.. method:: pin.irq(\*, trigger, priority=1, handler=None, wake=None)
Create a callback to be triggered when the input level at the pin changes.
- ``trigger`` configures the pin level which can generate an interrupt. Possible values are:
- ``Pin.IRQ_FALLING`` interrupt on falling edge.
- ``Pin.IRQ_RISING`` interrupt on rising edge.
- ``Pin.IRQ_LOW_LEVEL`` interrupt on low level.
- ``Pin.IRQ_HIGH_LEVEL`` interrupt on high level.
The values can be *ORed* together, for instance mode=Pin.IRQ_FALLING | Pin.IRQ_RISING
- ``priority`` level of the interrupt. Can take values in the range 1-7.
Higher values represent higher priorities.
- ``handler`` is an optional function to be called when new characters arrive.
- ``wakes`` selects the power mode in which this interrupt can wake up the
board. Please note:
- If ``wake_from=machine.Sleep.ACTIVE`` any pin can wake the board.
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
``GP11``, GP17`` or ``GP24`` can wake the board. Note that only 1
of this pins can be enabled as a wake source at the same time, so, only
the last enabled pin as a ``machine.Sleep.SUSPENDED`` wake source will have effect.
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
``GP11``, ``GP17`` and ``GP24`` can wake the board. In this case all of the
6 pins can be enabled as a ``machine.Sleep.HIBERNATE`` wake source at the same time.
- Values can be ORed to make a pin generate interrupts in more than one power
mode.
Returns a callback object.
Attributes
----------
.. class:: Pin.board
Contains all ``Pin`` objects supported by the board. Examples::
Pin.board.GP25
led = Pin(Pin.board.GP25, mode=Pin.OUT)
Pin.board.GP2.alt_list()
Constants
---------
.. only:: port_wipy
.. data:: Pin.IN
.. data:: Pin.OUT
.. data:: Pin.OPEN_DRAIN
.. data:: Pin.ALT
.. data:: Pin.ALT_OPEN_DRAIN
Selects the pin mode.
.. data:: Pin.PULL_UP
.. data:: Pin.PULL_DOWN
Selectes the wether there's pull up/down resistor.
.. data:: Pin.LOW_POWER
.. data:: Pin.MED_POWER
.. data:: Pin.HIGH_POWER
Selects the drive strength.
.. data:: Pin.IRQ_FALLING
.. data:: Pin.IRQ_RISING
.. data:: Pin.IRQ_LOW_LEVEL
.. data:: Pin.IRQ_HIGH_LEVEL
Selects the IRQ trigger type.

View File

@@ -0,0 +1,68 @@
.. _machine.RTC:
class RTC -- real time clock
============================
The RTC is and independent clock that keeps track of the date
and time.
Example usage::
rtc = machine.RTC()
rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0))
print(rtc.datetime())
Constructors
------------
.. class:: machine.RTC(id=0, ...)
Create an RTC object. See init for parameters of initialization.
Methods
-------
.. method:: rtc.init(id, datetime)
Initialise the RTC. Datetime is a tuple of the form:
``(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])``
.. method:: rtc.now()
Get get the current datetime tuple.
.. method:: rtc.deinit()
Resets the RTC to the time of January 1, 2015 and starts running it again.
.. method:: rtc.alarm(id, time, /*, repeat=False)
Set the RTC alarm. Time might be either a milllisecond value to program the alarm to
current time + time_in_ms in the future, or a datetimetuple. If the time passed is in
milliseconds, repeat can be set to ``True`` to make the alarm periodic.
.. method:: rtc.alarm_left(alarm_id=0)
Get the number of milliseconds left before the alarm expires.
.. method:: rtc.cancel(alarm_id=0)
Cancel a running alarm.
.. method:: rtc.irq(\*, trigger, handler=None, wake=machine.IDLE)
Create an irq object triggered by a real time clock alarm.
- ``trigger`` must be ``RTC.ALARM0``
- ``handler`` is the function to be called when the callback is triggered.
- ``wake`` specifies the sleep mode from where this interrupt can wake
up the system.
Constants
---------
.. data:: RTC.ALARM0
irq trigger source

View File

@@ -1,4 +1,4 @@
.. _pyb.SD:
.. _machine.SD:
class SD -- secure digital memory card
======================================
@@ -13,27 +13,29 @@ more info regarding the pins which can be remapped to be used with a SD card.
Example usage::
# data, clk and cmd pins must be passed along with
from machine import SD
import os
# clk cmd and dat0 pins must be passed along with
# their respective alternate functions
sd = pyb.SD('GP15', 8, 'GP10', 6, 'GP11', 6)
sd.enable() # enable and mount the SD card
sd.disable() # disable and unmount it
sd = machine.SD(pins=('GP10', 'GP11', 'GP15'))
os.mount(sd, '/sd')
# do normal file operations
Constructors
------------
.. class:: pyb.SD(dat_pin, dat_pin_af, clk_pin, clk_pin_af, cmd_pin, cmd_pin_af)
.. class:: machine.SD(id,... )
Create a SD card object. Data, clock and cmd pins must be passed along with
their respective alternate functions.
Create a SD card object. See ``init()`` for parameters if initialization.
Methods
-------
.. method:: sd.enable()
.. method:: sd.init(id=0, pins=('GP10', 'GP11', 'GP15'))
Enable the SD card and mount it on the file system. Accesible as ``/sd``.
Enable the SD card. In order to initalize the card, give it a 3-tuple:
``(clk_pin, cmd_pin, dat0_pin)``.
.. method:: sd.disable()
.. method:: sd.deinit()
Disable the SD card and remove it from the file system.
Disable the SD card.

View File

@@ -0,0 +1,85 @@
.. _machine.SPI:
class SPI -- a master-driven serial protocol
============================================
SPI is a serial protocol that is driven by a master. At the physical level
there are 3 lines: SCK, MOSI, MISO.
.. only:: port_wipy
See usage model of I2C; SPI is very similar. Main difference is
parameters to init the SPI bus::
from machine import SPI
spi = SPI(0, mode=SPI.MASTER, baudrate=1000000, polarity=0, phase=0, firstbit=SPI.MSB)
Only required parameter is mode, must be SPI.MASTER. Polarity can be 0 or
1, and is the level the idle clock line sits at. Phase can be 0 or 1 to
sample data on the first or second clock edge respectively.
Constructors
------------
.. only:: port_wipy
.. class:: machine.SPI(id, ...)
Construct an SPI object on the given bus. ``id`` can be only 0.
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.
Methods
-------
.. method:: spi.init(mode, baudrate=1000000, \*, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, pins=(CLK, MOSI, MISO))
Initialise the SPI bus with the given parameters:
- ``mode`` must be ``SPI.MASTER``.
- ``baudrate`` is the SCK clock rate.
- ``polarity`` can be 0 or 1, and is the level the idle clock line sits at.
- ``phase`` can be 0 or 1 to sample data on the first or second clock edge
respectively.
- ``bits`` is the width of each transfer, accepted values are 8, 16 and 32.
- ``firstbit`` can be ``SPI.MSB`` only.
- ``pins`` is an optional tupple with the pins to assign to the SPI bus.
.. method:: spi.deinit()
Turn off the SPI bus.
.. method:: spi.write(buf)
Write the data contained in ``buf``.
Returns the number of bytes written.
.. method:: spi.read(nbytes, *, write=0x00)
Read the ``nbytes`` while writing the data specified by ``write``.
Return the number of bytes read.
.. method:: spi.readinto(buf, *, write=0x00)
Read into the buffer specified by ``buf`` while writing the data specified by
``write``.
Return the number of bytes read.
.. method:: spi.write_readinto(write_buf, read_buf)
Write from ``write_buf`` and read into ``read_buf``. Both buffers must have the
same length.
Returns the number of bytes written
Constants
---------
.. data:: SPI.MASTER
for initialising the SPI bus to master
.. data:: SPI.MSB
set the first bit to be the most significant bit

View File

@@ -0,0 +1,196 @@
.. _machine.Timer:
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
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
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
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)
led = Pin('GPIO2', mode=Pin.OUT)
def tick(timer): # we will receive the timer object when being called
print(timer.time()) # show current timer's time value (is microseconds)
led.toggle() # toggle the LED
tim_a.callback(handler=tick)
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
.. note::
Memory can't be allocated inside irq handlers (an interrupt) and so
exceptions raised within a handler don't give much information. See
:func:`micropython.alloc_emergency_exception_buf` for how to get around this
limitation.
Constructors
------------
.. class:: machine.Timer(id, ...)
.. 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.
Methods
-------
.. only:: port_wipy
.. method:: timer.init(mode, \*, width=16)
Initialise the timer. Example::
tim.init(Timer.PERIODIC) # periodic 16-bit timer
tim.init(Timer.ONE_SHOT, width=32) # one shot 32-bit timer
Keyword arguments:
- ``mode`` can be one of:
- ``Timer.ONE_SHOT`` - The timer runs once until the configured
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.
- ``width`` must be either 16 or 32 (bits). For really low frequencies <= ~1Hz
(or large periods), 32-bit timers should be used. 32-bit mode is only available
for ``ONE_SHOT`` AND ``PERIODIC`` modes.
.. method:: timer.deinit()
Deinitialises the timer. Disables all channels and associated IRQs.
Stops the timer, and disables the timer peripheral.
.. only:: port_wipy
.. method:: timer.channel(channel, \**, freq, period, polarity=Timer.POSITIVE, duty_cycle=0)
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
create the channel.
- ``channel`` if the width of the timer is 16-bit, then must be either ``TIMER.A``, ``TIMER.B``.
If the width is 32-bit then it **must be** ``TIMER.A | TIMER.B``.
Keyword only arguments:
- ``freq`` sets the frequency in Hz.
- ``period`` sets the period in microseconds.
.. note::
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)
class TimerChannel --- setup a channel for a timer
==================================================
Timer channels are used to generate/capture a signal using a timer.
TimerChannel objects are created using the Timer.channel() method.
Methods
-------
.. only:: port_wipy
.. method:: timerchannel.irq(\*, trigger, priority=1, handler=None)
The behavior of this callback is heaviliy dependent on the operating
mode of the timer channel:
- If mode is ``Timer.PERIODIC`` the callback is executed periodically
with the configured frequency or period.
- If mode is ``Timer.ONE_SHOT`` the callback is executed once when
the configured timer expires.
- If mode is ``Timer.PWM`` the callback is executed when reaching the duty
cycle value.
The accepted params are:
- ``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.
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).

View File

@@ -0,0 +1,170 @@
.. _machine.UART:
class UART -- duplex serial communication bus
=============================================
UART implements the standard UART/USART duplex serial communications protocol. At
the physical level it consists of 2 lines: RX and TX. The unit of communication
is a character (not to be confused with a string character) which can be 8 or 9
bits wide.
UART objects can be created and initialised using::
from machine import UART
uart = UART(1, 9600) # init with given baudrate
uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters
.. only:: port_machineoard
Bits can be 7, 8 or 9. Parity can be None, 0 (even) or 1 (odd). Stop can be 1 or 2.
*Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled,
only 7 and 8 bits are supported.
.. only:: port_wipy
Bits can be 5, 6, 7, 8. Parity can be ``None``, ``UART.EVEN`` or ``UART.ODD``. Stop can be 1 or 2.
A UART object acts like a stream object and reading and writing is done
using the standard stream methods::
uart.read(10) # read 10 characters, returns a bytes object
uart.readall() # read all available characters
uart.readline() # read a line
uart.readinto(buf) # read and store into the given buffer
uart.write('abc') # write the 3 characters
.. only:: port_machineoard
Individual characters can be read/written using::
uart.readchar() # read 1 character and returns it as an integer
uart.writechar(42) # write 1 character
To check if there is anything to be read, use::
uart.any() # returns True if any characters waiting
*Note:* The stream functions ``read``, ``write``, etc. are new in MicroPython v1.3.4.
Earlier versions use ``uart.send`` and ``uart.recv``.
.. only:: port_wipy
To check if there is anything to be read, use::
uart.any() # returns the number of characters available for reading
Constructors
------------
.. only:: port_wipy
.. class:: machine.UART(bus, ...)
Construct a UART object on the given bus. ``bus`` can be 0 or 1.
If the bus is not given, the default one will be selected (0) or the selection
will be made based on the given pins.
Methods
-------
.. only:: port_wipy
.. method:: uart.init(baudrate=9600, bits=8, parity=None, stop=1, \*, pins=(TX, RX, RTS, CTS))
Initialise the UART bus with the given parameters:
- ``baudrate`` is the clock rate.
- ``bits`` is the number of bits per character, 7, 8 or 9.
- ``parity`` is the parity, ``None``, ``UART.EVEN`` or ``UART.ODD``.
- ``stop`` is the number of stop bits, 1 or 2.
- ``pins`` is a 4 or 2 item list indicating the TX, RX, RTS and CTS pins (in that order).
Any of the pins can be None if one wants the UART to operate with limited functionality.
If the RTS pin is given the the RX pin must be given as well. The same applies to CTS.
When no pins are given, then the default set of TX and RX pins is taken, and hardware
flow control will be disabled. If pins=None, no pin assignment will be made.
.. method:: uart.deinit()
Turn off the UART bus.
.. method:: uart.any()
Return the number of characters available for reading.
.. method:: uart.read([nbytes])
Read characters. If ``nbytes`` is specified then read at most that many bytes.
Return value: a bytes object containing the bytes read in. Returns ``b''``
on timeout.
.. method:: uart.readall()
Read as much data as possible.
Return value: a bytes object.
.. method:: uart.readinto(buf[, nbytes])
Read bytes into the ``buf``. If ``nbytes`` is specified then read at most
that many bytes. Otherwise, read at most ``len(buf)`` bytes.
Return value: number of bytes read and stored into ``buf``.
.. method:: uart.readline()
Read a line, ending in a newline character.
Return value: the line read.
.. method:: uart.write(buf)
Write the buffer of bytes to the bus.
Return value: number of bytes written.
.. method:: uart.sendbreak()
Send a break condition on the bus. This drives the bus low for a duration
of 13 bits.
Return value: ``None``.
.. only:: port_wipy
.. method:: uart.irq(trigger, priority=1, handler=None, wake=machine.IDLE)
Create a callback to be triggered when data is received on the UART.
- ``trigger`` can only be ``UART.RX_ANY``
- ``priority`` level of the interrupt. Can take values in the range 1-7.
Higher values represent higher priorities.
- ``handler`` an optional function to be called when new characters arrive.
- ``wake`` can only be ``machine.IDLE``.
.. note::
The handler will be called whenever any of the following two conditions are met:
- 8 new characters have been received.
- At least 1 new character is waiting in the Rx buffer and the Rx line has been
silent for the duration of 1 complete frame.
This means that when the handler function is called there will be between 1 to 8
characters waiting.
Returns an irq object.
Constants
---------
.. data:: UART.EVEN
.. data:: UART.ODD
parity types (anlong with ``None``)
.. data:: UART.RX_ANY
IRQ trigger sources

View File

@@ -0,0 +1,33 @@
.. _machine.WDT:
class WDT -- watchdog timer
===========================
The WDT is used to restart the system when the application crashes and ends
up into a non recoverable state. Once started it cannot be stopped or
reconfigured in any way. After enabling, the application must "feed" the
watchdog periodically to prevent it from expiring and resetting the system.
Example usage::
from machine import WDT
wdt = WDT(timeout=2000) # enable it with a timeout of 2s
wdt.feed()
Constructors
------------
.. class:: machine.WDT(id=0, timeout=5000)
Create a WDT object and start it. The timeout must be given in seconds and
the minimum value that is accepted is 1 second. Once it is running the timeout
cannot be changed and the WDT cannot be stopped either.
Methods
-------
.. method:: wdt.feed()
Feed the WDT to prevent it from resetting the system. The application
should place this call in a sensible place ensuring that the WDT is
only fed after verifying that everything is functioning correctly.

131
docs/library/machine.rst Normal file
View File

@@ -0,0 +1,131 @@
:mod:`machine` --- functions related to the board
=================================================
.. module:: machine
:synopsis: functions related to the board
The ``machine`` module contains specific functions related to the board.
Reset related functions
-----------------------
.. function:: reset()
Resets the WiPy in a manner similar to pushing the external RESET
button.
.. function:: reset_cause()
Get the reset cause. See :ref:`constants <machine_constants>` for the possible return values.
Interrupt related functions
---------------------------
.. function:: disable_irq()
Disable interrupt requests.
Returns the previous IRQ state: ``False``/``True`` for disabled/enabled IRQs
respectively. This return value can be passed to enable_irq to restore
the IRQ to its original state.
.. function:: enable_irq(state=True)
Enable interrupt requests.
If ``state`` is ``True`` (the default value) then IRQs are enabled.
If ``state`` is ``False`` then IRQs are disabled. The most common use of
this function is to pass it the value returned by ``disable_irq`` to
exit a critical section.
Power related functions
-----------------------
.. function:: freq()
Returns a tuple of clock frequencies: ``(sysclk,)``
These correspond to:
- sysclk: frequency of the CPU
.. function:: idle()
Gates the clock to the CPU, useful to reduce power consumption at any time during
short or long periods. Peripherals continue working and execution resumes as soon
as any interrupt is triggered (including the systick which has a period of 1ms).
Current consumption is reduced to ~12mA (in WLAN STA mode)
.. function:: sleep()
Stops the CPU and disables all peripherals except for WLAN. Execution is resumed from
the point where the sleep was requested. Wake sources are ``Pin``, ``RTC`` and ``WLAN``.
Current consumption is reduced to 950uA (in WLAN STA mode).
.. function:: deepsleep()
Stops the CPU and all peripherals including WLAN. Execution is resumed from main, just
as with a reset. The reset cause can be checked to know that we are coming from
from ``machine.DEEPSLEEP``. Wake sources are ``Pin`` and ``RTC``. Current consumption
is reduced to ~5uA.
.. function:: wake_reason()
Get the wake reason. See :ref:`constants <machine_constants>` for the possible return values.
Miscellaneous functions
-----------------------
.. function:: main(filename)
Set the filename of the main script to run after boot.py is finished. If
this function is not called then the default file main.py will be executed.
It only makes sense to call this function from within boot.py.
.. function:: rng()
Return a 24-bit software generated random number.
.. 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.
.. _machine_constants:
Constants
---------
.. data:: machine.IDLE
.. data:: machine.SLEEP
.. data:: machine.DEEPSLEEP
irq wake values
.. data:: machine.POWER_ON
.. data:: machine.HARD_RESET
.. data:: machine.WDT_RESET
.. data:: machine.DEEPSLEEP_RESET
.. data:: machine.SOFT_RESET
reset causes
.. data:: machine.WLAN_WAKE
.. data:: machine.PIN_WAKE
.. data:: machine.RTC_WAKE
wake reasons
Classes
-------
.. toctree::
:maxdepth: 1
machine.ADC.rst
machine.I2C.rst
machine.Pin.rst
machine.RTC.rst
machine.SD.rst
machine.SPI.rst
machine.Timer.rst
machine.UART.rst
machine.WDT.rst

View File

@@ -27,6 +27,44 @@ For example::
data = s.recv(1000)
s.close()
.. only:: port_wipy
.. _network.server:
class server
============
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.
Constructors
------------
.. class:: network.server(id, ...)
Create a server instance, see ``init`` for parameters of initialization.
Methods
-------
.. method:: server.init(\*, login=('micro', 'python'), timeout=300)
Init (and effectively start the server). Optionally a new ``user``, ``password``
and ``timeout`` (in seconds) can be passed.
.. method:: server.deinit()
Stop the server
.. method:: server.timeout([timeout_in_seconds])
Get or set the server timeout.
.. method:: server.isrunning()
Returns ``True`` is the server is running, ``False`` otherwise.
.. only:: port_pyboard
class CC3K
@@ -178,13 +216,13 @@ For example::
Dump the WIZnet5x00 registers. Useful for debugging.
class WLAN
==========
.. _network.WLAN:
.. only:: port_esp8266
class WLAN
==========
This class provides a driver for WiFi network processor in the ESP8266. Example usage::
import network
@@ -236,17 +274,41 @@ class WLAN
* 0 -- visible
* 1 -- hidden
.. method:: status()
Return the current status of the wireless connection.
The possible statuses are defined as constants:
* ``STAT_IDLE`` -- no connection and no activity,
* ``STAT_CONNECTING`` -- connecting in progress,
* ``STAT_WRONG_PASSWORD`` -- failed due to incorrect password,
* ``STAT_NO_AP_FOUND`` -- failed because no access point replied,
* ``STAT_CONNECT_FAIL`` -- failed due to other problems,
* ``STAT_GOT_IP`` -- connection susccessful.
.. method:: wlan.isconnected()
In case of STA mode, returns ``True`` if connected to a wifi access
point and has a valid IP address. In AP mode returns ``True`` when a
station is connected. Returns ``False`` otherwise.
.. only:: port_wipy
class WLAN
==========
This class provides a driver for WiFi network processor in the WiPy. Example usage::
import network
import time
# setup as a station
nic = network.WLAN(mode=WLAN.STA)
nic.connect('your-ssid', security=WLAN.WPA2, key='your-key')
while not nic.isconnected():
pyb.delay(50)
print(nic.ifconfig())
wlan = network.WLAN(mode=WLAN.STA)
wlan.connect('your-ssid', auth=(WLAN.WPA2, 'your-key'))
while not wlan.isconnected():
time.sleep_ms(50)
print(wlan.ifconfig())
# now use socket as usual
...
@@ -254,14 +316,22 @@ class WLAN
Constructors
------------
.. class:: WLAN(..)
.. class:: WLAN(id=0, ...)
Create a WLAN object, and optionally configure it. See ``iwconfig`` for params of configuration.
Create a WLAN object, and optionally configure it. See ``init`` for params of configuration.
.. note::
The ``WLAN`` constructor is special in the sense that if no arguments besides the id are given,
it will return the already exisiting ``WLAN`` instance without re-configuring it. This is
because ``WLAN`` is a system feature of the WiPy. If the already existing instance is not
initialized it will do the same as the other constructors an will initialize it with default
values.
Methods
-------
.. method:: iwconfig(\*, mode, ssid, security, key, channel, antenna)
.. method:: wlan.init(mode, \*, ssid, auth, channel, antenna)
Set or get the WiFi network processor configuration.
@@ -269,101 +339,111 @@ class WLAN
- ``mode`` can be either ``WLAN.STA`` or ``WLAN.AP``.
- ``ssid`` is a string with the ssid name. Only needed when mode is ``WLAN.AP``.
- ``security`` can be ``WLAN.OPEN``, ``WLAN.WEP``, ``WLAN.WPA`` or ``WLAN.WPA2``.
Only needed when mode is ``WLAN.AP``.
- ``key`` is a string with the network password. Not needed when mode is ``WLAN.STA``
or security is ``WLAN.OPEN``. If ``security`` is ``WLAN.WEP`` the key must be a
string representing hexadecimal values (e.g. 'ABC1DE45BF').
- ``auth`` is a tuple with (sec, key). Security can be ``None``, ``WLAN.WEP``,
``WLAN.WPA`` or ``WLAN.WPA2``. The key is a string with the network password.
If ``sec`` is ``WLAN.WEP`` the key must be a string representing hexadecimal
values (e.g. 'ABC1DE45BF'). Only needed when mode is ``WLAN.AP``.
- ``channel`` a number in the range 1-11. Only needed when mode is ``WLAN.AP``.
- ``antenna`` selects between the internal and the external antenna. Can be either
``WLAN.INTERNAL`` or ``WLAN.EXTERNAL``.
``WLAN.INT_ANT`` or ``WLAN.EXT_ANT``.
For example, you can do::
# create and configure as an access point
nic.iwconfig(mode=WLAN.AP, ssid='wipy-wlan', security=WLAN.WPA2, key='www.wipy.io', channel=7, antenna=WLAN.INTERNAL)
wlan.init(mode=WLAN.AP, ssid='wipy-wlan', auth=(WLAN.WPA2,'www.wipy.io'), channel=7, antenna=WLAN.INT_ANT)
or::
# configure as an station
nic.iwconfig(mode=WLAN.STA)
wlan.init(mode=WLAN.STA)
With no arguments given, the current configuration is returned as a namedtuple that looks like this:
``(mode=2, ssid='wipy-wlan', security=2, key='www.wipy.io', channel=5, antenna=0)``
.. method:: wlan.connect(ssid, \*, auth=None, bssid=None, timeout=5000)
.. method:: wlan.connect(ssid, \*, security=WLAN.OPEN, key=None, bssid=None, timeout=5000)
Connect to a wifi access point using the given SSID, and other security
parameters.
- ``key`` is always a string, but if ``security`` is ``WLAN.WEP`` the key must be a string
representing hexadecimal values (e.g. 'ABC1DE45BF').
- ``bssid`` is the MAC address of the AP to connect to. Useful when there are several APs
with the same ssid.
- ``auth`` is a tuple with (sec, key). Security can be ``None``, ``WLAN.WEP``,
``WLAN.WPA`` or ``WLAN.WPA2``. The key is a string with the network password.
If ``sec`` is ``WLAN.WEP`` the key must be a string representing hexadecimal
values (e.g. 'ABC1DE45BF'). Only needed when mode is ``WLAN.AP``
- ``bssid`` is the MAC address of the AP to connect to. Useful when there are several
APs with the same ssid.
- ``timeout`` is the maximum time in milliseconds to wait for the connection to succeed.
.. method:: wlan.scan()
Performs a network scan and returns a list of named tuples with (ssid, bssid, security, channel, rssi).
Performs a network scan and returns a list of named tuples with (ssid, bssid, sec, channel, rssi).
Note that channel is always ``None`` since this info is not provided by the WiPy.
.. method:: wlan.disconnect()
Disconnect from the wifi access point.
.. method:: wlan.isconnected()
In case of STA mode, returns ``True`` if connected to a wifi access point and has a valid IP address.
In AP mode returns ``True`` when a station is connected. Returns ``False`` otherwise.
.. method:: wlan.ifconfig(['dhcp' or configtuple])
With no parameters given eturns a 4-tuple of ``(ip, subnet mask, gateway, DNS server)``.
In AP mode returns ``True`` when a station is connected, ``False`` otherwise.
.. method:: wlan.ifconfig(if_id=0, config=['dhcp' or configtuple])
With no parameters given eturns a 4-tuple of ``(ip, subnet_mask, gateway, DNS_server)``.
if ``'dhcp'`` is passed as a parameter then the DHCP client is enabled and the IP params
are negotiated with the AP.
if the 4-tuple config is given then a static IP is configured. For example::
nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
.. method:: wlan.mac()
Returns a 6-byte long bytes object with the MAC address.
.. method:: wlan.connections()
Returns a list of the devices currently connected. Each item in the list is a
tuple of ``(ssid, mac)``.
If the 4-tuple config is given then a static IP is configured. For instance::
.. method:: wlan.callback(wakes)
wlan.ifconfig(config=('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
Create a callback to be triggered when a WLAN event occurs during ``pyb.Sleep.SUSPENDED``
.. method:: wlan.mode([mode])
Get or set the WLAN mode.
.. method:: wlan.ssid([ssid])
Get or set the SSID when in AP mode.
.. method:: wlan.auth([auth])
Get or set the authentication type when in AP mode.
.. method:: wlan.channel([channel])
Get or set the channel (only applicable in AP mode).
.. method:: wlan.antenna([antenna])
Get or set the antenna type (external or internal).
.. method:: wlan.mac([mac_addr])
Get or set a 6-byte long bytes object with the MAC address.
.. method:: wlan.irq(\*, handler, wake)
Create a callback to be triggered when a WLAN event occurs during ``machine.SLEEP``
mode. Events are triggered by socket activity or by WLAN connection/disconnection.
- ``wakes`` can only be ``pyb.Sleep.SUSPENDED``.
- ``handler`` is the function that gets called when the irq is triggered.
- ``wake`` must be ``machine.SLEEP``.
Returns a callback object.
Returns an irq object.
Constants
---------
.. data:: WLAN.STA
WiFi station mode
.. data:: WLAN.AP
WiFi access point mode
selects the WLAN mode
.. data:: WLAN.OPEN
.. data:: WLAN.WEP
.. data:: WLAN.WPA
.. data:: WLAN.WPA2
selects the network security
.. data:: WLAN.INTERNAL
.. data:: WLAN.EXTERNAL
.. data:: WLAN.INT_ANT
.. data:: WLAN.EXT_ANT
selects the antenna type

View File

@@ -71,9 +71,27 @@ Functions
.. only:: port_wipy
.. function:: mkfs(drive)
Formats the specified drive, must be either ``/flash`` or ``/sd``.
.. function:: mount(block_device, mount_point, \*, readonly=False)
Mounts a block device (like an ``SD`` object) in the specified mount
point. Example::
os.mount(sd, '/sd')
.. function:: unmount(path)
Unmounts a prevoulsy mounted block device from the given path.
.. function:: mkfs(block_device or path)
Formats the specified path, must be either ``/flash`` or ``/sd``.
A block device can also be passed like an ``SD`` object before
being mounted.
.. function:: dupterm(stream_object)
Duplicate the terminal (the REPL) on the passed stream-like object.
The given object must at least implement the ``.read()`` and ``.write()`` methods.
Constants
---------

View File

@@ -1,12 +1,12 @@
.. _pyb.ADC:
class ADC -- analog to digital conversion: read analog values on a pin
======================================================================
class ADC -- analog to digital conversion
=========================================
.. only:: port_pyboard
Usage::
import pyb
adc = pyb.ADC(pin) # create an analog object from a pin
@@ -18,53 +18,27 @@ class ADC -- analog to digital conversion: read analog values on a pin
val = adc.read_core_vbat() # read MCU VBAT
val = adc.read_core_vref() # read MCU VREF
.. only:: port_wipy
Usage::
import pyb
adc = pyb.ADC(pin) # create an analog object on one of the 4 ADC channels
val = adc.read() # read an analog value
adc.deinit() # disable the adc channel
adc.init() # enable the adc channel
Constructors
------------
.. only:: port_pyboard
.. class:: pyb.ADC(pin)
Create an ADC object associated with the given pin.
This allows you to then read analog values on that pin.
.. only:: port_wipy
.. class:: pyb.ADC(pin)
Create an ADC object associated with the given pin.
This allows you to then read analog values on that pin.
For more info check the `pinout and alternate functions
table. <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
.. warning::
ADC pin input range is 0-1.4V (being 1.8V the absolute maximum that it
can withstand). When GP2, GP3, GP4 or GP5 are remapped to the
ADC block, 1.8 V is the maximum. If these pins are used in digital mode,
then the maximum allowed input is 3.6V.
Methods
-------
.. method:: adc.read()
Read the value on the analog pin and return it. The returned value
will be between 0 and 4095.
.. only:: port_pyboard
.. method:: adc.read()
Read the value on the analog pin and return it. The returned value
will be between 0 and 4095.
.. method:: adc.read_timed(buf, timer)
Read analog values into ``buf`` at a rate set by the ``timer`` object.
@@ -97,15 +71,6 @@ Methods
# this will take 10 seconds to finish
for val in buf: # loop over all values
print(val) # print the value out
This function does not allocate any memory.
.. only:: port_wipy
.. method:: adc.init()
Enable the ADC channel.
.. method:: adc.deinit()
Disable the ADC channel.

View File

@@ -15,6 +15,9 @@ Example usage::
dac = DAC(1) # create DAC 1 on pin X5
dac.write(128) # write a value to the DAC (makes X5 1.65V)
dac = DAC(1, bits=12) # use 12 bit resolution
dac.write(4095) # output maximum value, 3.3V
To output a continuous sine-wave::
import math
@@ -23,27 +26,46 @@ To output a continuous sine-wave::
# create a buffer containing a sine-wave
buf = bytearray(100)
for i in range(len(buf)):
buf[i] = 128 + int(127 \* math.sin(2 \* math.pi \* i / len(buf)))
buf[i] = 128 + int(127 * math.sin(2 * math.pi * i / len(buf)))
# output the sine-wave at 400Hz
dac = DAC(1)
dac.write_timed(buf, 400 \* len(buf), mode=DAC.CIRCULAR)
dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR)
To output a continuous sine-wave at 12-bit resolution::
import math
from array import array
from pyb import DAC
# create a buffer containing a sine-wave, using half-word samples
buf = array('H', 2048 + int(2047 * math.sin(2 * math.pi * i / 128)) for i in range(128))
# output the sine-wave at 400Hz
dac = DAC(1, bits=12)
dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR)
Constructors
------------
.. class:: pyb.DAC(port)
.. class:: pyb.DAC(port, bits=8)
Construct a new DAC object.
``port`` can be a pin object, or an integer (1 or 2).
DAC(1) is on pin X5 and DAC(2) is on pin X6.
``bits`` is an integer specifying the resolution, and can be 8 or 12.
The maximum value for the write and write_timed methods will be
2\*\*``bits``-1.
Methods
-------
.. method:: dac.init(bits=8)
Reinitialise the DAC. ``bits`` can be 8 or 12.
.. method:: dac.noise(freq)
Generate a pseudo-random noise signal. A new random sample is written
@@ -57,13 +79,16 @@ Methods
.. method:: dac.write(value)
Direct access to the DAC output (8 bit only at the moment).
Direct access to the DAC output. The minimum value is 0. The maximum
value is 2\*\*``bits``-1, where ``bits`` is set when creating the DAC
object or by using the ``init`` method.
.. method:: dac.write_timed(data, freq, \*, mode=DAC.NORMAL)
Initiates a burst of RAM to DAC using a DMA transfer.
The input data is treated as an array of bytes (8 bit data).
The input data is treated as an array of bytes in 8-bit mode, and
an array of unsigned half-words (array typecode 'H') in 12-bit mode.
``freq`` can be an integer specifying the frequency to write the DAC
samples at, using Timer(6). Or it can be an already-initialised
Timer object which is used to trigger the DAC sample. Valid timers

View File

@@ -1,46 +0,0 @@
.. _pyb.HeartBeat:
class HeartBeat -- heart beat LED
=================================
The HeartBeat class controls the heart beat led which by default
flashes once every 5s. The user can disable the HeartBeat and then
is free to control this LED manually through GP25 using the Pin
class. The GP25 can also be remapped as a PWM output, an this
can be used to control the light intesity of the heart beat LED.
Example usage::
hb = pyb.HeartBeat()
hb.disable() # disable the heart beat
hb.enable() # enable the heart beat
Constructors
------------
.. class:: pyb.HeartBeat()
Create a HeartBeat object.
Methods
-------
.. method:: heartbeat.enable()
Enable the heart beat. The LED will flash once every 5 seconds.
.. method:: heartbeat.disable()
Disable the heart beat. The LED can then be controlled manually.
Example::
import pyb
# disable the heart beat
pyb.HeartBeat().disable()
# get the GP25 pin object
hbl = pyb.Pin('GP25')
# toggle the led
hbl.toggle()
...

View File

@@ -12,58 +12,49 @@ when created, or initialised later on.
.. only:: port_pyboard
Example::
from pyb import I2C
i2c = I2C(1) # create on bus 1
i2c = I2C(1, I2C.MASTER) # create and init as a master
i2c.init(I2C.MASTER, baudrate=20000) # init as a master
i2c.init(I2C.SLAVE, addr=0x42) # init as a slave with given address
i2c.deinit() # turn off the peripheral
.. only:: port_wipy
Example::
from pyb import I2C
i2c = I2C(1) # create on bus 1
i2c = I2C(1, I2C.MASTER) # create and init as a master
i2c.init(I2C.MASTER, baudrate=20000) # init as a master
i2c.deinit() # turn off the peripheral
Printing the i2c object gives you information about its configuration.
The basic methods are send and recv::
.. only:: port_pyboard
i2c.send('abc') # send 3 bytes
i2c.send(0x42) # send a single byte, given by the number
data = i2c.recv(3) # receive 3 bytes
The basic methods are send and recv::
To receive inplace, first create a bytearray::
i2c.send('abc') # send 3 bytes
i2c.send(0x42) # send a single byte, given by the number
data = i2c.recv(3) # receive 3 bytes
To receive inplace, first create a bytearray::
data = bytearray(3) # create a buffer
i2c.recv(data) # receive 3 bytes, writing them into data
data = bytearray(3) # create a buffer
i2c.recv(data) # receive 3 bytes, writing them into data
You can specify a timeout (in ms)::
You can specify a timeout (in ms)::
i2c.send(b'123', timeout=2000) # timout after 2 seconds
i2c.send(b'123', timeout=2000) # timout after 2 seconds
A master must specify the recipient's address::
A master must specify the recipient's address::
i2c.init(I2C.MASTER)
i2c.send('123', 0x42) # send 3 bytes to slave with address 0x42
i2c.send(b'456', addr=0x42) # keyword for address
i2c.init(I2C.MASTER)
i2c.send('123', 0x42) # send 3 bytes to slave with address 0x42
i2c.send(b'456', addr=0x42) # keyword for address
Master also has other methods::
Master also has other methods::
i2c.is_ready(0x42) # check if slave 0x42 is ready
i2c.scan() # scan for slaves on the bus, returning
# a list of valid addresses
i2c.mem_read(3, 0x42, 2) # read 3 bytes from memory of slave 0x42,
# starting at address 2 in the slave
i2c.mem_write('abc', 0x42, 2, timeout=1000) # write 'abc' (3 bytes) to memory of slave 0x42
# starting at address 2 in the slave, timeout after 1 second
i2c.is_ready(0x42) # check if slave 0x42 is ready
i2c.scan() # scan for slaves on the bus, returning
# a list of valid addresses
i2c.mem_read(3, 0x42, 2) # read 3 bytes from memory of slave 0x42,
# starting at address 2 in the slave
i2c.mem_write('abc', 0x42, 2, timeout=1000) # write 'abc' (3 bytes) to memory of slave 0x42
# starting at address 2 in the slave, timeout after 1 second
Constructors
------------
@@ -71,29 +62,18 @@ Constructors
.. only:: port_pyboard
.. 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
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:
- ``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)``
.. only:: port_wipy
.. class:: pyb.I2C(bus, ...)
Construct an I2C object on the given bus. `bus` can only be 1.
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.
Methods
-------
@@ -103,7 +83,7 @@ Methods
.. only:: port_pyboard
.. method:: i2c.init(mode, \*, addr=0x12, baudrate=400000, gencall=False)
.. method:: i2c.init(mode, \*, addr=0x12, baudrate=400000, gencall=False)
Initialise the I2C bus with the given parameters:
@@ -112,72 +92,63 @@ Methods
- ``baudrate`` is the SCL clock rate (only sensible for a master)
- ``gencall`` is whether to support general call mode
.. only:: port_wipy
.. method:: i2c.is_ready(addr)
.. method:: i2c.init(mode, \*, baudrate=100000)
Check if an I2C device responds to the given address. Only valid when in master mode.
Initialise the I2C bus with the given parameters:
.. method:: i2c.mem_read(data, addr, memaddr, \*, timeout=5000, addr_size=8)
- ``mode`` must be ``I2C.MASTER``
- ``baudrate`` is the SCL clock rate
Read from the memory of an I2C device:
.. method:: i2c.is_ready(addr)
- ``data`` can be an integer (number of bytes to read) or a buffer to read into
- ``addr`` is the I2C device address
- ``memaddr`` is the memory location within the I2C device
- ``timeout`` is the timeout in milliseconds to wait for the read
- ``addr_size`` selects width of memaddr: 8 or 16 bits
Check if an I2C device responds to the given address. Only valid when in master mode.
Returns the read data.
This is only valid in master mode.
.. method:: i2c.mem_read(data, addr, memaddr, \*, timeout=5000, addr_size=8)
.. method:: i2c.mem_write(data, addr, memaddr, \*, timeout=5000, addr_size=8)
Read from the memory of an I2C device:
Write to the memory of an I2C device:
- ``data`` can be an integer (number of bytes to read) or a buffer to read into
- ``addr`` is the I2C device address
- ``memaddr`` is the memory location within the I2C device
- ``timeout`` is the timeout in milliseconds to wait for the read
- ``addr_size`` selects width of memaddr: 8 or 16 bits
- ``data`` can be an integer or a buffer to write from
- ``addr`` is the I2C device address
- ``memaddr`` is the memory location within the I2C device
- ``timeout`` is the timeout in milliseconds to wait for the write
- ``addr_size`` selects width of memaddr: 8 or 16 bits
Returns the read data.
This is only valid in master mode.
Returns ``None``.
This is only valid in master mode.
.. method:: i2c.mem_write(data, addr, memaddr, \*, timeout=5000, addr_size=8)
.. method:: i2c.recv(recv, addr=0x00, \*, timeout=5000)
Write to the memory of an I2C device:
Receive data on the bus:
- ``data`` can be an integer or a buffer to write from
- ``addr`` is the I2C device address
- ``memaddr`` is the memory location within the I2C device
- ``timeout`` is the timeout in milliseconds to wait for the write
- ``addr_size`` selects width of memaddr: 8 or 16 bits
- ``recv`` can be an integer, which is the number of bytes to receive,
or a mutable buffer, which will be filled with received bytes
- ``addr`` is the address to receive from (only required in master mode)
- ``timeout`` is the timeout in milliseconds to wait for the receive
Return value: if ``recv`` is an integer then a new buffer of the bytes received,
otherwise the same buffer that was passed in to ``recv``.
Returns ``None``.
This is only valid in master mode.
.. method:: i2c.send(send, addr=0x00, \*, timeout=5000)
.. method:: i2c.recv(recv, addr=0x00, \*, timeout=5000)
Send data on the bus:
Receive data on the bus:
- ``send`` is the data to send (an integer to send, or a buffer object)
- ``addr`` is the address to send to (only required in master mode)
- ``timeout`` is the timeout in milliseconds to wait for the send
- ``recv`` can be an integer, which is the number of bytes to receive,
or a mutable buffer, which will be filled with received bytes
- ``addr`` is the address to receive from (only required in master mode)
- ``timeout`` is the timeout in milliseconds to wait for the receive
Return value: if ``recv`` is an integer then a new buffer of the bytes received,
otherwise the same buffer that was passed in to ``recv``.
Return value: ``None``.
.. method:: i2c.scan()
Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond.
Only valid when in master mode.
.. method:: i2c.send(send, addr=0x00, \*, timeout=5000)
Send data on the bus:
- ``send`` is the data to send (an integer to send, or a buffer object)
- ``addr`` is the address to send to (only required in master mode)
- ``timeout`` is the timeout in milliseconds to wait for the send
Return value: ``None``.
Constants
---------

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