Compare commits

...

241 Commits
v1.4 ... v1.4.3

Author SHA1 Message Date
Damien George
d7b7d5f6ee docs: Bump version to 1.4.3. 2015-05-16 21:26:43 +01:00
stijn
709955b601 py: Fix printing of complex number when imaginary part is nan 2015-05-13 23:10:15 +01:00
Damien George
1db3577bcb teensy: Add readinto and readlines qstrs. 2015-05-13 20:46:54 +01:00
Damien George
0bfc57022d docs: Document USB_VCP file-like methods. 2015-05-13 20:42:12 +01:00
Damien George
1511dd4f84 stmhal: Add readinto and readlines methods to sys.stdin, pyb.USB_VCP().
Addresses issue #1255.
2015-05-13 20:22:11 +01:00
Josef Gajdusek
1c132c8587 esp8266: Add configuration option for redirecting the built-in OS output 2015-05-13 18:03:00 +02:00
Josef Gajdusek
40c6d57804 esp8266: Actually use the decimal part of system_rtc_clock_cali_proc() 2015-05-13 17:59:36 +02:00
stijn
a09757f104 windows: Enable some recently added features in mpconfigport.h 2015-05-13 16:26:16 +01:00
Damien George
304a96d7d6 esp8266: Put more literal and text obj data in irom0_0_seg.
With newer versions of esp_iot_sdk the iram1_0_seg started to overflow.
Now it doesn't.

Addresses issue #1254.
2015-05-13 14:49:14 +01:00
Damien George
4e7dc97bdc esp8266: Add module weak links; link time to utime. 2015-05-13 00:18:41 +01:00
Josef Gajdusek
103d12a877 esp8266: Add utime and pyb.RTC 2015-05-13 00:12:54 +01:00
Josef Gajdusek
b47931978f esp8266: Update the linker script
Moved modesp.o to flash and increased size of the irom0_0_seg segment. The new
value was taken from NodeMCU linker script.
2015-05-13 00:12:54 +01:00
Josef Gajdusek
1db4253886 lib: Move time utility functions to common library. 2015-05-13 00:12:54 +01:00
Josef Gajdusek
800d5cd16f esp8266: Implement time functions 2015-05-12 23:47:18 +01:00
Steve Zatz
c7df9c6c47 stmhal: Add os.rename function. 2015-05-12 23:43:11 +01:00
Damien George
f601390ef8 unix: Add some extra coverage tests for vstr and attrtuple. 2015-05-12 23:34:10 +01:00
Damien George
7bab32ef89 tests: Add further tests for class defining __hash__. 2015-05-12 23:08:18 +01:00
Damien George
c50772d19f py: Add mp_obj_get_int_truncated and use it where appropriate.
mp_obj_get_int_truncated will raise a TypeError if the argument is not
an integral type.  Use mp_obj_int_get_truncated only when you know the
argument is a small or big int.
2015-05-12 23:05:53 +01:00
Damien George
c2a4e4effc py: Convert hash API to use MP_UNARY_OP_HASH instead of ad-hoc function.
Hashing is now done using mp_unary_op function with MP_UNARY_OP_HASH as
the operator argument.  Hashing for int, str and bytes still go via
fast-path in mp_unary_op since they are the most common objects which
need to be hashed.

This lead to quite a bit of code cleanup, and should be more efficient
if anything.  It saves 176 bytes code space on Thumb2, and 360 bytes on
x86.

The only loss is that the error message "unhashable type" is now the
more generic "unsupported type for __hash__".
2015-05-12 22:46:02 +01:00
Paul Sokolovsky
6738c1dded vm: Properly handle StopIteration raised in user instance iterator.
I.e. in bytecode Python functions.
2015-05-11 23:57:42 +01:00
Paul Sokolovsky
d5e629ad0e objgenerator: Can optimize StopIteration to STOP_ITERATION only if arg is None.
Unfortunately, MP_OBJ_STOP_ITERATION doesn't have means to pass an associated
value, so we can't optimize StopIteration exception with (non-None) argument
to MP_OBJ_STOP_ITERATION.
2015-05-11 23:57:42 +01:00
Paul Sokolovsky
aa9dbb1b03 objgenerator: If generator yielded STOP_ITERATION value, it's stopped.
MP_OBJ_STOP_ITERATION is equivalent of raising StopIteration, except
mp_vm_return_kind_t for it is "yield".
2015-05-11 23:57:42 +01:00
blmorris
5df81de7af sthmal/rtc.c: Add calibration() method to get/set RTC fine-tuning value. 2015-05-11 23:48:39 +01:00
Paul Sokolovsky
a7c02c4538 vm: Null pointer test when checking for StopIteration optimizations.
When generator raises exception, it is automatically terminated (by setting
its code_state.ip to 0), which interferes with this check.

Triggered in particular by CPython's test_pep380.py.
2015-05-10 17:20:46 +03:00
Paul Sokolovsky
8fbabab1a8 unix: Include stdio.h to allow easy debugging with printf(). 2015-05-10 17:13:33 +03:00
Paul Sokolovsky
4a60cac916 runtime: Add TODO for mp_resume() on handling .close().
Exceptions in .close() should be ignored (dumped to sys.stderr, not
propagated), but in uPy, they are propagated. Fix would require
nlr-wrapping .close() call, which is expensive. Bu on the other hand,
.close() is not called often, so maybe that's not too bad (depends,
if it's finally called and that causes stack overflow, there's nothing
good in that). And yet on another hand, .close() can be implemented to
catch exceptions on its side, and that should be the right choice.
2015-05-10 02:39:45 +03:00
Paul Sokolovsky
717a958256 unix: Print unhandled exception to stderr, like CPython does. 2015-05-10 00:55:35 +03:00
Paul Sokolovsky
4ed7b7f751 py: iternext() may not return MP_OBJ_NULL, only MP_OBJ_STOP_ITERATION.
Testing for incorrect value led to premature termination of generator
containing yield from for such iterator (e.g. "yield from [1, 2]").
2015-05-10 00:41:49 +03:00
Damien George
a37d13c95d ACKNOWLEDGEMENTS: Add 1 backer name. 2015-05-09 22:37:34 +01:00
Paul Sokolovsky
c3ae03ff18 unix: Fix thumb2 vs arm native emitter auto-detection.
Make thumb2 have priority over arm.
2015-05-08 22:35:34 +01:00
Paul Sokolovsky
351424e719 emitnative: Revamp ARM codegen compile after full-arg support refactors.
The code was apparently broken after 9988618e0e
"py: Implement full func arg passing for native emitter.". This attempts to
propagate those changes to ARM emitter.
2015-05-08 22:35:34 +01:00
Damien George
d792d9e49e unix: Make extra-coverage function callable from Python scripts.
This allows the output of the extra-coverage tests to be checked using
the normal run-tests script.
2015-05-08 09:18:38 +01:00
Damien George
d3b32caea4 unix: Add special function to improve coverage.
The function and corresponding command-line option are only enabled for
the coverage build.  They are used to exercise uPy features that can't
be properly tested by Python scripts.
2015-05-08 00:19:56 +01:00
Damien George
0589c19d52 tests: Add test for machine module (mem* functions). 2015-05-08 00:18:28 +01:00
Paul Sokolovsky
76abb2e623 tools: Add script to install "upip" package manager.
upip is a simple and light-weight package manager for MicroPython modules,
offering subset of pip functionality. upip is part of micropython-lib
project: https://github.com/micropython/micropython-lib/tree/master/upip
This script bootstraps upip by downloading and unpacking it directly from
PyPI repository, with all other packages to be installed with upip itself.
2015-05-07 16:00:40 +03:00
Daniel Campora
2bdefea9d6 cc3200: Enable MICROPY_MODULE_WEAK_LINKS. 2015-05-07 12:19:31 +02:00
Damien George
4865a22f78 tools/pyboard.py: Add "--follow" option to wait for output indefinitely.
Also flush stdout so you can see output as it comes.
2015-05-07 10:14:51 +01:00
Dave Hylands
ff987ccf11 stmhal: Move debug UART repl to after uart_init0 call. 2015-05-06 22:16:49 +01:00
Josef Gajdusek
bda7041294 esp8266: Add support for frozen modules 2015-05-06 22:04:20 +01:00
Josef Gajdusek
d39d96b700 esp8266: Add .onsent callback support
The function passed to socket.onsent() gets called after data is succesfully
sent by the socket.
2015-05-06 21:47:44 +01:00
Josef Gajdusek
2d56df67cd esp8266: Initialize socket->connlist to NULL
This was causing crashes in .onconnect()
2015-05-06 21:47:43 +01:00
Damien George
57ebe1b27d unix-cpy: Fix adjustment of stack size when leaving exception handler.
Also remove __debug__ from one of the bytecode tests.
2015-05-06 16:46:21 +01:00
Josef Gajdusek
28076f3d4b esp8266: Fix garbage collector by hard-coding stack end address.
As user_init() is not a true main functions, the stack pointer captured within
is not pointing at the base of the stack. This caused gc_collect being called
with sp being higher than stack_end, causing integer overflow and crashing as
gc tried to scan almost the entire address space.
2015-05-06 14:01:07 +01:00
Damien George
9a42eb541e py: Fix naming of function arguments when function is a closure.
Addresses issue #1226.
2015-05-06 13:55:33 +01:00
Paul Sokolovsky
cd87d20f46 mkrules.mk: Add comment why dependency parsing regex was tweaked.
(Windows compatibility.)
2015-05-06 15:34:33 +03:00
Ari Suutari
c097ea5dd2 Adjust sed regex that processes dependency file from compiler
so that resulting file is correct also on windows systems (ie.
with file names containing drive letter).
2015-05-06 15:32:13 +03:00
Damien George
c98c128fe8 pyexec: Make raw REPL work with event-driven version of pyexec.
esp8266 port now has working raw and friendly REPL, as well as working
soft reset (CTRL-D at REPL, or raise SystemExit).

tools/pyboard.py now works with esp8266 port.
2015-05-06 00:02:58 +01:00
Damien George
367d4d1098 tests: Fix cmd_showbc now that LOAD_CONST_ELLIPSIS bytecode is gone. 2015-05-05 23:58:52 +01:00
Damien George
3d91b1f67f esp8266: Return CPU frequency in Hz. 2015-05-05 22:23:23 +01:00
Josef Gajdusek
82d08dccc6 esp8266: Fix endian of address returned by esp.getaddrinfo() 2015-05-05 22:19:48 +01:00
Damien George
8872abcbc4 py: Remove LOAD_CONST_ELLIPSIS bytecode, use LOAD_CONST_OBJ instead.
Ellipsis constant is rarely used so no point having an extra bytecode
for it.
2015-05-05 22:15:42 +01:00
Paul Sokolovsky
37c6555b44 obj: Handle user instance hash based on Python adhoc rules.
User instances are hashable by default (using __hash__ inherited from
"object"). But if __eq__ is defined and __hash__ not defined in particular
class, instance is not hashable.
2015-05-05 22:48:19 +03:00
Paul Sokolovsky
7667727021 objsingleton: New home for Ellipsis and NotImplemented.
Having NotImplemented as MP_OBJ_SENTINEL turned out to be problematic
(it needs to be checked for in a lot of places, otherwise it'll crash
as would pass MP_OBJ_IS_OBJ()), so made a proper singleton value like
Ellipsis, both of them sharing the same type.
2015-05-05 22:18:07 +03:00
Daniel Campora
e04aa96b4d cc3200: Define MICROPY_CPYTHON_COMPAT=0.
This only disables some corner case functionality to keep C Python
compatibility, and saves ~600 bytes.
2015-05-05 11:23:06 +02:00
Paul Sokolovsky
5ab5ac5448 modbuiltins: Add NotImplemented builtin constant.
From https://docs.python.org/3/library/constants.html#NotImplemented :
"Special value which should be returned by the binary special methods
(e.g. __eq__(), __lt__(), __add__(), __rsub__(), etc.) to indicate
that the operation is not implemented with respect to the other type;
may be returned by the in-place binary special methods (e.g. __imul__(),
__iand__(), etc.) for the same purpose. Its truth value is true."

Some people however appear to abuse it to mean "no value" when None is
a legitimate value (don't do that).
2015-05-04 19:45:53 +03:00
Paul Sokolovsky
3d3ef36e97 modstruct: Rename module to "ustruct", to allow full Python-level impl. 2015-05-04 16:53:52 +03:00
Paul Sokolovsky
1829d86ef5 modstruct: Group module qstr's together. 2015-05-04 15:51:08 +03:00
Josef Gajdusek
9e00ac89d5 esp8266: Add esp.socket class, with ESP-style socket functionality.
* UDP currently not supported
 * As there is no way (that I know of) the espconn_regist_connectcb()
   callback can recognize on which socket has the connection arrived,
   only one listening function at a time is supported
2015-05-04 11:48:40 +01:00
Josef Gajdusek
04ee5983fe lib: Move some common mod_network_* functions to lib/netutils. 2015-05-04 11:48:40 +01:00
Damien George
47b9809d23 py: Check that arg to object.__new__ is a user-defined type.
Addresses issue #1203.
2015-05-04 11:08:40 +01:00
Paul Sokolovsky
0116218fa8 modmachine: Add new module to access hardware, starting with physical memory.
Refactored from "stm" module, provides mem8, mem16, mem32 objects with
array subscript syntax.
2015-05-04 13:05:12 +03:00
Paul Sokolovsky
c4dc1b5c23 CONTRIBUTING.md: Link to contrib guidelines and code conventions. 2015-05-03 22:04:52 +01:00
Josef Gajdusek
7e7039b53c esp8266: Export station status() constants 2015-05-03 22:07:00 +03:00
Eero af Heurlin
2378be4e93 stmhal: Allow to configure UART pins completely via mpconfigboard.h. 2015-05-03 13:48:26 +01:00
Daniel Campora
8c8d7f3c60 cc3200: Clean up pyb.Pin
Remove unused and unneeded functions, also create Pin.get_config() that
returns the whole configuration of the pin.

This reduces code size by ~500 bytes.
2015-05-03 11:26:56 +02:00
Daniel Campora
e4c899a08c cc3200: WLAN.ifconfig returns an attrtuple instead of a dictionary. 2015-05-03 11:26:25 +02:00
Daniel Campora
f54bdecff2 cc3200: Implement Sleep.wake_reason() 2015-05-03 11:21:14 +02:00
Daniel Campora
71d482df47 cc3200: Clear the pending interrupt flag when disabling RTC callbacks. 2015-05-03 11:21:12 +02:00
Damien George
a9afcb159a unix/modffi.c: get_buffer is allowed to return NULL if len=0.
This is consistent with the logic in mp_get_buffer, and the code here is
an inlined version of that function.
2015-05-01 21:34:08 +01:00
stijn
a62c106974 msvc: Allow overriding of build options with custom file
- by default look for a user.props in the msvc directory, which is more convenient
  than the built-in way of looking for such file in the user's home directory
- make git ignore the file
2015-04-30 10:14:59 +02:00
Daniel Campora
6f218d7472 cc3200: Move wlan_init0() to the boot section.
This one creates a semaphore, therefore it must be executed only
after a hard reset (or when coming out of hibernation).
2015-04-29 16:10:40 +02:00
Daniel Campora
d8713d78f5 cc3200: Correct Sleep module name. Must be 'Sleep', not 'sleep'. 2015-04-29 15:27:28 +02:00
Daniel Campora
e282884e54 cc3200: When requesting safe boot, blink the led 3 times, not 4. 2015-04-29 15:27:21 +02:00
Daniel Campora
dbb4aef5e3 cc3200: Make WLAN.isconnected() also work in AP mode.
While in STA mode isconnected() returns True when connected to an AP
and the IP has been acquired. In AP mode, WLAN.isconnected() returns
True if at least one connected station is present.
2015-04-29 15:26:21 +02:00
Daniel Campora
bf4576dc91 cc3200: Clean-up servers enable/disable algorithm. 2015-04-29 14:25:44 +02:00
Dave Hylands
c3e37a0cde stmhal: Automatically re-enable IRQs on the USB REPL.
This allows errors to be seen and prevents hanging
the board from doing: pyb.disable_irq()
2015-04-29 08:27:38 +01:00
Damien George
f27aa27a0c py/repl.c: Fix shadowing of local variable "i". 2015-04-29 01:01:48 +01:00
Damien George
a1a2c411b2 py, readline: Add tab autocompletion for REPL.
Can complete names in the global namespace, as well as a chain of
attributes, eg pyb.Pin.board.<tab> will give a list of all board pins.

Costs 700 bytes ROM on Thumb2 arch, but greatly increases usability of
REPL prompt.
2015-04-29 00:46:26 +01:00
Damien George
b7a4f15b34 mp-readline: Save "prompt" string in readline state. 2015-04-29 00:32:35 +01:00
Damien George
ad9daadf8a py: Fix attrtuple array length in print and creation. 2015-04-29 00:17:48 +01:00
Damien George
95f53461c2 py: Replace py-version.sh with makeversionhdr.py, written in Python.
Also rename py-version.h to mpversion.h for consistency with mpconfig.h.
2015-04-28 23:52:36 +01:00
Daniel Campora
d11317bcab cc3200: Make WLAN scan results a list of attrtupple.
Each result is displayed like this:

ssid='MySSID', bssid=b'\xc0J\x00z.\xcc', security=2, channel=None, rssi=-74

The CC3200 doesn't provide channel info, that why is 'None'.
2015-04-29 00:04:01 +02:00
Daniel Campora
94792dd88f py: In attrtuple use the correct length value and index for 'fields'. 2015-04-29 00:04:00 +02:00
Daniel Campora
5225e29ce7 cc3200: Remove unneeded -lgcc in Makefile. 2015-04-29 00:03:58 +02:00
Daniel Campora
f81684141e cc3200: Implement os.uname() to get details of the OS and hardware. 2015-04-29 00:03:56 +02:00
Daniel Campora
6fefd5d330 cc3200: Move telnet_process_credential with the other private functions.
Just for consistency.
2015-04-29 00:03:54 +02:00
Damien George
6bbbb1ab41 unix/modffi: Support passing float/double args. 2015-04-28 19:40:34 +01:00
Daniel Campora
f1ed8c8a2e cc3200: Improve telnet_parse_input() in case of an incomplete option. 2015-04-28 16:48:33 +02:00
Matt Anderson
0458833072 cc3200: Make telnet login procedure work with Tera Term.
This is actually a workaround Ter Term's issue of not obeying to the
telnet options that the server is sending. Therefore, we must buffer
chars until either a '\r' or the max length of the username/password
is received.
2015-04-28 16:48:26 +02:00
Daniel Campora
abea1c38a9 lib/libc: Add memchr. We already have strchr, but memchr is useful too. 2015-04-28 16:48:20 +02:00
Daniel Campora
9fbc265eb8 cc3200: Add delays to allow the servers to start and stop properly. 2015-04-28 15:16:33 +02:00
Daniel Campora
d34c4784a5 cc3200: Select NIC when the socket is created.
This makes sense since only WLAN is supported here.
2015-04-28 15:14:36 +02:00
Dave Hylands
fdcb3b7ebb stmhal: Actually disable unhandled timer interrupts. 2015-04-28 00:17:05 -07:00
Damien George
9472907ae1 py: Fix handling of negative numbers in struct.pack of q/Q. 2015-04-25 23:51:14 +01:00
Paul Sokolovsky
ae2c81ff38 vm: On exiting except block, clear sys.exc_info() value.
This doesn't handle case fo enclosed except blocks, but once again,
sys.exc_info() support is a workaround for software which uses it
instead of properly catching exceptions via variable in except clause.
2015-04-26 01:40:37 +03:00
Damien George
0f553fe10b py: Implement power op for long-long implementation of bignum. 2015-04-25 23:28:10 +01:00
Damien George
271d18eb08 py: Support conversion of bignum to bytes.
This gets int.to_bytes working for bignum, and also struct.pack with 'q'
and 'Q' args on 32-bit machines.

Addresses issue #1155.
2015-04-25 23:16:39 +01:00
Daniel Campora
7c8b4c1a8b cc3200: Correct MAKE_SOCKADDR and UNPACK_SOCKADDR byte order. 2015-04-25 23:36:45 +02:00
Paul Sokolovsky
8b85d14b92 modsys: Add basic sys.exc_info() implementation.
The implementation is very basic and non-compliant and provided solely for
CPython compatibility. The function itself is bad Python2 heritage, its
usage is discouraged.
2015-04-25 03:49:23 +03:00
Paul Sokolovsky
cf5b6f6974 objfun: Fix to stackless mode after recent refactor. 2015-04-25 01:43:45 +03:00
Damien George
8c1d23a0e2 py: Modify bytecode "with" behaviour so it doesn't use any heap.
Before this patch a "with" block needed to create a bound method object
on the heap for the __exit__ call.  Now it doesn't because we use
load_method instead of load_attr, and save the method+self on the stack.
2015-04-24 01:52:28 +01:00
Damien George
ede0f3ab3d py: Add optional code to check bytes constructor values are in range.
Compiled in only if MICROPY_CPYTHON_COMPAT is set.

Addresses issue #1093.
2015-04-23 15:28:18 +01:00
Dave Hylands
fd787c5e4e stmhal: Reset the timer counter to zero after changing the auto reload.
Because if the counter is above the new value of the auto-reload register
then it may be a long time until the timer wraps around.
2015-04-22 23:31:56 +01:00
Damien George
40d43ea88d tests: Add more tests for viper, including tests for ViperTypeError's. 2015-04-22 23:18:28 +01:00
Damien George
5e9810396f py/objint_mpz.c: Make int_from_uint actually return uint. 2015-04-22 23:17:34 +01:00
Damien George
f66ee4dfd7 py/mpz.c: Fix bug with shl not truncating zero digits correctly. 2015-04-22 23:16:49 +01:00
Damien George
8f6aad2f48 py/emitnative.c: Fix stack adjustment when erroring on binary op. 2015-04-22 23:16:03 +01:00
Daniel Campora
eaefc8b9d6 cc3200: Add WiPy specific information to README.md 2015-04-22 21:03:10 +02:00
Damien George
1f9e2188a6 tests: Add tests for attrtuple, and for more corner cases. 2015-04-22 16:52:03 +01:00
Damien George
956d765786 py: Fix printing of "inf" and "nan" floating point values. 2015-04-22 16:51:29 +01:00
stijn
c52f1258a8 msvc: Update genhdr script to emit MicroPython version numbers 2015-04-22 12:07:30 +02:00
Damien George
dea853d3a3 docs: Document pyb.stop, pyb.standby and pyb.RTC.wakeup. 2015-04-21 22:35:17 +01:00
Damien George
4735c45c51 py: Clean up some bits and pieces in parser, grammar. 2015-04-21 16:43:18 +00:00
Damien George
fa90ab1407 py: Simplify grammar for stmt rule (this is also how CPython has it). 2015-04-21 16:35:50 +00:00
Damien George
d8837cea6f stmhal: Implement os.uname() to get details of OS and hardware. 2015-04-21 14:51:49 +00:00
Damien George
c3184aea63 py: Add sys.implementation, containing uPy name and version number.
Uses attrtuple if it's enabled, otherwise just a normal tuple.
2015-04-21 14:45:04 +00:00
Damien George
5aa311d330 py: Add attrtuple object, for space-efficient tuples with attr access.
If you need the functionality of a namedtuple but will only make 1 or a
few instances, then use an attrtuple instead.
2015-04-21 14:14:24 +00:00
Damien George
23a2b11abf tools: Add STM32F4DISC and ESPRUINO_PICO to stmhal build script. 2015-04-21 13:16:41 +00:00
Damien George
43d56f9ba9 docs: Bump version to 1.4.2. 2015-04-21 12:51:14 +00:00
Damien George
e521f0eb68 acks: Add 2 names to ACKNOWLEDGEMENTS file. 2015-04-21 11:23:23 +01:00
Damien George
c8b60f013b py: Make viper codegen raise proper exception (ViperTypeError) on error.
This fixes a long standing problem that viper code generation gave
terrible error messages, and actually no errors on pyboard where
assertions are disabled.

Now all compile-time errors are raised as proper Python exceptions, and
are of type ViperTypeError.

Addresses issue #940.
2015-04-20 13:29:31 +00:00
Damien George
2bb5f41611 tools/pyboard.py: Make it 8-bit clean, so it works with unicode chars.
Addresses issue #1190.
2015-04-19 21:31:28 +01:00
Damien George
f35b5d28db stmhal/pyexec.c: Make raw REPL mode 8-bit clean. 2015-04-19 21:30:49 +01:00
Daniel Campora
df5d9c77f4 cc3200: Fix bootloader and modpyb after printf overhaul.
The bootloader needs string0.c because of memset, memcpy and others,
without string0.c it magically links, but calling any of those
functions results in a hard fault.
In debug mode, modpyb needs printf, and including stdio.h leads to
conflicts due to the redefinitions made in the simplelink drivers.
2015-04-19 20:59:10 +02:00
Damien George
d8475092d1 qemu-arm: Disable inline asm tests that use floating point. 2015-04-19 15:50:24 +01:00
=
5008972fef py/inlinethumb: Support for core floating point instructions.
Adds support for the following Thumb2 VFP instructions, via the option
MICROPY_EMIT_INLINE_THUMB_FLOAT:

vcmp
vsqrt
vneg
vcvt_f32_to_s32
vcvt_s32_to_f32
vmrs
vmov
vldr
vstr
vadd
vsub
vmul
vdiv
2015-04-19 15:47:05 +01:00
Damien George
d8cbbcaa9d py: Fix builtin ord so that it can handle bytes values >= 0x80.
Addresses issue #1188.
2015-04-19 12:26:46 +01:00
Damien George
404b68da88 stmhal: Provide ADC capabilities for F401 and F411 MCUs.
Simply needed to define which pins have which ADC channel on them.
2015-04-18 22:39:06 +01:00
Damien George
b42a5050fb stmhal: Add support for STM32F411 MCU. 2015-04-18 22:15:59 +01:00
Damien George
3e592531eb stmhal: For flash storage use same params for F407 as F405. 2015-04-18 22:08:16 +01:00
Damien George
90e6d0c2ac stmhal: Add support for Espruino Pico board.
To build:

make BOARD=ESPRUINO_PICO

To deploy: short the BOOT0/BTN contact on the back of the board (eg by
drawing over it with a graphite pencil), then hold down BTN while
inserting the board into the USB port.  The board should then enter DFU
mode, and the firmware can be downloaded using:

make BOARD=ESPRUINO_PICO deploy
2015-04-18 21:40:59 +01:00
Damien George
e4b4e5aa31 stmhal: Add stm32f401.ld for linking F401 targets. 2015-04-18 21:40:59 +01:00
Damien George
0435e76250 stmhal: Make ld and af files configurable within Makefile.
Each board now needs an mpconfigboard.mk file which defines AF_FILE and
LD_FILE.

Also moved stm32f405.ld to boards/ directory to keep things organised.
2015-04-18 21:40:59 +01:00
Damien George
03ec6e4d01 stmhal: Add stm32f401_af.csv, for AF definitions of F401 MCUs. 2015-04-18 21:40:59 +01:00
Damien George
9253e7bdf7 stmhal: Rename stm32f4xx_af.csv to stm32f405_af.csv.
Since this file is only valid for F405 MCUs, not generic F4xx.
2015-04-18 21:40:59 +01:00
Damien George
6be0bbb886 stmhal: Add support for flash filesystem on F401 MCUs.
It uses a 16k cache buffer and so the filesystem size is limited.
2015-04-18 21:40:59 +01:00
Damien George
5a11086d64 stmhal: Allow extint.c to compile without USB HS support. 2015-04-18 21:40:59 +01:00
Damien George
d15fe5a6b3 stmhal: Make I2C busses and their pins configurable in mpconfigboard.h. 2015-04-18 21:40:59 +01:00
Damien George
8892f71dd0 stmhal: Exclude code for UARTs that don't exist in hardware. 2015-04-18 21:40:58 +01:00
Damien George
73f1a49137 stmhal: Exclude USB HS code when USB HS mode not enabled. 2015-04-18 21:40:58 +01:00
Damien George
c92c7a69fd stmhal: Exclude code for those timers that don't exist in the hardware. 2015-04-18 21:40:58 +01:00
Damien George
7d6595fd18 stmhal: Make LCD initialiser use board pin names instead of cpu names. 2015-04-18 21:40:58 +01:00
Damien George
50ea86fe8b stmhal: For pins, define macros mapping board names to cpu names. 2015-04-18 21:40:58 +01:00
Damien George
2e5704d101 stmhal: Make a HW config option for LED4 being controlled by PWM. 2015-04-18 21:40:58 +01:00
Damien George
8bdbc20e74 stmhal: Make HSE PLL parameters configurable per board. 2015-04-18 21:40:58 +01:00
Daniel Campora
23008db6e1 README.md: Add the CC3200 port to the list of additional components. 2015-04-18 19:49:00 +02:00
Henrik
e3cd154317 stmhal: Add support for sending and receiving CAN RTR messages. 2015-04-18 14:53:00 +01:00
Damien George
259eaab9a9 cc3200: Clean up and reduce use/include of std.h. 2015-04-18 14:29:28 +01:00
Damien George
2764a8ee8d stmhal: Remove std.h. It's not needed anymore. 2015-04-18 14:28:39 +01:00
Damien George
f53a8e712f lib/libc/string0.c: Remove include of std.h, replace with string.h.
Much more portable this way.
2015-04-18 14:27:55 +01:00
Damien George
1c9a499135 py/vstr.c: Allow vstr_printf to print correctly to a fixed buffer.
This patch allows vstr_printf to use all the available space of a fixed
vstr buffer.  vstr_printf is a good alternative to snprintf.
2015-04-18 14:23:13 +01:00
Daniel Campora
c1a77a0c9f cc3200: Use new %q format to print qstr's where appropiate. 2015-04-17 10:15:55 +02:00
Daniel Campora
2cd247e819 cc3200: Clean up bootloader makefile and remove superflous assert. 2015-04-17 09:55:24 +02:00
Damien George
dcbf62b43d acks: Add 1 name to the ACKNOWLEDGEMENTS file. 2015-04-17 00:15:29 +01:00
Damien George
7d5e34287c stmhal: Allow sending CAN messages with timeout=0.
Thanks to Henrik Sölver for this patch.
2015-04-16 23:52:43 +01:00
blmorris
4c45921349 stmhal: Use new %q format to print qstr's in a few more places.
Saves 68 bytes.
2015-04-16 22:30:00 +01:00
Damien George
feff00e1a5 Add .gitattributes file to force text line endings to LF.
Some files are excluded, otherwise a whole lot of files need converting.
2015-04-16 22:23:56 +01:00
Damien George
a102e01ce1 logo: Change line endings in FONT-LICENSE.txt from CRLF to LF. 2015-04-16 22:12:19 +01:00
Damien George
90aa7595b4 tests: Convert line endings in fun_name.py from CRLF to LF. 2015-04-16 22:09:17 +01:00
Damien George
2941d5c714 qemu-arm: Get compiling again with recent changes to print framework. 2015-04-16 21:44:52 +01:00
Damien George
a86d40ccd4 cc3200: Get bootloader compiling with latest overhaul of printf code. 2015-04-16 14:30:17 +00:00
Damien George
044c473de2 py: Add %q format support to mp_[v]printf, and use it. 2015-04-16 14:30:16 +00:00
Damien George
e72cda99fd py: Convert occurrences of non-debug printf to mp_printf. 2015-04-16 14:30:16 +00:00
Damien George
5ae5ec986e py: Make mp_sys_stdout_print object, wrapping sys.stdout for mp_print*.
So now all printing should go via either mp_plat_print or
mp_sys_stdout_print.
2015-04-16 14:30:16 +00:00
Damien George
7f9d1d6ab9 py: Overhaul and simplify printf/pfenv mechanism.
Previous to this patch the printing mechanism was a bit of a tangled
mess.  This patch attempts to consolidate printing into one interface.

All (non-debug) printing now uses the mp_print* family of functions,
mainly mp_printf.  All these functions take an mp_print_t structure as
their first argument, and this structure defines the printing backend
through the "print_strn" function of said structure.

Printing from the uPy core can reach the platform-defined print code via
two paths: either through mp_sys_stdout_obj (defined pert port) in
conjunction with mp_stream_write; or through the mp_plat_print structure
which uses the MP_PLAT_PRINT_STRN macro to define how string are printed
on the platform.  The former is only used when MICROPY_PY_IO is defined.

With this new scheme printing is generally more efficient (less layers
to go through, less arguments to pass), and, given an mp_print_t*
structure, one can call mp_print_str for efficiency instead of
mp_printf("%s", ...).  Code size is also reduced by around 200 bytes on
Thumb2 archs.
2015-04-16 14:30:16 +00:00
Paul Sokolovsky
56beb01724 objarray: Support assignment of bytes to bytearray slice. 2015-04-16 00:51:12 +03:00
Damien George
9a18e21066 acks: Add 2 names to the ACKNOWLEDGEMENTS file. 2015-04-14 22:06:51 +01:00
Daniel Campora
4c37489f4c cc3200: Correct the IP address byte order in the FTP server. 2015-04-14 01:57:29 +02:00
Daniel Campora
f7a26472af cc3200: Add IPPROTO_SEC to be able to create secure sockets. 2015-04-14 01:57:27 +02:00
Damien George
b1f68685ec stmhal: In USB HID driver, make polling interval configurable.
When setting usb_mode to "HID", hid config object now has
polling-interval (in ms) as the 4th element.  It mmust now be a 5-tuple
of the form:

(subclass, protocol, max_packet_len, polling_interval, report_desc)

The mouse and keyboard defaults have polling interval at 8ms.
2015-04-13 16:59:05 +01:00
Daniel Campora
99f7184073 cc3200: Disable MICROPY_COMP_TRIPLE_TUPLE_ASSIGN.
Because it's only a compiler optimization and increases code size.
2015-04-13 00:03:41 +02:00
Daniel Campora
c69b4310c8 cc3200: Add WLAN.config_ip().
This new method allows to assign an static IP to the device.
2015-04-13 00:02:56 +02:00
Dave Hylands
b21786947f py/formatfloat.c: Fix format of floating point numbers near 1.0.
In particular, numbers which are less than 1.0 but which
round up to 1.0.

This also makes those numbers which round up to 1.0 to
print with e+00 rather than e-00 for those formats which
print exponents.

Addresses issue #1178.
2015-04-12 13:06:20 +01:00
Paul Sokolovsky
8b7faa31e1 objstr: split(None): Fix whitespace properly. 2015-04-12 00:17:57 +03:00
Damien George
6eb7530083 py: In emitinlinethumb, use qstr_data instead of qstr_str and strlen. 2015-04-11 21:53:39 +01:00
Damien George
55fe92bb8f py: Remove old debugging printf's in compile.c. 2015-04-11 21:52:27 +01:00
Damien George
7a6dbaa89b stmhal: Make LED object print LED(x) for consistency with constructor. 2015-04-11 21:50:53 +01:00
Damien George
b1bbe966c4 py: Combine load_attr and store_attr type methods into one (attr).
This simplifies the API for objects and reduces code size (by around 400
bytes on Thumb2, and around 2k on x86).  Performance impact was measured
with Pystone score, but change was barely noticeable.
2015-04-11 16:54:37 +01:00
Damien George
d07ccc5a39 lib/fatfs: Space optimise the ff_wtoupper function.
Saves 768 bytes code space on Thumb2 archs.
2015-04-11 15:17:04 +01:00
Daniel Campora
d278e49475 cc3200: Enable TRIPLE_TUPLE_ASSIGN and UBINASCII. 2015-04-11 13:35:07 +02:00
Daniel Campora
6e25d955f4 cc3200: Enable long filename support in FatFS.
This has implications all over the place. I have to admit that
you can instantly see that usability improves, but it costs 3K.
At the same time I took the oportunity to rename the '/SFLASH'
drive to '/flash' which improves compatibility with the pyboard.
2015-04-11 13:35:05 +02:00
Paul Sokolovsky
d35ac956d1 input.c: Fix line-endings after recent changes. 2015-04-10 23:01:58 +03:00
Damien George
91bc32dc16 py: Provide typedefs for function types instead of writing them inline. 2015-04-09 15:31:53 +00:00
Damien George
4dea922610 py: Adjust some spaces in code style/format, purely for consistency. 2015-04-09 15:29:54 +00:00
stijn
df1637c580 unix: Automatically fix incompatible readline build options. 2015-04-09 13:35:16 +00:00
stijn
e50cff69bb py: Use a dummy type for referring to extern structs
Fixes msvc linker warnings about mismatching sizes between the mp_obj_fdfile_t
struct defined in file.c and the mp_uint_t declarations found in modsys.c and modbuiltins.c
2015-04-09 15:03:22 +02:00
stijn
36cc84a2a9 py: Fix msvc warning '*/ found outside of comment'
Also prevents some of the weaker syntax parsers out there treating the whole
'*/*const*/' part as a comment
2015-04-09 12:40:38 +02:00
Damien George
e97dddcdca docs: Document pyb.main function to set main script. 2015-04-09 10:08:25 +01:00
Damien George
9988618e0e py: Implement full func arg passing for native emitter.
This patch gets full function argument passing working with native
emitter.  Includes named args, keyword args, default args, var args
and var keyword args.  Fully Python compliant.

It reuses the bytecode mp_setup_code_state function to do all the hard
work.  This function is slightly adjusted to accommodate native calls,
and the native emitter is forced a bit to emit similar prelude and
code-info as bytecode.
2015-04-07 22:43:28 +01:00
Daniel Campora
18bd51707c cc3200: Enable the stdio UART for the LaunchXL only. 2015-04-07 12:12:16 +02:00
Daniel Campora
c7acfc90b9 cc3200: Enable pull-ups for the STDIO UART pins. 2015-04-07 10:50:20 +02:00
Damien George
c9aa1883ed py: Simplify bytecode prelude when encoding closed over variables. 2015-04-07 00:08:17 +01:00
Damien George
78772ada0d py: Implement calling functions with *args in native emitter. 2015-04-06 22:48:21 +01:00
Paul Sokolovsky
282ca09f8e py: Add MICROPY_PY_BUILTINS_REVERSED, disable for minimal ports. 2015-04-07 00:17:11 +03:00
Paul Sokolovsky
e2d44e30c7 py: Add MICROPY_PY_BUILTINS_ENUMERATE, disable for minimal ports. 2015-04-06 23:51:29 +03:00
Paul Sokolovsky
96b60ed956 cc3200: Fix typo after previous refactor. 2015-04-05 22:32:41 +03:00
Paul Sokolovsky
2192824ad8 teensy: Fix function prototype. 2015-04-05 22:15:37 +03:00
Paul Sokolovsky
3a84c8b58d string0.c: Move from stmhal/ to lib/. 2015-04-05 21:57:55 +03:00
Damien George
e5c4362a98 tests: Add some more tests to improve code coverage of corner cases. 2015-04-05 00:03:43 +01:00
Damien George
97abe22963 tests: Add tests to exercise lexer; and some more complex number tests. 2015-04-04 23:16:22 +01:00
Damien George
9dd3640464 tests: Add missing tests for builtins, and many other things. 2015-04-04 22:05:30 +01:00
Damien George
7e758b1cf8 stmhal, qemu-arm: Enable sys.maxsize attribute. 2015-04-04 22:04:53 +01:00
Daniel Campora
b9d850227d cc3200: Add WLAN AP specific settings for each board. 2015-04-04 22:09:55 +02:00
Damien George
56606f3475 py: Implement delete for property and descriptors.
Without this patch deleting a property, or class with descriptor, will
call the setter with a NULL value and lead to a crash.
2015-04-04 20:15:31 +01:00
Damien George
0528c5a22a py: In str unicode, str_subscr will never be passed a bytes object. 2015-04-04 19:42:03 +01:00
Damien George
0f6424efda docs: Bump version to 1.4.1. 2015-04-04 17:41:11 +01:00
Damien George
40fc01f406 stmhal: Enable new str.splitlines() method. 2015-04-04 16:02:23 +01:00
Damien George
2801e6fad8 py: Some trivial cosmetic changes, for code style consistency. 2015-04-04 15:53:11 +01:00
Paul Sokolovsky
7f59b4b2ca objstr: Fix bugs introduced by inability to have shadow variables.
Warnings lead to programming errors - as expected.
2015-04-04 01:55:40 +03:00
Paul Sokolovsky
acf6aec71c objstr: Avoid variable shadowing. 2015-04-04 01:24:59 +03:00
Paul Sokolovsky
620058cc57 tests: Add test for str.splitlines(). 2015-04-04 00:09:54 +03:00
Paul Sokolovsky
ac2f7a7f6a objstr: Add .splitlines() method.
splitlines() occurs ~179 times in CPython3 standard library, so was
deemed worthy to implement. The method has subtle semantic differences
from just .split("\n"). It is also defined as working for any end-of-line
combination, but this is currently not implemented - it works only with
LF line-endings (which should be OK for text strings on any platforms,
but not OK for bytes).
2015-04-04 00:09:48 +03:00
Damien George
82f37bf0d1 tests: Add specific test for closures in native emitter. 2015-04-03 16:14:25 +01:00
Damien George
fa5950eb00 py: Fix bug in native emitter when closing over an argument. 2015-04-03 15:03:24 +00:00
Damien George
99957384ea py: Get native emitter working again with x86 (now supports closures). 2015-04-03 14:38:41 +00:00
Damien George
4cd9ced8dc py: Implement closures in native code generator.
Currently supports only x64 and Thumb2 archs.
2015-04-03 15:05:53 +01:00
Damien George
2cc5473021 py: Implement (non-compliant) support for delete_fast in native emitter.
This implementation is smaller (in code size) than #1024.
2015-04-03 14:29:30 +01:00
Damien George
c0dcf6e878 README: Add note about pic16bit port. 2015-04-03 14:16:49 +01:00
Damien George
43ea73faa6 pic16bit: Initial version of port to 16-bit PIC family.
Reference MCU is dsPIC33J256GP506 with 256k ROM and 8k RAM, on the dsPIC
DSC Starter Kit board.  The REPL works, GC works, pyb module has LED and
Switch objects.  It passes some tests from the test suite (most it can't
run because it doesn't have the Python features enabled).
2015-04-03 14:11:19 +01:00
Damien George
12ab9eda8d py: Make heap printing compatible with 16-bit word size. 2015-04-03 14:11:13 +01:00
Damien George
3f327cc4c6 py: Allow MPZ_DIG_SIZE to be optionally configured by a port. 2015-04-03 14:11:13 +01:00
Damien George
567184e21e py: Allow configurable object representation, with 2 different options. 2015-04-03 14:11:13 +01:00
Damien George
12a5e17afb py: Add finer configuration of static funcs when not in stackless mode.
Also rename call_args_t to mp_call_args_t.
2015-04-02 22:56:58 +01:00
Paul Sokolovsky
dbc0191d5f unix: Add stackless config settings, for easy access. 2015-04-03 00:27:14 +03:00
Paul Sokolovsky
7f1c98177b vm: Support strict stackless mode, with proper exception reporting.
I.e. in this mode, C stack will never be used to call a Python function,
but if there's no free heap for a call, it will be reported as
RuntimeError (as expected), not MemoryError.
2015-04-03 00:26:47 +03:00
Paul Sokolovsky
f0a8f21190 vm: Implement stackless for CALL_FUNCTION_VAR_KW & CALL_METHOD_VAR_KW. 2015-04-03 00:03:07 +03:00
Paul Sokolovsky
e6c6fe3275 runtime: Split mp_call_prepare_args_n_kw_var() from mp_call_method_n_kw_var().
Allow for reuse for stackless design, where preparing args is separate from
calling.
2015-04-03 00:03:07 +03:00
Paul Sokolovsky
390e92688c vm: Stackless support for MP_BC_CALL_METHOD. 2015-04-03 00:03:07 +03:00
Paul Sokolovsky
332a909d44 vm: If there's no heap to call function in stackless manner, call via C stack. 2015-04-03 00:03:07 +03:00
Paul Sokolovsky
2039757b85 vm: Initial support for calling bytecode functions w/o C stack ("stackless"). 2015-04-03 00:03:07 +03:00
Paul Sokolovsky
f88eec0de2 makeqstrdata.py: Add support for strings with backslash escapes. 2015-04-02 01:10:11 +03:00
Damien George
2686f9b3e8 py: Fix emitnative's creation of small ints so it uses the macro. 2015-04-01 00:12:43 +01:00
Daniel Campora
d460a30711 cc3200: Add specific version file for the CC3200 port.
Current version has been numbered as 0.9.0 since Timers/PWM support
is still missing.
2015-03-31 14:34:09 +02:00
Daniel Campora
3f42f32648 cc3200: Remove duplicated code from moduos.
Error reporting is also changed from detailed to terse, as with the
rest of the CC3200's modules. All this combined saves ~200 bytes.
2015-03-31 14:34:07 +02:00
Paul Sokolovsky
344057ac50 docs: uctypes: Bullet list formatting fixes. 2015-03-31 01:29:07 +03:00
Paul Sokolovsky
9d2c0c231c docs: uctypes: Describe how to instantiate struct objects. 2015-03-31 01:16:14 +03:00
Paul Sokolovsky
1bc534247c objtype: Add special unary methods __pos__, __neg__, __invert__.
Conditional on MICROPY_PY_ALL_SPECIAL_METHODS.
2015-03-31 01:05:03 +03:00
Paul Sokolovsky
fdaac1dbf8 modbuiltins: round(): Accept second arg, and at least support it to be 0.
Per https://docs.python.org/3/library/functions.html#round, 2-args format
guaranteedly returns float.
2015-03-31 01:02:44 +03:00
Ivan Pejić
e178ef2520 docs: Add additional example/note for Timer's callback usage.
Add example: using named function for the Timer's callback.
Add note: improving traceback inside interrupt timers.
2015-03-30 00:43:04 +01:00
Damien George
47098efbda docs: Provide initial documentation for micropython module. 2015-03-30 00:32:29 +01:00
Daniel Campora
7b19e99edd lib: Update FatFs to R0.11.
There are lots of cosmetic changes, but this release brings a  very
important bug fix:
 - Fixed f_unlink() does not remove cluster chain of the file.

With R0.10c if you try to write a file that is too large to fit in the
free space of the drive, the operation fails, you delete the incomplete
file, and it seems to be erased, but the space is not really freed,
because any subsequent write operations fail because the drive is
"still" full. The only way to recover from this is by formatting the
drive. I can confirm that R0.11 fixes the problem.
2015-03-29 22:12:14 +01:00
417 changed files with 11076 additions and 4585 deletions

31
.gitattributes vendored Normal file
View File

@@ -0,0 +1,31 @@
# Per default everything gets normalized and gets LF line endings on checkout.
* text eol=lf
# These will always have CRLF line endings on checkout.
*.vcxproj text eol=crlf
*.props text eol=crlf
*.bat text eol=crlf
# These are binary so should never be modified by git.
*.png binary
*.jpg binary
*.dxf binary
# These should also not be modified by git.
tests/basics/string_cr_conversion.py -text
tests/basics/string_crlf_conversion.py -text
stmhal/startup_stm32f40xx.s -text
stmhal/pybcdc.inf_template -text
stmhal/usbd_* -text
stmhal/boards/*/stm32f4xx_hal_conf.h -text
stmhal/cmsis/** -text
stmhal/hal/** -text
stmhal/usbdev/** -text
stmhal/usbhost/** -text
cc3200/hal/aes.c -text
cc3200/hal/aes.h -text
cc3200/hal/des.c -text
cc3200/hal/i2s.c -text
cc3200/hal/i2s.h -text
cc3200/version.h -text
lib/fatfs/** -text

4
.gitignore vendored
View File

@@ -33,5 +33,7 @@ tests/*.out
######################
__pycache__/
# Customized Makefile overrides
# Customized Makefile/project overrides
######################
GNUmakefile
user.props

View File

@@ -339,6 +339,7 @@ today. The names appear in order of pledging.
668 pmst - Italy
671 Sergio Conde Gómez (skgsergio)
672 Micromint, www.micromint.com
673 Xie Yanbo, China
675 Thank you
677 Kacem Ben Dhiab
679 CornishSteve
@@ -375,6 +376,7 @@ today. The names appear in order of pledging.
759 Padraic D. Hallinan
760 Rob Fairbairn
763 Zac Luzader
768 Sam Shams
773 terje nagel, dk
775 Luc LEGER
782 Luis M. Morales S.
@@ -417,6 +419,7 @@ today. The names appear in order of pledging.
868 Stephan Schulte, Germany
869 Kenneth Henderick
872 DaveP (www.davepeake.com)
873 Markus Schuss, Austria
876 Kyle Gordon, http://lodge.glasgownet.com
877 Joseph Gerard Campbell
881 Thanks for the board. Good luck to you. --Jason Doege
@@ -477,6 +480,7 @@ today. The names appear in order of pledging.
1007 Charles V Bock - Charles at CharlesBock dot com
1010 Remember June 4th, 1989
1012 Stuart Marsden
1013 Herbert Graef, Stuttgart
1014 Arthur P, USA
1015 John Hall & Jeremy Armijo
1017 Luciano Ramalho, Python.pro.br
@@ -690,6 +694,7 @@ today. The names appear in order of pledging.
1499 Ronald Eddy
1500 SynShop Las Vegas
1503 This is really cool. - Jack Conway
1505 Victor Suarez, Argentina
1507 Renesas Electronics America
1509 Team
1513 A. Lamborn KD0ZFY
@@ -889,6 +894,7 @@ today. The names appear in order of pledging.
1922 Nicci Tofts
1925 Joshua Coxwell
1926 Franklin Hamilton
1928 Peter Korcz
1929 Leroy Douglas
1930 A ナルと fan from Nigeria who likes smileys, here's one for good measure :)
1931 Kimmo Lahtinen, Finland

8
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,8 @@
When reporting an issue and especially submitting a pull request, please
make sure that you are acquainted with Contributor Guidelines:
https://github.com/micropython/micropython/wiki/ContributorGuidelines
and Code Conventions:
https://github.com/micropython/micropython/blob/master/CODECONVENTIONS.md

View File

@@ -44,6 +44,8 @@ Additional components:
mostly to control code size.
- teensy/ -- a version of Micro Python 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.
- 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.

View File

@@ -6,7 +6,6 @@
#include "py/compile.h"
#include "py/runtime.h"
#include "py/repl.h"
#include "py/pfenv.h"
void do_str(const char *src) {
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
@@ -23,7 +22,7 @@ void do_str(const char *src) {
nlr_pop();
} else {
// uncaught exception
mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t)nlr.ret_val);
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
}
}

View File

@@ -27,6 +27,7 @@
#define MICROPY_PY___FILE__ (0)
#define MICROPY_PY_GC (0)
#define MICROPY_PY_ARRAY (0)
#define MICROPY_PY_ATTRTUPLE (0)
#define MICROPY_PY_COLLECTIONS (0)
#define MICROPY_PY_MATH (0)
#define MICROPY_PY_CMATH (0)

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 ) 72 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 64 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 16384 ) )
#define configMAX_TASK_NAME_LEN ( 8 )
#define configUSE_TRACE_FACILITY 0

View File

@@ -28,12 +28,12 @@ make BTARGET=bootloader BTYPE=release
- Make sure that you have built both the *bootloader* and the *application* in **release** mode.
- Make sure the SOP2 jumper is in position.
- Open CCS_Uniflash and connect to the board (by default on port 22).
- Format the serial flash (select 1MB size in case of the CC3200-LAUNCHXL, leave the rest unchecked).
- Format the serial flash (select 1MB size in case of the CC3200-LAUNCHXL, 2MB in case of the WiPy, leave the rest unchecked).
- Mark the following files for erasing: `/cert/ca.pem`, `/cert/client.pm`, `/cert/private.key` and `/tmp/pac.bin`.
- Add a new file with the name of /sys/mcuimg.bin, and select the URL to point to cc3200\bootmgr\build\<BOARD_NAME>\bootloader.bin.
- Add another file with the name of /sys/factimg.bin, and select the URL to point to cc3200\build\<BOARD_NAME>\MCUIMG.BIN.
- Add another file with the name of /sys/factimg.bin, and select the URL to point to cc3200\build\<BOARD_NAME>\mcuimg.bin.
- Click "Program" to apply all changes.
- Flash the latest service pack (servicepack_1.0.0.1.2.bin) using the "Service Pack Update" button.
- Flash the latest service pack (servicepack_1.0.0.10.0.bin) using the "Service Pack Update" button.
- Close CCS_Uniflash, remove the SOP2 jumper and reset the board.
## Playing with MicroPython and the CC3200:
@@ -43,15 +43,14 @@ Once the software is running, you have two options to access the MicroPython REP
- 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 = "micropy-wlan", key = "micropython"**
* 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
different ssid and/or key.
* Use your favourite telnet client with the following settings: **host = 192.168.1.1, port = 23.**
* Log in with **user = "micro" and password = "python"**
The board has a small file system of 64K located in the serial flash connected to the CC3200. SD cards are also supported, but
since the CC3200 LaunchXL doesn't come with an SD card socket installed, you will need to add one yourself. Any SD card breakout
board will do, as long as you connect it as described here: <http://processors.wiki.ti.com/index.php/CC32xx_SDHost_FatFS>
The board has a small file system of 192K (WiPy) or 64K (Launchpad) located in the serial flash connected to the CC3200.
SD cards are also supported, you can connect any SD card and configure the pinout using the SD class API.
## Uploading scripts:
@@ -64,14 +63,14 @@ not 100% sure of it.
## Upgrading the firmware Over The Air:
OTA software updates can be performed through the FTP server. After building a new MCUIMG.BIN in release mode, upload it to:
`/SFLASH/SYS/MCUIMG.BIN` it will take around 8s (The TI simplelink file system is quite slow because every file is mirrored for
safety). You won't see the file being stored inside `/SFLASH/SYS/` because it's actually saved bypassing FatFS, but rest assured that
`/flash/sys/mcuimg.bin` it will take around 6s (The TI simplelink file system is quite slow because every file is mirrored for
safety). You won't see the file being stored inside `/flash/sys/` because it's actually saved bypassing FatFS, but rest assured that
the file was successfully transferred, and it has been signed with a MD5 checksum to verify its integrity.
Now, reset the MCU by pressing the switch on the board, or by typing:
```python
import pyb
pyb.hard_reset()
pyb.reset()
```
### Note regarding FileZilla:

View File

@@ -20,6 +20,8 @@ APP_INC += -I$(BUILD)
APP_INC += -I$(BUILD)/genhdr
APP_INC += -I../lib/fatfs
APP_INC += -I../lib/mp-readline
APP_INC += -I../lib/netutils
APP_INC += -I../lib/timeutils
APP_INC += -I../stmhal
APP_CPPDEFINES = -Dgcc -DTARGET_IS_CC3200 -DSL_FULL -DUSE_FREERTOS
@@ -80,7 +82,6 @@ APP_MISC_SRC_C = $(addprefix misc/,\
mperror.c \
mpexception.c \
mpsystick.c \
pin_defs_cc3200.c \
)
APP_MODS_SRC_C = $(addprefix mods/,\
@@ -140,7 +141,11 @@ APP_MAIN_SRC_C = \
APP_LIB_SRC_C = $(addprefix lib/,\
fatfs/ff.c \
fatfs/option/ccsbcs.c \
libc/string0.c \
mp-readline/readline.c \
netutils/netutils.c \
timeutils/timeutils.c \
)
APP_STM_SRC_C = $(addprefix stmhal/,\
@@ -154,7 +159,6 @@ APP_STM_SRC_C = $(addprefix stmhal/,\
printf.c \
pyexec.c \
pybstdio.c \
string0.c \
)
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(APP_FATFS_SRC_C:.c=.o) $(APP_RTOS_SRC_C:.c=.o) $(APP_FTP_SRC_C:.c=.o) $(APP_HAL_SRC_C:.c=.o) $(APP_MISC_SRC_C:.c=.o))
@@ -206,7 +210,7 @@ endif
SHELL = bash
APP_SIGN = appsign.sh
all: $(BUILD)/MCUIMG.BIN
all: $(BUILD)/mcuimg.bin
$(BUILD)/application.axf: $(OBJ) $(LINKER_SCRIPT)
$(ECHO) "LINK $@"
@@ -217,7 +221,7 @@ $(BUILD)/application.bin: $(BUILD)/application.axf
$(ECHO) "Create $@"
$(Q)$(OBJCOPY) -O binary $< $@
$(BUILD)/MCUIMG.BIN: $(BUILD)/application.bin
$(BUILD)/mcuimg.bin: $(BUILD)/application.bin
$(ECHO) "Create $@"
$(Q)$(SHELL) $(APP_SIGN) $(BOARD) $(BTYPE)

View File

@@ -16,13 +16,13 @@ BUILD=build/${BOARD}/${BTYPE}
echo -n `md5sum --binary $BUILD/application.bin | awk '{ print $1 }'` > __md5hash.bin
# Concatenate it with the application binary
cat $BUILD/application.bin __md5hash.bin > $BUILD/MCUIMG.BIN
cat $BUILD/application.bin __md5hash.bin > $BUILD/mcuimg.bin
RET=$?
# Remove the tmp files
rm -f __md5hash.bin
# Remove hte unsigned binary
# Remove the unsigned binary
rm -f $BUILD/application.bin
exit $RET

View File

@@ -25,7 +25,7 @@
* THE SOFTWARE.
*/
#define LAUNCHXL
#define WIPY_SD
#define MICROPY_HW_BOARD_NAME "WiPy-SD"
#define MICROPY_HW_MCU_NAME "CC3200"

View File

@@ -25,7 +25,7 @@
* THE SOFTWARE.
*/
#define LAUNCHXL
#define WIPY
#define MICROPY_HW_BOARD_NAME "WiPy"
#define MICROPY_HW_MCU_NAME "CC3200"

View File

@@ -60,17 +60,20 @@ BOOT_MAIN_SRC_S = \
bootmgr/runapp.s
BOOT_PY_SRC_C = $(addprefix py/,\
pfenv.c \
pfenv_printf.c \
mpprint.c \
)
BOOT_STM_SRC_C = $(addprefix stmhal/,\
printf.c \
string0.c \
)
BOOT_LIB_SRC_C = $(addprefix lib/,\
libc/string0.c \
)
OBJ = $(addprefix $(BUILD)/, $(BOOT_HAL_SRC_C:.c=.o) $(BOOT_SL_SRC_C:.c=.o) $(BOOT_CC3100_SRC_C:.c=.o) $(BOOT_UTIL_SRC_C:.c=.o) $(BOOT_MISC_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(BOOT_MAIN_SRC_C:.c=.o) $(BOOT_MAIN_SRC_S:.s=.o) $(BOOT_PY_SRC_C:.c=.o) $(BOOT_STM_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(BOOT_LIB_SRC_C:.c=.o))
# Add the linker script
LINKER_SCRIPT = bootmgr/bootmgr.lds
@@ -125,6 +128,6 @@ $(BUILD)/bootloader.bin: $(BUILD)/bootmgr.bin
$(HEADER_BUILD)/qstrdefs.generated.h: | $(HEADER_BUILD)
touch $@
# Create an empty "py-version.h" needed by py/mkrules.mk
$(HEADER_BUILD)/py-version.h: | $(HEADER_BUILD)
# Create an empty "mpversion.h" needed by py/mkrules.mk
$(HEADER_BUILD)/mpversion.h: | $(HEADER_BUILD)
touch $@

View File

@@ -26,7 +26,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <std.h>
#include "std.h"
#include "py/mpconfig.h"
#include MICROPY_HAL_H
@@ -62,7 +62,7 @@
#define BOOTMGR_HASH_SIZE 32
#define BOOTMGR_BUFF_SIZE 512
#define BOOTMGR_WAIT_SAFE_MODE_MS 1600
#define BOOTMGR_WAIT_SAFE_MODE_MS 1200
#define BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS 200
#define BOOTMGR_SAFE_MODE_ENTER_MS 800
@@ -196,7 +196,7 @@ static bool bootmgr_verify (void) {
}
// read the hash from the file and close it
ASSERT (BOOTMGR_HASH_SIZE == sl_FsRead(fHandle, offset, bootmgr_file_buf, BOOTMGR_HASH_SIZE));
sl_FsRead(fHandle, offset, bootmgr_file_buf, BOOTMGR_HASH_SIZE);
sl_FsClose (fHandle, NULL, NULL, 0);
bootmgr_file_buf[BOOTMGR_HASH_SIZE] = '\0';
// compare both hashes
@@ -347,3 +347,12 @@ int main (void) {
}
}
//*****************************************************************************
//! The following stub function is needed to link mp_vprintf
//*****************************************************************************
#include "py/qstr.h"
const byte *qstr_data(qstr q, mp_uint_t *len) {
*len = 0;
return NULL;
}

View File

@@ -15,12 +15,12 @@
#if MICROPY_HW_HAS_SDCARD
#include "sd_diskio.h" /* SDCARD disk IO API */
#endif
#include "modutime.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "rom_map.h"
#include "prcm.h"
#include "timeutils.h"
/* Definitions of physical drive number for each drive */
#define SFLASH 0 /* Map SFLASH drive to drive number 0 */
@@ -192,13 +192,13 @@ DWORD get_fattime (
void
)
{
mod_struct_time tm;
timeutils_struct_time_t tm;
uint32_t seconds;
uint16_t mseconds;
// Get the time from the on-chip RTC and convert it to struct_time
MAP_PRCMRTCGet(&seconds, &mseconds);
mod_time_seconds_since_2000_to_struct_time(seconds, &tm);
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
return ((tm.tm_year - 1980) << 25) | ((tm.tm_mon) << 21) |
((tm.tm_mday) << 16) | ((tm.tm_hour) << 11) |

View File

@@ -25,7 +25,6 @@
*/
#include <string.h>
#include <std.h>
#include "py/mpconfig.h"
#include "py/misc.h"
@@ -38,7 +37,6 @@ extern BYTE ff_CurrVol;
#endif
STATIC bool check_path(const TCHAR **path, const char *mount_point_str, mp_uint_t mount_point_len) {
stoupper ((char *)(*path));
if (strncmp(*path, mount_point_str, mount_point_len) == 0) {
if ((*path)[mount_point_len] == '/') {
*path += mount_point_len;
@@ -66,11 +64,11 @@ int ff_get_ldnumber (const TCHAR **path) {
#endif
}
if (check_path(path, "/SFLASH", 7)) {
if (check_path(path, "/flash", 6)) {
return 0;
}
#if MICROPY_HW_HAS_SDCARD
else if (check_path(path, "/SD", 3)) {
else if (check_path(path, "/sd", 3)) {
return 1;
}
#endif
@@ -84,13 +82,13 @@ void ff_get_volname(BYTE vol, TCHAR **dest) {
if (vol == 0)
#endif
{
memcpy(*dest, "/SFLASH", 7);
memcpy(*dest, "/flash", 6);
*dest += 7;
}
#if MICROPY_HW_HAS_SDCARD
else
{
memcpy(*dest, "/SD", 3);
memcpy(*dest, "/sd", 3);
*dest += 3;
}
#endif

View File

@@ -1,6 +1,35 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file R0.10c (C)ChaN, 2014
/---------------------------------------------------------------------------*/
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* Original file from:
* FatFs - FAT file system module configuration file R0.10c (C)ChaN, 2014
*
* 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.
*/
#ifndef _FFCONF
#define _FFCONF 32020 /* Revision ID */
#include <stdint.h>
#include "py/mpconfig.h"
@@ -8,8 +37,6 @@
#include "task.h"
#include "semphr.h"
#define _FFCONF 80376 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Functions and Buffer Configurations
/---------------------------------------------------------------------------*/
@@ -24,9 +51,9 @@
#define _FS_READONLY 0
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes basic writing API functions, f_write(),
/ f_sync(), f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(),
/ f_getfree() and optional writing functions as well. */
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
#define _FS_MINIMIZE 0
@@ -48,9 +75,13 @@
/ 2: Enable with LF-CRLF conversion. */
#define _USE_FIND 0
/* This option switches filtered directory read feature and related functions,
/ f_findfirst() and f_findnext(). (0:Disable or 1:Enable) */
#define _USE_MKFS 1
/* This option switches f_mkfs() function. (0:Disable or 1:Enable)
/ To enable it, also _FS_READONLY need to be set to 0. */
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define _USE_FASTSEEK 0
@@ -63,8 +94,8 @@
#define _USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/* To enable it, also _FS_TINY need to be set to 1. */
/* This option switches f_forward() function. (0:Disable or 1:Enable)
/ To enable it, also _FS_TINY need to be set to 1. */
/*---------------------------------------------------------------------------/
@@ -75,32 +106,24 @@
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
/ 932 - Japanese Shift_JIS (DBCS, OEM, Windows)
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
/ 949 - Korean (DBCS, OEM, Windows)
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
/ 1250 - Central Europe (Windows)
/ 1251 - Cyrillic (Windows)
/ 1252 - Latin 1 (Windows)
/ 1253 - Greek (Windows)
/ 1254 - Turkish (Windows)
/ 1255 - Hebrew (Windows)
/ 1256 - Arabic (Windows)
/ 1257 - Baltic (Windows)
/ 1258 - Vietnam (OEM, Windows)
/ 437 - U.S. (OEM)
/ 720 - Arabic (OEM)
/ 737 - Greek (OEM)
/ 775 - Baltic (OEM)
/ 850 - Multilingual Latin 1 (OEM)
/ 858 - Multilingual Latin 1 + Euro (OEM)
/ 852 - Latin 2 (OEM)
/ 855 - Cyrillic (OEM)
/ 866 - Russian (OEM)
/ 857 - Turkish (OEM)
/ 862 - Hebrew (OEM)
/ 874 - Thai (OEM, Windows)
/ 1 - ASCII (No extended character. Valid for only non-LFN configuration.) */
/ 1 - ASCII (No extended character. Non-LFN cfg. only)
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
/ 775 - Baltic
/ 850 - Multilingual Latin 1
/ 852 - Latin 2
/ 855 - Cyrillic
/ 857 - Turkish
/ 858 - Multilingual Latin 1 + Euro
/ 862 - Hebrew
/ 866 - Russian
/ 874 - Thai
/ 932 - Japanese Shift_JIS (DBCS)
/ 936 - Simplified Chinese GBK (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese Big5 (DBCS)
*/
#define _USE_LFN (MICROPY_ENABLE_LFN)
@@ -155,8 +178,8 @@
/* Number of volumes (logical drives) to be used. */
#define _STR_VOLUME_ID 0
#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
#define _STR_VOLUME_ID 0
#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
/* _STR_VOLUME_ID option switches string volume ID feature.
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
@@ -169,7 +192,7 @@
/ number is bound to the same physical drive number and only an FAT volume found on
/ the physical drive will be mounted. When multi-partition feature is enabled (1),
/ each logical drive number is bound to arbitrary physical drive and partition
/ listed in the VolToPart[]. Also f_fdisk() funciton will be enabled. */
/ listed in the VolToPart[]. Also f_fdisk() funciton will be available. */
#define _MIN_SS 512
@@ -206,9 +229,9 @@
/---------------------------------------------------------------------------*/
#define _FS_NORTC 0
#define _NORTC_MON 11
#define _NORTC_MDAY 9
#define _NORTC_YEAR 2014
#define _NORTC_MON 2
#define _NORTC_MDAY 1
#define _NORTC_YEAR 2015
/* The _FS_NORTC option switches timestamp feature. If the system does not have
/ an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to disable
/ the timestamp feature. All objects modified by FatFs will have a fixed timestamp
@@ -274,3 +297,4 @@
/ PIC32 0 H8/300H 0 8051 0/1
*/
#endif // _FFCONF

View File

@@ -3,8 +3,6 @@
/* (C)ChaN, 2014 */
/*------------------------------------------------------------------------*/
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "ff.h"
@@ -134,7 +132,7 @@ void* ff_memalloc ( /* Returns pointer to the allocated memory block */
UINT msize /* Number of bytes to allocate */
)
{
return malloc(msize); /* Allocate a new memory block with POSIX API */
return pvPortMalloc(msize); /* Allocate a new memory block with POSIX API */
}
@@ -146,7 +144,7 @@ void ff_memfree (
void* mblock /* Pointer to the memory block to free */
)
{
free(mblock); /* Discard the memory block with POSIX API */
vPortFree(mblock); /* Discard the memory block with POSIX API */
}
#endif

View File

@@ -26,7 +26,7 @@
#include <stdint.h>
#include <ctype.h>
#include <std.h>
#include "std.h"
#include "py/mpconfig.h"
#include MICROPY_HAL_H
@@ -40,7 +40,6 @@
#include "ftp.h"
#include "simplelink.h"
#include "modwlan.h"
#include "modutime.h"
#include "debug.h"
#include "serverstask.h"
#include "ff.h"
@@ -49,6 +48,7 @@
#include "diskio.h"
#include "sd_diskio.h"
#include "updater.h"
#include "timeutils.h"
/******************************************************************************
@@ -301,19 +301,21 @@ void ftp_run (void) {
if (SOCKETFIFO_IsEmpty()) {
uint32_t readsize;
ftp_result_t result;
ftp_data.ctimeout = 0;
result = ftp_read_file ((char *)ftp_data.dBuffer, FTP_BUFFER_SIZE, &readsize);
if (readsize > 0 && result != E_FTP_RESULT_FAILED) {
ftp_send_data(readsize);
ftp_data.ctimeout = 0;
if (result == E_FTP_RESULT_FAILED) {
ftp_send_reply(451, NULL);
ftp_data.state = E_FTP_STE_END_TRANSFER;
}
else {
if (readsize > 0) {
ftp_send_data(readsize);
}
if (result == E_FTP_RESULT_OK) {
ftp_send_reply(226, NULL);
ftp_data.state = E_FTP_STE_END_TRANSFER;
}
}
else {
ftp_send_reply(451, NULL);
ftp_data.state = E_FTP_STE_END_TRANSFER;
}
}
break;
case E_FTP_STE_CONTINUE_FILE_RX:
@@ -433,7 +435,7 @@ static bool ftp_create_listening_socket (_i16 *sd, _u16 port, _u8 backlog) {
// Bind the socket to a port number
sServerAddress.sin_family = AF_INET;
sServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);
sServerAddress.sin_addr.s_addr = INADDR_ANY;
sServerAddress.sin_port = htons(port);
ASSERT (sl_Bind(_sd, (const SlSockAddr_t *)&sServerAddress, sizeof(sServerAddress)) == SL_SOC_OK);
@@ -588,8 +590,12 @@ static void ftp_process_cmd (void) {
char *bufptr = (char *)ftp_cmd_buffer;
ftp_result_t result;
uint32_t listsize;
FILINFO fno;
FRESULT fres;
FILINFO fno;
#if _USE_LFN
fno.lfname = NULL;
fno.lfsize = 0;
#endif
ftp_data.closechild = false;
// also use the reply buffer to receive new commands
@@ -665,7 +671,7 @@ static void ftp_process_cmd (void) {
case E_FTP_CMD_USER:
ftp_pop_param (&bufptr, ftp_scratch_buffer);
if (!memcmp(ftp_scratch_buffer, servers_user, MAX(strlen(ftp_scratch_buffer), strlen(servers_user)))) {
ftp_data.loggin.uservalid = true;
ftp_data.loggin.uservalid = true && (strlen(servers_user) == strlen(ftp_scratch_buffer));
}
ftp_send_reply(331, NULL);
break;
@@ -673,12 +679,13 @@ static void ftp_process_cmd (void) {
ftp_pop_param (&bufptr, ftp_scratch_buffer);
if (!memcmp(ftp_scratch_buffer, servers_pass, MAX(strlen(ftp_scratch_buffer), strlen(servers_pass))) &&
ftp_data.loggin.uservalid) {
ftp_data.loggin.passvalid = true;
ftp_send_reply(230, NULL);
}
else {
ftp_send_reply(530, NULL);
ftp_data.loggin.passvalid = true && (strlen(servers_pass) == strlen(ftp_scratch_buffer));
if (ftp_data.loggin.passvalid) {
ftp_send_reply(230, NULL);
break;
}
}
ftp_send_reply(530, NULL);
break;
case E_FTP_CMD_PASV:
{
@@ -695,7 +702,7 @@ static void ftp_process_cmd (void) {
ftp_data.dtimeout = 0;
wlan_get_ip(&ip);
snprintf((char *)ftp_data.dBuffer, FTP_BUFFER_SIZE, "(%u,%u,%u,%u,%u,%u)",
pip[0], pip[1], pip[2], pip[3], (FTP_PASIVE_DATA_PORT >> 8), (FTP_PASIVE_DATA_PORT & 0xFF));
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_send_reply(227, (char *)ftp_data.dBuffer);
}
@@ -877,7 +884,7 @@ static int ftp_print_eplf_item (char *dest, uint32_t destsize, FILINFO *fno) {
uint16_t mseconds;
uint mindex = (((fno->fdate >> 5) & 0x0f) > 0) ? (((fno->fdate >> 5) & 0x0f) - 1) : 0;
uint day = ((fno->fdate & 0x1f) > 0) ? (fno->fdate & 0x1f) : 1;
uint fseconds = mod_time_seconds_since_2000(1980 + ((fno->fdate >> 9) & 0x7f),
uint fseconds = timeutils_seconds_since_2000(1980 + ((fno->fdate >> 9) & 0x7f),
(fno->fdate >> 5) & 0x0f,
fno->fdate & 0x1f,
(fno->ftime >> 11) & 0x1f,
@@ -887,22 +894,30 @@ static int ftp_print_eplf_item (char *dest, uint32_t destsize, FILINFO *fno) {
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,
#if _USE_LFN
1980 + ((fno->fdate >> 9) & 0x7f), *fno->lfname ? fno->lfname : fno->fname);
#else
1980 + ((fno->fdate >> 9) & 0x7f), fno->fname);
#endif
}
else {
return snprintf(dest, destsize, "%srw-rw-r-- 1 root root %9u %s %2u %02u:%02u %s\r\n",
type, (_u32)fno->fsize, ftp_month[mindex].month, day,
#if _USE_LFN
(fno->ftime >> 11) & 0x1f, (fno->ftime >> 5) & 0x3f, *fno->lfname ? fno->lfname : fno->fname);
#else
(fno->ftime >> 11) & 0x1f, (fno->ftime >> 5) & 0x3f, fno->fname);
#endif
}
}
static int ftp_print_eplf_drive (char *dest, uint32_t destsize, char *name) {
mod_struct_time tm;
timeutils_struct_time_t tm;
uint32_t tseconds;
uint16_t mseconds;
char *type = "d";
mod_time_seconds_since_2000_to_struct_time((FTP_UNIX_TIME_20150101 - FTP_UNIX_TIME_20000101), &tm);
timeutils_seconds_since_2000_to_struct_time((FTP_UNIX_TIME_20150101 - FTP_UNIX_TIME_20000101), &tm);
MAP_PRCMRTCGet(&tseconds, &mseconds);
if (FTP_UNIX_SECONDS_180_DAYS < tseconds - (FTP_UNIX_TIME_20150101 - FTP_UNIX_TIME_20000101)) {
@@ -956,10 +971,10 @@ static ftp_result_t ftp_open_dir_for_listing (const char *path, char *list, uint
uint next = 0;
// "hack" to list root directory
if (path[0] == '/' && path[1] == '\0') {
next += ftp_print_eplf_drive((list + next), (maxlistsize - next), "SFLASH");
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");
next += ftp_print_eplf_drive((list + next), (maxlistsize - next), "sd");
}
#endif
*listsize = next;
@@ -979,11 +994,18 @@ static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *li
uint next = 0;
uint count = 0;
FRESULT res;
FILINFO fno;
ftp_result_t result = E_FTP_RESULT_CONTINUE;
FILINFO fno;
#if _USE_LFN
fno.lfname = mem_Malloc(_MAX_LFN);
fno.lfsize = _MAX_LFN;
/* read up to 4 directory items */
while (count++ < 4) {
// read up to 2 directory items
while (count < 2) {
#else
// read up to 4 directory items
while (count < 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;
@@ -992,13 +1014,17 @@ static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *li
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
// add the entry to the list
next += ftp_print_eplf_item((list + next), (maxlistsize - next), &fno);
count++;
}
if (result == E_FTP_RESULT_OK) {
ftp_close_files();
}
*listsize = next;
#if _USE_LFN
mem_Free(fno.lfname);
#endif
return result;
}

View File

@@ -1,6 +1,5 @@
#include <stdint.h>
#include <stdbool.h>
#include "std.h"
#include "py/mpconfig.h"
#include MICROPY_HAL_H
@@ -14,9 +13,9 @@
/******************************************************************************
DEFINE PRIVATE CONSTANTS
******************************************************************************/
#define UPDATER_IMG_PATH "/SFLASH/SYS/MCUIMG.BIN"
#define UPDATER_SRVPACK_PATH "/SFLASH/SYS/SRVPCK.UCF"
#define UPDATER_SIGN_PATH "/SFLASH/SYS/SRVPCK.SIG"
#define UPDATER_IMG_PATH "/flash/sys/mcuimg.bin"
#define UPDATER_SRVPACK_PATH "/flash/sys/servicepack.ucf"
#define UPDATER_SIGN_PATH "/flash/sys/servicepack.sig"
/******************************************************************************
DEFINE TYPES
@@ -37,8 +36,6 @@ static updater_data_t updater_data;
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
bool updater_check_path (void *path) {
// conert the path supplied to upper case
stoupper (path);
if (!strcmp(UPDATER_IMG_PATH, path)) {
updater_data.path = IMG_UPDATE;
updater_data.fsize = IMG_SIZE;

View File

@@ -25,7 +25,7 @@
* THE SOFTWARE.
*/
#include <std.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

View File

@@ -27,7 +27,6 @@
#include <stdint.h>
#include <string.h>
#include <std.h>
#include "py/mpstate.h"
#include "mpexception.h"

View File

@@ -37,17 +37,6 @@
#include "pybpin.h"
#include MICROPY_HAL_H
STATIC void pin_named_pins_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
pin_named_pins_obj_t *self = self_in;
print(env, "<Pin.%s>", qstr_str(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);
@@ -58,16 +47,6 @@ pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) {
return NULL;
}
pin_obj_t *pin_find_pin(const mp_obj_dict_t *named_pins, uint pin_num) {
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)->pin_num == pin_num) {
return named_map->table[i].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++) {

View File

@@ -25,7 +25,7 @@
* THE SOFTWARE.
*/
#include <std.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -54,13 +54,11 @@ void mod_network_register_nic(mp_obj_t nic) {
mp_obj_list_append(&MP_STATE_PORT(mod_network_nic_list), nic);
}
mp_obj_t mod_network_find_nic(const uint8_t *ip) {
// find a NIC that is suited to given IP address
mp_obj_t mod_network_find_nic(void) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) {
mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i];
return nic;
}
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
@@ -116,65 +114,3 @@ const mp_obj_module_t mp_module_network = {
.name = MP_QSTR_network,
.globals = (mp_obj_dict_t*)&mp_module_network_globals,
};
/******************************************************************************/
// Miscellaneous helpers
void mod_network_convert_ipv4_endianness(uint8_t *ip) {
uint8_t ip0 = ip[0]; ip[0] = ip[3]; ip[3] = ip0;
uint8_t ip1 = ip[1]; ip[1] = ip[2]; ip[2] = ip1;
}
// Takes an address of the form '192.168.0.1' and converts it to network format
// in out_ip (big endian, so the 192 is the first byte).
void mod_network_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip) {
mp_uint_t addr_len;
const char *addr_str = mp_obj_str_get_data(addr_in, &addr_len);
if (addr_len == 0) {
// special case of no address given
memset(out_ip, 0, MOD_NETWORK_IPV4ADDR_BUF_SIZE);
return;
}
const char *s = addr_str;
const char *s_top = addr_str + addr_len;
for (mp_uint_t i = 0;; i++) {
mp_uint_t val = 0;
for (; s < s_top && *s != '.'; s++) {
val = val * 10 + *s - '0';
}
out_ip[i] = val;
if (i == 3 && s == s_top) {
return;
} else if (i < 3 && s < s_top && *s == '.') {
s++;
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
}
}
// Takes an address of the form ('192.168.0.1', 8080), returns the port and
// puts IP in out_ip (which must take at least IPADDR_BUF_SIZE bytes).
mp_uint_t mod_network_parse_inet_addr(mp_obj_t addr_in, uint8_t *out_ip) {
mp_obj_t *addr_items;
mp_obj_get_array_fixed_n(addr_in, 2, &addr_items);
mod_network_parse_ipv4_addr(addr_items[0], out_ip);
return mp_obj_get_int(addr_items[1]);
}
// Takes an array with a raw IPv4 address and returns something like '192.168.0.1'.
mp_obj_t mod_network_format_ipv4_addr(uint8_t *ip) {
char ip_str[16];
mp_uint_t ip_len = snprintf(ip_str, 16, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
return mp_obj_new_str(ip_str, ip_len, false);
}
// Takes an array with a raw IP address, and a port, and returns a net-address
// tuple such as ('192.168.0.1', 8080).
mp_obj_t mod_network_format_inet_addr(uint8_t *ip, mp_uint_t port) {
mp_obj_t tuple[2] = {
tuple[0] = mod_network_format_ipv4_addr(ip),
tuple[1] = mp_obj_new_int(port),
};
return mp_obj_new_tuple(2, tuple);
}

View File

@@ -25,6 +25,9 @@
* THE SOFTWARE.
*/
#ifndef MODNETWORK_H_
#define MODNETWORK_H_
#define MOD_NETWORK_IPV4ADDR_BUF_SIZE (4)
// Forward declaration
@@ -72,10 +75,6 @@ extern const mod_network_nic_type_t mod_network_nic_type_wlan;
void mod_network_init0(void);
void mod_network_register_nic(mp_obj_t nic);
mp_obj_t mod_network_find_nic(const uint8_t *ip);
mp_obj_t mod_network_find_nic(void);
void mod_network_convert_ipv4_endianness(uint8_t *ip);
void mod_network_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip);
mp_uint_t mod_network_parse_inet_addr(mp_obj_t addr_in, uint8_t *out_ip);
mp_obj_t mod_network_format_ipv4_addr(uint8_t *ip);
mp_obj_t mod_network_format_inet_addr(uint8_t *ip, mp_uint_t port);
#endif // MODNETWORK_H_

View File

@@ -25,9 +25,8 @@
* THE SOFTWARE.
*/
#include <std.h>
#include <stdint.h>
#include "std.h"
#include "py/mpstate.h"
#include "py/runtime.h"
@@ -66,6 +65,7 @@
#include "utils.h"
#include "gccollect.h"
#include "mperror.h"
#include "genhdr/mpversion.h"
#ifdef DEBUG
@@ -233,17 +233,6 @@ STATIC mp_obj_t pyb_repl_uart(uint n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_repl_uart_obj, 0, 1, pyb_repl_uart);
/// \function mkdisk('path')
/// Formats the selected drive, useful when the filesystem has been damaged beyond repair
STATIC mp_obj_t pyb_mkdisk(mp_obj_t path_o) {
const char *path = mp_obj_str_get_str(path_o);
if (FR_OK != f_mkfs(path, 1, 0)) {
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(pyb_mkdisk_obj, pyb_mkdisk);
MP_DECLARE_CONST_FUN_OBJ(pyb_main_obj); // defined in main.c
STATIC const mp_map_elem_t pyb_module_globals_table[] = {
@@ -268,8 +257,6 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ 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 },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&os_sync_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mkdisk), (mp_obj_t)&pyb_mkdisk_obj },
#if MICROPY_HW_ENABLE_RNG
{ MP_OBJ_NEW_QSTR(MP_QSTR_rng), (mp_obj_t)&pyb_rng_get_obj },

View File

@@ -27,19 +27,22 @@
#include <stdint.h>
#include <string.h>
#include "std.h"
#include "py/mpconfig.h"
#include "py/nlr.h"
#include "py/obj.h"
#include "py/objtuple.h"
#include "py/objstr.h"
#include "genhdr/mpversion.h"
#include "ff.h"
#include "diskio.h"
#include "sflash_diskio.h"
#include "file.h"
#include "modutime.h"
#include "random.h"
#include "sd_diskio.h"
#include "mpexception.h"
#include "version.h"
#include "timeutils.h"
/// \module os - basic "operating system" services
///
@@ -48,12 +51,15 @@
/// The filesystem has `/` as the root directory, and the available physical
/// drives are accessible from here. They are currently:
///
/// /SFLASH -- the serial flash filesystem
/// /SD -- the SD card (if it exists)
/// /flash -- the serial flash filesystem
/// /sd -- the SD card (if it exists)
///
/// On boot up, the current directory is `/SFLASH` if no SD card is inserted,
/// otherwise it is `/SD`.
/// On boot up, the current directory is `/flash` if no SD card is inserted,
/// otherwise it is `/sd`.
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
STATIC bool sd_in_root(void) {
#if MICROPY_HW_HAS_SDCARD
return sd_disk_ready();
@@ -62,6 +68,35 @@ STATIC bool sd_in_root(void) {
#endif
}
/******************************************************************************/
// Micro Python bindings
//
STATIC const qstr os_uname_info_fields[] = {
MP_QSTR_sysname, MP_QSTR_nodename,
MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine
};
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM);
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM);
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_release_obj, WIPY_SW_VERSION_NUMBER);
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE);
STATIC const MP_DEFINE_STR_OBJ(os_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
STATIC MP_DEFINE_ATTRTUPLE(
os_uname_info_obj,
os_uname_info_fields,
5,
(mp_obj_t)&os_uname_info_sysname_obj,
(mp_obj_t)&os_uname_info_nodename_obj,
(mp_obj_t)&os_uname_info_release_obj,
(mp_obj_t)&os_uname_info_version_obj,
(mp_obj_t)&os_uname_info_machine_obj
);
STATIC mp_obj_t os_uname(void) {
return (mp_obj_t)&os_uname_info_obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname);
/// \function chdir(path)
/// Change current directory.
STATIC mp_obj_t os_chdir(mp_obj_t path_in) {
@@ -73,10 +108,9 @@ STATIC mp_obj_t os_chdir(mp_obj_t path_in) {
if (res == FR_OK) {
res = f_chdir(path);
}
// TODO: Warn if too many open files...
if (res != FR_OK) {
// TODO should be mp_type_FileNotFoundError
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path));
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
return mp_const_none;
@@ -102,6 +136,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd);
STATIC mp_obj_t os_listdir(mp_uint_t n_args, const mp_obj_t *args) {
bool is_str_type = true;
const char *path;
if (n_args == 1) {
if (mp_obj_get_type(args[0]) == &mp_type_bytes) {
is_str_type = false;
@@ -114,21 +149,25 @@ STATIC mp_obj_t os_listdir(mp_uint_t n_args, const mp_obj_t *args) {
// "hack" to list 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_SFLASH));
mp_obj_list_append(dir_list, MP_OBJ_NEW_QSTR(MP_QSTR_flash));
if (sd_in_root()) {
mp_obj_list_append(dir_list, MP_OBJ_NEW_QSTR(MP_QSTR_SD));
mp_obj_list_append(dir_list, MP_OBJ_NEW_QSTR(MP_QSTR_sd));
}
return dir_list;
}
FRESULT res;
FILINFO fno;
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) {
// TODO should be mp_type_FileNotFoundError
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path));
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
mp_obj_t dir_list = mp_obj_new_list(0, NULL);
@@ -139,7 +178,11 @@ STATIC mp_obj_t os_listdir(mp_uint_t n_args, const mp_obj_t *args) {
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;
@@ -168,44 +211,28 @@ STATIC mp_obj_t os_mkdir(mp_obj_t path_o) {
case FR_OK:
return mp_const_none;
case FR_EXIST:
// TODO should be FileExistsError
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "File exists: '%s'", path));
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
break;
default:
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error creating directory '%s'", path));
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir);
/// \function remove(path)
/// Remove a file.
/// 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);
// TODO check that path is actually a file before trying to unlink it
FRESULT res = f_unlink(path);
switch (res) {
case FR_OK:
return mp_const_none;
default:
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing file '%s'", path));
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove);
/// \function rmdir(path)
/// Remove a directory.
STATIC mp_obj_t os_rmdir(mp_obj_t path_o) {
const char *path = mp_obj_str_get_str(path_o);
// TODO check that path is actually a directory before trying to unlink it
FRESULT res = f_unlink(path);
switch (res) {
case FR_OK:
return mp_const_none;
default:
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing directory '%s'", path));
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_rmdir_obj, os_rmdir);
// Checks for path equality, ignoring trailing slashes:
// path_equal(/, /) -> true
// path_equal(/flash//, /flash) -> true
@@ -225,14 +252,18 @@ STATIC bool path_equal(const char *path, const char *path_canonical) {
/// 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);
stoupper((char *)path);
FILINFO fno;
FRESULT res;
if (path_equal(path, "/") || path_equal(path, "/SFLASH") || path_equal(path, "/SD")) {
FILINFO fno;
#if _USE_LFN
fno.lfname = NULL;
fno.lfsize = 0;
#endif
if (path_equal(path, "/") || path_equal(path, "/flash") || path_equal(path, "/sd")) {
// stat built-in directory
if (path[1] == 'S' && !sd_in_root()) {
// no /SD directory
if (path[1] == 's' && !sd_in_root()) {
// no /sd directory
res = FR_NO_PATH;
goto error;
}
@@ -254,7 +285,7 @@ STATIC mp_obj_t os_stat(mp_obj_t path_in) {
} else {
mode |= 0x8000; // stat.S_IFREG
}
mp_int_t seconds = mod_time_seconds_since_2000(
mp_int_t seconds = timeutils_seconds_since_2000(
1980 + ((fno.fdate >> 9) & 0x7f),
(fno.fdate >> 5) & 0x0f,
fno.fdate & 0x1f,
@@ -282,11 +313,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_stat_obj, os_stat);
/// \function sync()
/// Sync all filesystems.
mp_obj_t os_sync(void) {
STATIC mp_obj_t os_sync(void) {
sflash_disk_flush();
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_0(os_sync_obj, os_sync);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_sync_obj, os_sync);
#if MICROPY_HW_ENABLE_RNG
/// \function urandom(n)
@@ -304,26 +335,37 @@ STATIC mp_obj_t os_urandom(mp_obj_t num) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
#endif
/// \function mkdisk('path')
/// Formats the selected drive, useful when the filesystem has been damaged beyond repair
STATIC mp_obj_t os_mkdisk(mp_obj_t path_o) {
const char *path = mp_obj_str_get_str(path_o);
if (FR_OK != f_mkfs(path, 1, 0)) {
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_mkdisk_obj, os_mkdisk);
STATIC const mp_map_elem_t os_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uos) },
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uos) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_chdir), (mp_obj_t)&os_chdir_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_getcwd), (mp_obj_t)&os_getcwd_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_listdir), (mp_obj_t)&os_listdir_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mkdir), (mp_obj_t)&os_mkdir_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_rmdir_obj },
{ 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_sync), (mp_obj_t)&os_sync_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_uname), (mp_obj_t)&os_uname_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_chdir), (mp_obj_t)&os_chdir_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_getcwd), (mp_obj_t)&os_getcwd_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_listdir), (mp_obj_t)&os_listdir_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mkdir), (mp_obj_t)&os_mkdir_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_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_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
{ MP_OBJ_NEW_QSTR(MP_QSTR_mkdisk), (mp_obj_t)&os_mkdisk_obj },
/// \constant sep - separation character used in paths
{ MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_OBJ_NEW_QSTR(MP_QSTR__slash_) },
#if MICROPY_HW_ENABLE_RNG
{ MP_OBJ_NEW_QSTR(MP_QSTR_urandom), (mp_obj_t)&os_urandom_obj },
#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_OBJ_NEW_QSTR(MP_QSTR__slash_) },
};
STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);

View File

@@ -25,9 +25,8 @@
* THE SOFTWARE.
*/
#ifndef MODUTIME_H_
#define MODUTIME_H_
#ifndef MODUOS_H_
#define MODUOS_H_
MP_DECLARE_CONST_FUN_OBJ(os_sync_obj);
#endif // MODUTIME_H_
#endif // MODUOS_H_

View File

@@ -25,7 +25,6 @@
* THE SOFTWARE.
*/
#include <std.h>
#include <stdint.h>
#include <string.h>
@@ -33,6 +32,7 @@
#include "py/mpstate.h"
#include MICROPY_HAL_H
#include "py/runtime.h"
#include "netutils.h"
#include "modnetwork.h"
#include "mpexception.h"
@@ -41,6 +41,18 @@
STATIC const mp_obj_type_t socket_type;
STATIC void socket_select_nic(mod_network_socket_obj_t *self) {
// select a nic
self->nic = mod_network_find_nic();
self->nic_type = (mod_network_nic_type_t*)mp_obj_get_type(self->nic);
// call the nic to open the socket
int _errno;
if (self->nic_type->socket(self, &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
}
}
// constructor socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None)
STATIC mp_obj_t socket_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 4, false);
@@ -66,22 +78,12 @@ STATIC mp_obj_t socket_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_
}
}
}
socket_select_nic(s);
return s;
}
STATIC void socket_select_nic(mod_network_socket_obj_t *self, const byte *ip) {
if (self->nic == MP_OBJ_NULL) {
// select NIC based on IP
self->nic = mod_network_find_nic(ip);
self->nic_type = (mod_network_nic_type_t*)mp_obj_get_type(self->nic);
// call the NIC to open the socket
int _errno;
if (self->nic_type->socket(self, &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
}
}
}
// method socket.close()
STATIC mp_obj_t socket_close(mp_obj_t self_in) {
mod_network_socket_obj_t *self = self_in;
@@ -98,10 +100,7 @@ STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
// get address
uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
mp_uint_t port = mod_network_parse_inet_addr(addr_in, ip);
// check if we need to select a NIC
socket_select_nic(self, ip);
mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE);
// call the NIC to bind the socket
int _errno;
@@ -157,7 +156,7 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
// make the return value
mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL);
client->items[0] = socket2;
client->items[1] = mod_network_format_inet_addr(ip, port);
client->items[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE);
return client;
}
@@ -169,10 +168,7 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
// get address
uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
mp_uint_t port = mod_network_parse_inet_addr(addr_in, ip);
// check if we need to select a NIC
socket_select_nic(self, ip);
mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE);
// call the NIC to connect the socket
int _errno;
@@ -236,10 +232,7 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_
// get address
uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
mp_uint_t port = mod_network_parse_inet_addr(addr_in, ip);
// check if we need to select a NIC
socket_select_nic(self, ip);
mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE);
// call the NIC to sendto
int _errno;
@@ -276,7 +269,7 @@ STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
vstr.buf[vstr.len] = '\0';
tuple[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
tuple[1] = mod_network_format_inet_addr(ip, port);
tuple[1] = netutils_format_inet_addr(ip, port, NETUTILS_LITTLE);
return mp_obj_new_tuple(2, tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom);
@@ -292,7 +285,7 @@ STATIC mp_obj_t socket_setsockopt(mp_uint_t n_args, const mp_obj_t *args) {
mp_uint_t optlen;
mp_int_t val;
if (mp_obj_is_integer(args[3])) {
val = mp_obj_int_get_truncated(args[3]);
val = mp_obj_get_int_truncated(args[3]);
optval = &val;
optlen = sizeof(val);
} else {
@@ -407,7 +400,7 @@ STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCK_STREAM);
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
tuple->items[4] = mod_network_format_inet_addr(out_ip, port);
tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_LITTLE);
return mp_obj_new_list(1, (mp_obj_t*)&tuple);
}
}
@@ -430,6 +423,7 @@ STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
{ 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) },

View File

@@ -32,7 +32,7 @@
#include MICROPY_HAL_H
#include "py/nlr.h"
#include "py/obj.h"
#include "modutime.h"
#include "timeutils.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
@@ -41,126 +41,11 @@
#include "pybrtc.h"
#include "mpexception.h"
// LEAPOCH corresponds to 2000-03-01, which is a mod-400 year, immediately
// after Feb 29. We calculate seconds as a signed integer relative to that.
//
// Our timebase is relative to 2000-01-01.
#define LEAPOCH ((31 + 29) * 86400)
#define DAYS_PER_400Y (365*400 + 97)
#define DAYS_PER_100Y (365*100 + 24)
#define DAYS_PER_4Y (365*4 + 1)
/// \module time - time related functions
///
/// The `time` module provides functions for getting the current time and date,
/// and for sleeping.
STATIC const uint16_t days_since_jan1[]= { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
STATIC bool is_leap_year(mp_uint_t year) {
return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0;
}
// Month is one based
STATIC mp_uint_t mod_time_days_in_month(mp_uint_t year, mp_uint_t month) {
mp_uint_t mdays = days_since_jan1[month] - days_since_jan1[month - 1];
if (month == 2 && is_leap_year(year)) {
mdays++;
}
return mdays;
}
// compute the day of the year, between 1 and 366
// month should be between 1 and 12, date should start at 1
STATIC mp_uint_t mod_time_year_day(mp_uint_t year, mp_uint_t month, mp_uint_t date) {
mp_uint_t yday = days_since_jan1[month - 1] + date;
if (month >= 3 && is_leap_year(year)) {
yday += 1;
}
return yday;
}
// returns the number of seconds, as an integer, since 2000-01-01
mp_uint_t mod_time_seconds_since_2000(mp_uint_t year, mp_uint_t month, mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second) {
return
second
+ minute * 60
+ hour * 3600
+ (mod_time_year_day(year, month, date) - 1
+ ((year - 2000 + 3) / 4) // add a day each 4 years starting with 2001
- ((year - 2000 + 99) / 100) // subtract a day each 100 years starting with 2001
+ ((year - 2000 + 399) / 400) // add a day each 400 years starting with 2001
) * 86400
+ (year - 2000) * 31536000;
}
void mod_time_seconds_since_2000_to_struct_time(mp_uint_t t, mod_struct_time *tm) {
// The following algorithm was adapted from musl's __secs_to_tm and adapted
// for differences in Micro Python's timebase.
mp_int_t seconds = t - LEAPOCH;
mp_int_t days = seconds / 86400;
seconds %= 86400;
tm->tm_hour = seconds / 3600;
tm->tm_min = seconds / 60 % 60;
tm->tm_sec = seconds % 60;
mp_int_t wday = (days + 2) % 7; // Mar 1, 2000 was a Wednesday (2)
if (wday < 0) {
wday += 7;
}
tm->tm_wday = wday;
mp_int_t qc_cycles = days / DAYS_PER_400Y;
days %= DAYS_PER_400Y;
if (days < 0) {
days += DAYS_PER_400Y;
qc_cycles--;
}
mp_int_t c_cycles = days / DAYS_PER_100Y;
if (c_cycles == 4) {
c_cycles--;
}
days -= (c_cycles * DAYS_PER_100Y);
mp_int_t q_cycles = days / DAYS_PER_4Y;
if (q_cycles == 25) {
q_cycles--;
}
days -= q_cycles * DAYS_PER_4Y;
mp_int_t years = days / 365;
if (years == 4) {
years--;
}
days -= (years * 365);
tm->tm_year = 2000 + years + 4 * q_cycles + 100 * c_cycles + 400 * qc_cycles;
// Note: days_in_month[0] corresponds to March
STATIC const int8_t days_in_month[] = {31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29};
mp_int_t month;
for (month = 0; days_in_month[month] <= days; month++) {
days -= days_in_month[month];
}
tm->tm_mon = month + 2;
if (tm->tm_mon >= 12) {
tm->tm_mon -= 12;
tm->tm_year++;
}
tm->tm_mday = days + 1; // Make one based
tm->tm_mon++; // Make one based
tm->tm_yday = mod_time_year_day(tm->tm_year, tm->tm_mon, tm->tm_mday);
}
/// \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)
@@ -175,14 +60,14 @@ void mod_time_seconds_since_2000_to_struct_time(mp_uint_t t, mod_struct_time *tm
/// yearday is 1-366
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) {
mod_struct_time tm;
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);
mod_time_seconds_since_2000_to_struct_time(seconds, &tm);
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
mp_obj_t tuple[8] = {
mp_obj_new_int(tm.tm_year),
@@ -197,8 +82,8 @@ STATIC mp_obj_t time_localtime(mp_uint_t n_args, const mp_obj_t *args) {
return mp_obj_new_tuple(8, tuple);
} else {
mp_int_t seconds = mp_obj_get_int(args[0]);
mod_struct_time tm;
mod_time_seconds_since_2000_to_struct_time(seconds, &tm);
timeutils_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
mp_obj_t tuple[8] = {
tuple[0] = mp_obj_new_int(tm.tm_year),
tuple[1] = mp_obj_new_int(tm.tm_mon),
@@ -231,64 +116,10 @@ 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));
}
mp_int_t year = mp_obj_get_int(elem[0]);
mp_int_t month = mp_obj_get_int(elem[1]);
mp_int_t mday = mp_obj_get_int(elem[2]);
mp_int_t hours = mp_obj_get_int(elem[3]);
mp_int_t minutes = mp_obj_get_int(elem[4]);
mp_int_t seconds = 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])));
// Normalize the tuple. This allows things like:
//
// tm_tomorrow = list(time.localtime())
// tm_tomorrow[2] += 1 # Adds 1 to mday
// tomorrow = time.mktime(tm_tommorrow)
//
// And not have to worry about all the weird overflows.
//
// You can subtract dates/times this way as well.
minutes += seconds / 60;
if ((seconds = seconds % 60) < 0) {
seconds += 60;
minutes--;
}
hours += minutes / 60;
if ((minutes = minutes % 60) < 0) {
minutes += 60;
hours--;
}
mday += hours / 24;
if ((hours = hours % 24) < 0) {
hours += 24;
mday--;
}
month--; // make month zero based
year += month / 12;
if ((month = month % 12) < 0) {
month += 12;
year--;
}
month++; // back to one based
while (mday < 1) {
if (--month == 0) {
month = 12;
year--;
}
mday += mod_time_days_in_month(year, month);
}
while (mday > mod_time_days_in_month(year, month)) {
mday -= mod_time_days_in_month(year, month);
if (++month == 13) {
month = 1;
year++;
}
}
return mp_obj_new_int_from_uint(mod_time_seconds_since_2000(year, month, mday, hours, minutes, seconds));
}
MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime);

View File

@@ -24,15 +24,17 @@
* THE SOFTWARE.
*/
#include "std.h"
#include <stdint.h>
#include <stdbool.h>
#include "std.h"
#include "simplelink.h"
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/obj.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "netutils.h"
#include "modnetwork.h"
#include "modwlan.h"
#include "pybioctl.h"
@@ -94,6 +96,8 @@ typedef struct _wlan_obj_t {
uint8_t ssid[33];
uint8_t bssid[6];
uint8_t staconnected;
} wlan_obj_t;
/******************************************************************************
@@ -130,21 +134,23 @@ typedef struct _wlan_obj_t {
#define WLAN_MAX_RX_SIZE 16000
#define WLAN_MAX_TX_SIZE 1476
#define MODWLAN_IP_MODE_DYNAMIC 0
#define MODWLAN_IP_MODE_STATIC 1
#define MAKE_SOCKADDR(addr, ip, port) sockaddr addr; \
addr.sa_family = AF_INET; \
addr.sa_data[0] = port >> 8; \
addr.sa_data[1] = port; \
addr.sa_data[2] = ip[0]; \
addr.sa_data[3] = ip[1]; \
addr.sa_data[4] = ip[2]; \
addr.sa_data[5] = ip[3];
addr.sa_data[2] = ip[3]; \
addr.sa_data[3] = ip[2]; \
addr.sa_data[4] = ip[1]; \
addr.sa_data[5] = ip[0];
#define UNPACK_SOCKADDR(addr, ip, port) port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \
ip[0] = addr.sa_data[2]; \
ip[1] = addr.sa_data[3]; \
ip[2] = addr.sa_data[4]; \
ip[3] = addr.sa_data[5];
ip[0] = addr.sa_data[5]; \
ip[1] = addr.sa_data[4]; \
ip[2] = addr.sa_data[3]; \
ip[3] = addr.sa_data[2];
/******************************************************************************
DECLARE PRIVATE DATA
@@ -162,6 +168,7 @@ STATIC wlan_obj_t wlan_obj = {
.ssid = {0},
.bssid = {0},
.mac = {0},
.staconnected = 0
};
STATIC const mp_cb_methods_t wlan_cb_methods;
@@ -176,11 +183,14 @@ OsiLockObj_t wlan_LockObj;
******************************************************************************/
STATIC void wlan_initialize_data (void);
STATIC void wlan_reenable (SlWlanMode_t mode);
STATIC void wlan_servers_start (void);
STATIC void wlan_servers_stop (void);
STATIC void wlan_get_sl_mac (void);
STATIC modwlan_Status_t wlan_do_connect (const char* ssid, uint32_t ssid_len, const char* bssid, uint8_t sec,
const char* key, uint32_t key_len);
STATIC void wlan_lpds_callback_enable (mp_obj_t self_in);
STATIC void wlan_lpds_callback_disable (mp_obj_t self_in);
STATIC bool wlan_scan_result_is_unique (const mp_obj_list_t *nets, _u8 *bssid);
//*****************************************************************************
//
@@ -219,10 +229,12 @@ void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) {
}
break;
case SL_WLAN_STA_CONNECTED_EVENT:
// TODO
wlan_obj.staconnected++;
break;
case SL_WLAN_STA_DISCONNECTED_EVENT:
// TODO
if (wlan_obj.staconnected > 0) {
wlan_obj.staconnected--;
}
break;
case SL_WLAN_P2P_DEV_FOUND_EVENT:
// TODO
@@ -265,9 +277,9 @@ void SimpleLinkNetAppEventHandler(SlNetAppEvent_t *pNetAppEvent) {
pEventData = &pNetAppEvent->EventData.ipAcquiredV4;
// Get ip, gateway and dns
wlan_obj.gateway = ntohl(pEventData->gateway);
wlan_obj.ip = ntohl(pEventData->ip);
wlan_obj.dns = ntohl(pEventData->dns);
wlan_obj.gateway = pEventData->gateway;
wlan_obj.ip = pEventData->ip;
wlan_obj.dns = pEventData->dns;
}
break;
case SL_NETAPP_IPV6_IPACQUIRED_EVENT:
@@ -321,8 +333,6 @@ void SimpleLinkGeneralEventHandler(SlDeviceEvent_t *pDevEvent) {
if (!pDevEvent) {
return;
}
ASSERT (false);
}
@@ -370,16 +380,15 @@ void SimpleLinkSockEventHandler(SlSockEvent_t *pSock) {
// SimpleLink Asynchronous Event Handlers -- End
//*****************************************************************************
void wlan_init0 (void) {
__attribute__ ((section (".boot")))
void wlan_pre_init (void) {
// create the wlan lock
ASSERT(OSI_OK == sl_LockObjCreate(&wlan_LockObj, "WlanLock"));
}
void wlan_first_start (void) {
// clear wlan data after checking any of the status flags
wlan_initialize_data();
if (wlan_obj.mode < 0) {
wlan_initialize_data();
wlan_obj.mode = sl_Start(0, 0, 0);
sl_LockObjUnlock (&wlan_LockObj);
}
@@ -392,14 +401,10 @@ modwlan_Status_t wlan_sl_enable (SlWlanMode_t mode, const char *ssid, uint8_t ss
const char *key, uint8_t key_len, uint8_t channel) {
if (mode == ROLE_STA || mode == ROLE_AP || mode == ROLE_P2P) {
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
// Stop all other processes using the wlan engine
if ((wlan_obj.servers_enabled = servers_are_enabled())) {
servers_stop();
}
#endif
// stop the servers
wlan_servers_stop();
// do a basic start fisrt
// do a basic start
wlan_first_start();
// Device in station-mode. Disconnect previous connection if any
@@ -408,10 +413,8 @@ modwlan_Status_t wlan_sl_enable (SlWlanMode_t mode, const char *ssid, uint8_t ss
// other return-codes
if (0 == sl_WlanDisconnect()) {
while (IS_CONNECTED (wlan_obj.status)) {
#ifndef SL_PLATFORM_MULTI_THREADED
_SlTaskEntry();
#endif
HAL_Delay (5);
wlan_update();
}
}
@@ -454,10 +457,21 @@ modwlan_Status_t wlan_sl_enable (SlWlanMode_t mode, const char *ssid, uint8_t ss
ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID, WLAN_GENERAL_PARAM_OPT_COUNTRY_CODE, 2, country));
ASSERT_ON_ERROR(sl_WlanSet(SL_WLAN_CFG_AP_ID, WLAN_AP_OPT_CHANNEL, 1, (_u8 *)&channel));
// Stop and start again
// stop and start again
wlan_reenable(mode);
ASSERT (wlan_obj.mode == mode);
SlNetCfgIpV4Args_t ipV4;
ipV4.ipV4 = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 IP address
ipV4.ipV4Mask = (_u32)SL_IPV4_VAL(255,255,255,0); // _u32 Subnet mask for this AP
ipV4.ipV4Gateway = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 Default gateway address
ipV4.ipV4DnsServer = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 DNS server address
ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_AP_P2P_GO_STATIC_ENABLE, IPCONFIG_MODE_ENABLE_IPV4,
sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4));
// stop and start again
wlan_reenable(mode);
SlNetAppDhcpServerBasicOpt_t dhcpParams;
dhcpParams.lease_time = 4096; // lease time (in seconds) of the IP Address
dhcpParams.ipv4_addr_start = SL_IPV4_VAL(192,168,1,2); // first IP Address for allocation.
@@ -467,16 +481,9 @@ modwlan_Status_t wlan_sl_enable (SlWlanMode_t mode, const char *ssid, uint8_t ss
sizeof(SlNetAppDhcpServerBasicOpt_t), (_u8* )&dhcpParams)); // set parameters
ASSERT_ON_ERROR(sl_NetAppStart(SL_NET_APP_DHCP_SERVER_ID)); // Start DHCP server with new settings
SlNetCfgIpV4Args_t ipV4;
ipV4.ipV4 = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 IP address
ipV4.ipV4Mask = (_u32)SL_IPV4_VAL(255,255,255,0); // _u32 Subnet mask for this AP
ipV4.ipV4Gateway = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 Default gateway address
ipV4.ipV4DnsServer = (_u32)SL_IPV4_VAL(192,168,1,1); // _u32 DNS server address
ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_AP_P2P_GO_STATIC_ENABLE, IPCONFIG_MODE_ENABLE_IPV4,
sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4));
// Stop and start again
// stop and start again
wlan_reenable(mode);
// save the security type
wlan_obj.security = sec;
}
@@ -487,15 +494,11 @@ modwlan_Status_t wlan_sl_enable (SlWlanMode_t mode, const char *ssid, uint8_t ss
ASSERT_ON_ERROR(sl_WlanSetMode(mode));
// stop and start again
wlan_reenable(mode);
// set connection policy to Auto + SmartConfig (Device's default connection policy)
ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_CONNECTION, SL_CONNECTION_POLICY(1, 0, 0, 0, 1), NULL, 0));
// set connection policy to Auto + Fast (tries to connect to the last connected AP)
ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_CONNECTION,SL_CONNECTION_POLICY(1, 1, 0, 0, 0), NULL, 0));
}
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
// Start the servers again
if (wlan_obj.servers_enabled) {
servers_start();
}
#endif
// start the servers before returning
wlan_servers_start();
return MODWLAN_OK;
}
return MODWLAN_ERROR_INVALID_PARAMS;
@@ -508,12 +511,7 @@ void wlan_update(void) {
}
void wlan_stop (uint32_t timeout) {
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
// Stop all other processes using the wlan engine
if ((wlan_obj.servers_enabled = servers_are_enabled())) {
servers_stop();
}
#endif
wlan_servers_stop();
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
sl_Stop(timeout);
wlan_obj.mode = -1;
@@ -522,12 +520,7 @@ void wlan_stop (uint32_t timeout) {
void wlan_start (void) {
wlan_obj.mode = sl_Start(0, 0, 0);
sl_LockObjUnlock (&wlan_LockObj);
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
// start the servers if they were enabled before
if (wlan_obj.servers_enabled) {
servers_start();
}
#endif
wlan_servers_start();
}
void wlan_get_mac (uint8_t *macAddress) {
@@ -552,6 +545,7 @@ STATIC void wlan_initialize_data (void) {
wlan_obj.gateway = 0;
wlan_obj.ip = 0;
wlan_obj.security = SL_SEC_TYPE_OPEN;
wlan_obj.staconnected = 0;
memset(wlan_obj.ssid, 0, sizeof(wlan_obj.ssid));
memset(wlan_obj.bssid, 0, sizeof(wlan_obj.bssid));
}
@@ -560,11 +554,30 @@ STATIC void wlan_reenable (SlWlanMode_t mode) {
// stop and start again
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
sl_Stop(SL_STOP_TIMEOUT);
wlan_initialize_data();
wlan_obj.mode = sl_Start(0, 0, 0);
sl_LockObjUnlock (&wlan_LockObj);
ASSERT (wlan_obj.mode == mode);
}
STATIC void wlan_servers_start (void) {
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
// start the servers if they were enabled before
if (wlan_obj.servers_enabled) {
servers_start();
}
#endif
}
STATIC void wlan_servers_stop (void) {
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
// Stop all other processes using the wlan engine
if ((wlan_obj.servers_enabled = servers_are_enabled())) {
servers_stop();
}
#endif
}
STATIC modwlan_Status_t wlan_do_connect (const char* ssid, uint32_t ssid_len, const char* bssid, uint8_t sec,
const char* key, uint32_t key_len) {
SlSecParams_t secParams;
@@ -576,10 +589,8 @@ STATIC modwlan_Status_t wlan_do_connect (const char* ssid, uint32_t ssid_len, co
// Wait for the WLAN Event
uint32_t waitForConnectionMs = 0;
while (!IS_CONNECTED(wlan_obj.status)) {
#ifndef SL_PLATFORM_MULTI_THREADED
_SlTaskEntry();
#endif
HAL_Delay (5);
wlan_update();
if (++waitForConnectionMs >= MODWLAN_TIMEOUT_MS) {
return MODWLAN_ERROR_TIMEOUT;
}
@@ -648,6 +659,17 @@ STATIC void wlan_lpds_callback_disable (mp_obj_t self_in) {
pybsleep_set_wlan_lpds_callback (NULL);
}
STATIC bool wlan_scan_result_is_unique (const mp_obj_list_t *nets, _u8 *bssid) {
for (int i = 0; i < nets->len; i++) {
// index 1 in the list is the bssid
mp_obj_str_t *_bssid = (mp_obj_str_t *)((mp_obj_tuple_t *)nets->items[i])->items[1];
if (!memcmp (_bssid->data, bssid, SL_BSSID_LENGTH)) {
return false;
}
}
return true;
}
/******************************************************************************/
// Micro Python bindings; WLAN class
@@ -689,19 +711,19 @@ STATIC mp_obj_t wlan_make_new (mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
return &wlan_obj;
}
STATIC void wlan_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
STATIC void wlan_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
wlan_obj_t *self = self_in;
print(env, "<WLAN, mode=%u", self->mode);
mp_printf(print, "<WLAN, mode=%u", self->mode);
// only print the bssid if in station mode
if (self->mode != ROLE_AP && GET_STATUS_BIT(self->status, STATUS_BIT_CONNECTION)) {
print(env, ", connected to: ssid=%s, bssid=%02x:%02x:%02x:%02x:%02x:%02x", self->ssid,
mp_printf(print, ", connected to: ssid=%s, bssid=%02x:%02x:%02x:%02x:%02x:%02x", self->ssid,
self->bssid[0], self->bssid[1], self->bssid[2], self->bssid[3], self->bssid[4], self->bssid[5]);
}
else {
print(env, ", ssid=%s", self->ssid);
mp_printf(print, ", ssid=%s", self->ssid);
}
print(env, ", security=%u>", self->security);
mp_printf(print, ", security=%u>", self->security);
}
/// \method connect(ssid, security=OPEN, key=None, bssid=None)
@@ -756,10 +778,8 @@ STATIC mp_obj_t wlan_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
if (GET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION)) {
if (0 == sl_WlanDisconnect()) {
while (IS_CONNECTED(wlan_obj.status)) {
#ifndef SL_PLATFORM_MULTI_THREADED
_SlTaskEntry();
#endif
HAL_Delay (5);
wlan_update();
}
}
}
@@ -788,10 +808,11 @@ STATIC mp_obj_t wlan_disconnect(mp_obj_t self_in) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_disconnect_obj, wlan_disconnect);
/// \method is_connected()
/// Return true if connected to the AP and an IP address has been assigned. False otherwise.
/// Return true if connected to the AP and an IP address has been assigned. Also true if there's any station connected.
/// false otherwise.
STATIC mp_obj_t wlan_isconnected(mp_obj_t self_in) {
if (GET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION) &&
GET_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED)) {
if ((GET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION) &&
GET_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED)) || (wlan_obj.staconnected > 0)) {
return mp_const_true;
}
return mp_const_false;
@@ -799,37 +820,29 @@ STATIC mp_obj_t wlan_isconnected(mp_obj_t self_in) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_isconnected_obj, wlan_isconnected);
STATIC mp_obj_t wlan_ifconfig (mp_obj_t self_in) {
STATIC const qstr wlan_ifconfig_fields[] = {
MP_QSTR_mode, MP_QSTR_ssid,
MP_QSTR_mac, MP_QSTR_bssid,
MP_QSTR_ip, MP_QSTR_subnet,
MP_QSTR_gateway, MP_QSTR_dns
};
unsigned char len = sizeof(SlNetCfgIpV4Args_t);
unsigned char dhcpIsOn;
SlNetCfgIpV4Args_t ipV4;
sl_NetCfgGet(SL_IPV4_STA_P2P_CL_GET_INFO, &dhcpIsOn, &len, (uint8_t *)&ipV4);
// shift byte order
ipV4.ipV4Mask = ntohl(ipV4.ipV4Mask);
mp_obj_t ifconfig = mp_obj_new_dict(0);
mp_obj_dict_store (ifconfig, mp_obj_new_str("ip", strlen("ip"), false), mod_network_format_ipv4_addr((uint8_t *)&wlan_obj.ip));
mp_obj_dict_store (ifconfig, mp_obj_new_str("subnet", strlen("subnet"), false), mod_network_format_ipv4_addr((uint8_t *)&ipV4.ipV4Mask));
mp_obj_dict_store (ifconfig, mp_obj_new_str("gateway", strlen("gateway"), false), mod_network_format_ipv4_addr((uint8_t *)&wlan_obj.gateway));
mp_obj_dict_store (ifconfig, mp_obj_new_str("dns", strlen("dns"), false), mod_network_format_ipv4_addr((uint8_t *)&wlan_obj.dns));
char mac_str[18];
mp_uint_t mac_len = snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x", wlan_obj.mac[0], wlan_obj.mac[1], wlan_obj.mac[2],
wlan_obj.mac[3], wlan_obj.mac[4], wlan_obj.mac[5]);
mp_obj_dict_store (ifconfig, mp_obj_new_str("mac", strlen("mac"), false), mp_obj_new_str(mac_str, mac_len, false));
char *mode_str;
if (wlan_obj.mode == ROLE_STA) {
mode_str = "station";
}
else if (wlan_obj.mode == ROLE_AP) {
mode_str = "ap";
}
else {
mode_str = "p2p";
}
mp_obj_dict_store (ifconfig, mp_obj_new_str("mode", strlen("mode"), false), mp_obj_new_str(mode_str, strlen(mode_str), false));
mp_obj_dict_store (ifconfig, mp_obj_new_str("ssid", strlen("ssid"), false), mp_obj_new_str((const char *)wlan_obj.ssid, strlen((const char *)wlan_obj.ssid), false));
mp_obj_t ifconfig[8];
ifconfig[0] = mp_obj_new_int(wlan_obj.mode);
ifconfig[1] = mp_obj_new_str((const char *)wlan_obj.ssid, strlen((const char *)wlan_obj.ssid), false);
ifconfig[2] = mp_obj_new_bytes((const byte *)wlan_obj.bssid, SL_BSSID_LENGTH);
ifconfig[3] = mp_obj_new_bytes((const byte *)wlan_obj.mac, SL_BSSID_LENGTH);
ifconfig[4] = netutils_format_ipv4_addr((uint8_t *)&wlan_obj.ip, NETUTILS_LITTLE);
ifconfig[5] = netutils_format_ipv4_addr((uint8_t *)&ipV4.ipV4Mask, NETUTILS_LITTLE);
ifconfig[6] = netutils_format_ipv4_addr((uint8_t *)&wlan_obj.gateway, NETUTILS_LITTLE);
ifconfig[7] = netutils_format_ipv4_addr((uint8_t *)&wlan_obj.dns, NETUTILS_LITTLE);
return ifconfig;
return mp_obj_new_attrtuple(wlan_ifconfig_fields, 8, ifconfig);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(wlan_ifconfig_obj, wlan_ifconfig);
@@ -867,38 +880,49 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_urn_obj, 1, 2, wlan_urn);
/// \method wlan_netlist()
/// Return a list of tuples with all the acces points within range
STATIC mp_obj_t wlan_scan(mp_obj_t self_in) {
STATIC const qstr wlan_scan_info_fields[] = {
MP_QSTR_ssid, MP_QSTR_bssid,
MP_QSTR_security, MP_QSTR_channel, MP_QSTR_rssi
};
Sl_WlanNetworkEntry_t wlanEntry;
uint8_t _index = 0;
mp_obj_t nets = NULL;
// trigger a new newtork scanning
// trigger a new network scan
uint32_t scanSeconds = MODWLAN_SCAN_PERIOD_S;
ASSERT_ON_ERROR(sl_WlanPolicySet(SL_POLICY_SCAN , MODWLAN_SL_SCAN_ENABLE, (_u8 *)&scanSeconds, sizeof(scanSeconds)));
// wait for the scan to be completed
// wait for the scan to complete
HAL_Delay (MODWLAN_WAIT_FOR_SCAN_MS);
do {
if (sl_WlanGetNetworkList(_index++, 1, &wlanEntry) <= 0) {
break;
}
mp_obj_t tuple[4];
if (_index == 1) {
// initialize the list
nets = mp_obj_new_list(0, NULL);
}
// we must skip any duplicated results
else if (!wlan_scan_result_is_unique(nets, wlanEntry.bssid)) {
continue;
}
mp_obj_t tuple[5];
tuple[0] = mp_obj_new_str((const char *)wlanEntry.ssid, wlanEntry.ssid_len, false);
tuple[1] = mp_obj_new_str((const char *)wlanEntry.bssid, SL_BSSID_LENGTH, false);
// 'Normalize' the security type
tuple[1] = mp_obj_new_bytes((const byte *)wlanEntry.bssid, SL_BSSID_LENGTH);
// 'normalize' the security type
if (wlanEntry.sec_type > 2) {
wlanEntry.sec_type = 2;
}
tuple[2] = mp_obj_new_int(wlanEntry.sec_type);
tuple[3] = mp_obj_new_int(wlanEntry.rssi);
tuple[3] = mp_const_none;
tuple[4] = mp_obj_new_int(wlanEntry.rssi);
if (_index == 1) {
// Initialize the set
nets = mp_obj_new_set(0, NULL);
}
// Add the network found to the list if it's unique
mp_obj_set_store(nets, mp_obj_new_tuple(4, tuple));
// add the network to the list
mp_obj_list_append(nets, mp_obj_new_attrtuple(wlan_scan_info_fields, 5, tuple));
} while (_index < MODWLAN_SL_MAX_NETWORKS);
@@ -933,6 +957,76 @@ STATIC mp_obj_t wlan_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_callback_obj, 1, wlan_callback);
/// \method config_ip(mode, *, ip='192.168.1.1', subnet='255.255.255.0', gateway='192.168.1.1', dns='8.8.8.8')
STATIC mp_obj_t wlan_config_ip (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC const mp_arg_t allowed_args[] = {
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = MODWLAN_IP_MODE_DYNAMIC} },
{ MP_QSTR_ip, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_subnet, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_gateway, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_dns, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
if (args[0].u_int == MODWLAN_IP_MODE_DYNAMIC) {
// only mode must be given
if (args[1].u_obj || args[2].u_obj || args[3].u_obj || args[4].u_obj) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, mpexception_num_type_invalid_arguments));
}
wlan_servers_stop();
// nothing to do if we are an access point
if (wlan_obj.mode != ROLE_AP) {
_u8 val = 1;
sl_NetCfgSet(SL_IPV4_STA_P2P_CL_DHCP_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, 1, &val);
wlan_reenable (wlan_obj.mode);
}
}
else {
// we need all arguments at this point
if (!args[1].u_obj || !args[2].u_obj || !args[3].u_obj || !args[4].u_obj) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, mpexception_num_type_invalid_arguments));
}
SlNetCfgIpV4Args_t ipV4;
netutils_parse_ipv4_addr(args[1].u_obj, (uint8_t *)&ipV4.ipV4, NETUTILS_LITTLE);
netutils_parse_ipv4_addr(args[2].u_obj, (uint8_t *)&ipV4.ipV4Mask, NETUTILS_LITTLE);
netutils_parse_ipv4_addr(args[3].u_obj, (uint8_t *)&ipV4.ipV4Gateway, NETUTILS_LITTLE);
netutils_parse_ipv4_addr(args[4].u_obj, (uint8_t *)&ipV4.ipV4DnsServer, NETUTILS_LITTLE);
wlan_servers_stop();
if (wlan_obj.mode == ROLE_AP) {
ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_AP_P2P_GO_STATIC_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4));
// stop and start again
wlan_reenable(wlan_obj.mode);
SlNetAppDhcpServerBasicOpt_t dhcpParams;
dhcpParams.lease_time = 4096; // lease time (in seconds) of the IP Address
dhcpParams.ipv4_addr_start = ipV4.ipV4 + 1; // first IP Address for allocation.
dhcpParams.ipv4_addr_last = (ipV4.ipV4 & 0xFFFFFF00) + 254; // last IP Address for allocation.
ASSERT_ON_ERROR(sl_NetAppStop(SL_NET_APP_DHCP_SERVER_ID)); // stop DHCP server before settings
ASSERT_ON_ERROR(sl_NetAppSet(SL_NET_APP_DHCP_SERVER_ID, NETAPP_SET_DHCP_SRV_BASIC_OPT,
sizeof(SlNetAppDhcpServerBasicOpt_t), (_u8* )&dhcpParams)); // set parameters
ASSERT_ON_ERROR(sl_NetAppStart(SL_NET_APP_DHCP_SERVER_ID)); // start DHCP server with new settings
}
else {
ASSERT_ON_ERROR(sl_NetCfgSet(SL_IPV4_STA_P2P_CL_STATIC_ENABLE, IPCONFIG_MODE_ENABLE_IPV4, sizeof(SlNetCfgIpV4Args_t), (_u8 *)&ipV4));
}
wlan_reenable (wlan_obj.mode);
}
wlan_servers_start();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_config_ip_obj, 1, wlan_config_ip);
STATIC const mp_map_elem_t wlan_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&wlan_connect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&wlan_scan_obj },
@@ -941,6 +1035,7 @@ STATIC const mp_map_elem_t wlan_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_ifconfig), (mp_obj_t)&wlan_ifconfig_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_urn), (mp_obj_t)&wlan_urn_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&wlan_callback_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_config_ip), (mp_obj_t)&wlan_config_ip_obj },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_OPEN), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_OPEN) },
@@ -952,6 +1047,8 @@ STATIC const mp_map_elem_t wlan_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_STA), MP_OBJ_NEW_SMALL_INT(ROLE_STA) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_AP), MP_OBJ_NEW_SMALL_INT(ROLE_AP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_P2P), MP_OBJ_NEW_SMALL_INT(ROLE_P2P) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_DYNAMIC), MP_OBJ_NEW_SMALL_INT(MODWLAN_IP_MODE_DYNAMIC) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_STATIC), MP_OBJ_NEW_SMALL_INT(MODWLAN_IP_MODE_STATIC) },
};
STATIC MP_DEFINE_CONST_DICT(wlan_locals_dict, wlan_locals_dict_table);
@@ -968,10 +1065,10 @@ STATIC int wlan_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uin
uint32_t ip;
int result = sl_NetAppDnsGetHostByName((_i8 *)name, (_u16)len, (_u32*)&ip, (_u8)family);
out_ip[0] = ip >> 24;
out_ip[1] = ip >> 16;
out_ip[2] = ip >> 8;
out_ip[3] = ip;
out_ip[0] = ip;
out_ip[1] = ip >> 8;
out_ip[2] = ip >> 16;
out_ip[3] = ip >> 24;
return result;
}

View File

@@ -53,10 +53,11 @@ extern _SlLockObj_t wlan_LockObj;
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
******************************************************************************/
extern void wlan_init0 (void);
extern void wlan_pre_init (void);
extern modwlan_Status_t wlan_sl_enable (SlWlanMode_t mode, const char *ssid, uint8_t ssid_len, uint8_t sec,
const char *key, uint8_t key_len, uint8_t channel);
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);

View File

@@ -100,9 +100,9 @@ STATIC pyb_adc_obj_t pyb_adc_obj[PYB_ADC_NUM_CHANNELS];
/******************************************************************************/
/* Micro Python bindings : adc object */
STATIC void adc_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
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;
print(env, "<ADC, channel=%u>", self->num);
mp_printf(print, "<ADC, channel=%u>", self->num);
}
/// \classmethod \constructor(channel)

View File

@@ -294,13 +294,13 @@ STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n
return (mp_obj_t)self;
}
STATIC void pyb_i2c_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
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) {
print(env, "<I2C0, I2C.MASTER, baudrate=%u>)", self->baudrate);
mp_printf(print, "<I2C0, I2C.MASTER, baudrate=%u>)", self->baudrate);
}
else {
print(env, "<I2C0>");
mp_print_str(print, "<I2C0>");
}
}

View File

@@ -61,29 +61,7 @@
///
/// Usage Model:
///
/// All CPU Pins are predefined as pyb.Pin.cpu.Name
///
/// GPIO9_pin = pyb.Pin.cpu.GPIO9
///
/// g = pyb.Pin(pyb.Pin.cpu.GPIO9, 0, pyb.Pin.IN)
///
/// CPU pins which correspond to the board pins are available
/// as `pyb.cpu.Name`.
///
/// You can also use strings:
///
/// g = pyb.Pin('GPIO9', 0)
///
/// And finally, you can also pass a pin number directly:
///
/// g = pyb.Pin(64, 0)
///
/// To summarise, the following order determines how things get mapped into
/// an ordinal pin number:
///
/// 1. Directly specify a Pin object
/// 2. Supply a string which matches a CPU pin name
/// 3. Provide a pin number
/// g = pyb.Pin('GPIO9', af=0, mode=pyb.Pin.IN, type=pyb.Pin.STD, strength=pyb.Pin.S2MA)
///
/// \Interrupts:
//// You can also configure the Pin to generate interrupts
@@ -91,7 +69,7 @@
/// Example callback:
///
/// def pincb(pin):
/// print(pin.pin())
/// print(pin.get_config().name)
///
/// extint = pyb.Pin('GPIO10', 0, pyb.Pin.INT_RISING, pyb.GPIO.STD_PD, pyb.S2MA)
/// extint.callback (intmode=pyb.Pin.INT_RISING, handler=pincb)
@@ -166,28 +144,18 @@ void pin_init0(void) {
pin_obj_t *pin_find(mp_obj_t user_obj) {
pin_obj_t *pin_obj;
// If a pin was provided, then use it
// if a pin was provided, use it
if (MP_OBJ_IS_TYPE(user_obj, &pin_type)) {
pin_obj = user_obj;
return pin_obj;
}
// See if the pin name matches a cpu pin
// otherwise see if the pin name matches a cpu pin
pin_obj = pin_find_named_pin(&pin_cpu_pins_locals_dict, user_obj);
if (pin_obj) {
return pin_obj;
}
// See if the pin number matches a cpu pin
mp_int_t pin_num;
if (mp_obj_get_int_maybe(user_obj, &pin_num)) {
// The Pins dictionary has pin indexes, so we must substract one from the value passed
pin_obj = pin_find_pin(&pin_cpu_pins_locals_dict, (pin_num - 1));
if (pin_obj) {
return pin_obj;
}
}
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
@@ -387,7 +355,7 @@ STATIC const mp_arg_t pin_init_args[] = {
{ MP_QSTR_af, MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_mode, MP_ARG_INT, {.u_int = GPIO_DIR_MODE_OUT} },
{ MP_QSTR_type, MP_ARG_INT, {.u_int = PIN_TYPE_STD} },
{ MP_QSTR_str, MP_ARG_INT, {.u_int = PIN_STRENGTH_4MA} },
{ MP_QSTR_strength, MP_ARG_INT, {.u_int = PIN_STRENGTH_4MA} },
};
#define pin_INIT_NUM_ARGS MP_ARRAY_SIZE(pin_init_args)
@@ -429,25 +397,26 @@ STATIC mp_obj_t pin_obj_init_helper(pin_obj_t *self, mp_uint_t n_args, const mp_
/// \method print()
/// Return a string describing the pin object.
STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pin_obj_t *self = self_in;
uint32_t af = MAP_PinModeGet(self->pin_num);
uint32_t type = pin_get_type(self);
uint32_t strength = pin_get_strenght(self);
uint32_t af = self->af;
uint32_t type = self->type;
uint32_t strength = self->strength;
// pin name
print(env, "<Pin.cpu.%s, af=%u", qstr_str(self->name), af);
mp_printf(print, "<Pin.cpu.%q, af=%u", self->name, af);
// pin mode
if (af == PIN_MODE_0) {
// IO mode
qstr mode_qst;
uint32_t mode = pin_get_mode(self);
uint32_t mode = self->mode;
if (mode == GPIO_DIR_MODE_IN) {
mode_qst = MP_QSTR_IN;
} else {
mode_qst = MP_QSTR_OUT;
}
print(env, ", mode=Pin.%s", qstr_str(mode_qst)); // safe because mode_qst has no formatting chars
mp_printf(print, ", mode=Pin.%q", mode_qst);
}
// pin type
@@ -465,9 +434,9 @@ STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env,
} else {
type_qst = MP_QSTR_OD_PD;
}
print(env, ", pull=Pin.%s", qstr_str(type_qst));
mp_printf(print, ", type=Pin.%q", type_qst);
// Strength
// pin strength
qstr str_qst;
if (strength == PIN_STRENGTH_2MA) {
str_qst = MP_QSTR_S2MA;
@@ -476,7 +445,7 @@ STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env,
} else {
str_qst = MP_QSTR_S6MA;
}
print(env, ", strength=Pin.%s>", qstr_str(str_qst));
mp_printf(print, ", strength=Pin.%q>", str_qst);
}
/// \classmethod \constructor(id, ...)
@@ -554,65 +523,25 @@ STATIC mp_obj_t pin_toggle(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_toggle_obj, pin_toggle);
/// \method name()
/// Get the pin name.
STATIC mp_obj_t pin_name(mp_obj_t self_in) {
/// \method get_config()
/// Returns a named tupple with the current configuration of the gpio pin
STATIC mp_obj_t pin_get_config(mp_obj_t self_in) {
STATIC const qstr pin_config_fields[] = {
MP_QSTR_name, MP_QSTR_af, MP_QSTR_mode,
MP_QSTR_type, MP_QSTR_strength
};
pin_obj_t *self = self_in;
return MP_OBJ_NEW_QSTR(self->name);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_name_obj, pin_name);
mp_obj_t pin_config[5];
pin_config[0] = MP_OBJ_NEW_QSTR(self->name);
pin_config[1] = mp_obj_new_int(self->af);
pin_config[2] = mp_obj_new_int(self->mode);
pin_config[3] = mp_obj_new_int(self->type);
pin_config[4] = mp_obj_new_int(self->strength);
/// \method port()
/// Get the pin port.
STATIC mp_obj_t pin_port(mp_obj_t self_in) {
pin_obj_t *self = self_in;
return mp_obj_new_int(self->port);
return mp_obj_new_attrtuple(pin_config_fields, 5, pin_config);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_port_obj, pin_port);
/// \method pin()
/// Get the pin number.
STATIC mp_obj_t pin_pin(mp_obj_t self_in) {
pin_obj_t *self = self_in;
return MP_OBJ_NEW_SMALL_INT(self->pin_num);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_pin_obj, pin_pin);
/// \method mode()
/// Returns the currently configured mode of the gpio pin. The integer returned
/// will match one of the allowed constants for the mode argument to the init
/// function.
STATIC mp_obj_t pin_mode(mp_obj_t self_in) {
return MP_OBJ_NEW_SMALL_INT(pin_get_mode(self_in));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_mode_obj, pin_mode);
/// \method type()
/// Returns the currently configured type of the pin. The integer returned
/// will match one of the allowed constants for the type argument to the init
/// function.
STATIC mp_obj_t pin_type_get(mp_obj_t self_in) {
return MP_OBJ_NEW_SMALL_INT(pin_get_type(self_in));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_type_obj, pin_type_get);
/// \method strength()
/// Returns the currently configured drive strength of the pin. The integer returned
/// will match one of the allowed constants for the strength argument to the init
/// function.
STATIC mp_obj_t pin_strength(mp_obj_t self_in) {
return MP_OBJ_NEW_SMALL_INT(pin_get_strenght(self_in));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_strenght_obj, pin_strength);
/// \method af()
/// Returns the currently configured alternate function of the gpio pin. The integer returned
/// will match one of the allowed constants for the af argument to the init function.
STATIC mp_obj_t pin_af(mp_obj_t self_in) {
pin_obj_t *self = self_in;
return MP_OBJ_NEW_SMALL_INT(MAP_PinModeGet(self->pin_num));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_obj, pin_af);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_get_config_obj, pin_get_config);
/// \method callback(method, intmode, priority, pwrmode)
/// Creates a callback object associated to a pin
@@ -750,18 +679,9 @@ STATIC const mp_map_elem_t pin_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&pin_low_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&pin_high_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_toggle), (mp_obj_t)&pin_toggle_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&pin_name_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_port), (mp_obj_t)&pin_port_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pin), (mp_obj_t)&pin_pin_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mode), (mp_obj_t)&pin_mode_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_type), (mp_obj_t)&pin_type_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_strength), (mp_obj_t)&pin_strenght_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_af), (mp_obj_t)&pin_af_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_config), (mp_obj_t)&pin_get_config_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pin_callback_obj },
// class attributes
{ MP_OBJ_NEW_QSTR(MP_QSTR_cpu), (mp_obj_t)&pin_cpu_pins_obj_type },
// class constants
/// \constant IN - set the pin to input mode
/// \constant OUT - set the pin to output mode

View File

@@ -25,13 +25,18 @@
* THE SOFTWARE.
*/
// This file requires pin_defs_xxx.h (which has port specific enums and
// defines, so we include it here. It should never be included directly
#include MICROPY_PIN_DEFS_PORT_H
#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
};
typedef struct {
const mp_obj_base_t base;
const qstr name;
@@ -67,9 +72,9 @@ void pin_config(pin_obj_t *self, uint af, uint mode, uint type, uint strength);
void pin_extint_register(pin_obj_t *self, uint32_t intmode, uint32_t priority);
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(const mp_obj_dict_t *named_pins, uint pin_num);
pin_obj_t *pin_find_pin_by_port_bit (const mp_obj_dict_t *named_pins, uint port, uint bit);
uint32_t pin_get_mode(const pin_obj_t *self);
uint32_t pin_get_type(const pin_obj_t *self);
uint32_t pin_get_strenght(const pin_obj_t *self);
#endif // PYBPIN_H_

View File

@@ -31,7 +31,6 @@
#include MICROPY_HAL_H
#include "py/obj.h"
#include "py/runtime.h"
#include "modutime.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
@@ -40,6 +39,7 @@
#include "pybrtc.h"
#include "pybsleep.h"
#include "mpcallback.h"
#include "timeutils.h"
/// \moduleref pyb
/// \class RTC - real time clock
@@ -82,7 +82,7 @@ void pybrtc_init(void) {
// fresh reset; configure the RTC Calendar
// set the date to 1st Jan 2015
// set the time to 00:00:00
uint32_t seconds = mod_time_seconds_since_2000(2015, 1, 1, 0, 0, 0);
uint32_t seconds = timeutils_seconds_since_2000(2015, 1, 1, 0, 0, 0);
// Mark the RTC in use first
MAP_PRCMRTCInUseSet();
@@ -111,11 +111,13 @@ STATIC void pyb_rtc_callback_enable (mp_obj_t self_in) {
STATIC void pyb_rtc_callback_disable (mp_obj_t self_in) {
// check the wake from param
if (pybrtc_data.prwmode & PYB_PWR_MODE_ACTIVE) {
// enable the slow clock interrupt
// disable the slow clock interrupt
MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
}
// 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();
}
/******************************************************************************/
@@ -135,7 +137,7 @@ STATIC void pyb_rtc_callback_disable (mp_obj_t self_in) {
/// `weekday` is 0-6 for Monday through Sunday.
///
mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
mod_struct_time tm;
timeutils_struct_time_t tm;
uint32_t seconds;
uint16_t mseconds;
@@ -143,7 +145,7 @@ mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
// get the seconds and the milliseconds from the RTC
MAP_PRCMRTCGet(&seconds, &mseconds);
mseconds = RTC_CYCLES_U16MS(mseconds);
mod_time_seconds_since_2000_to_struct_time(seconds, &tm);
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
mp_obj_t tuple[8] = {
mp_obj_new_int(tm.tm_year),
@@ -170,7 +172,7 @@ mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
tm.tm_sec = mp_obj_get_int(items[6]);
mseconds = mp_obj_get_int(items[7]);
seconds = mod_time_seconds_since_2000(tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
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);
@@ -217,7 +219,7 @@ STATIC mp_obj_t pyb_rtc_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp
// set the lpds callback
pybsleep_set_timer_lpds_callback(_callback);
// the interrupt priority is ignored since is already set to to highest level by the sleep module
// 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)

View File

@@ -73,7 +73,7 @@ STATIC mp_obj_t pybsd_disable (mp_obj_t self_in);
STATIC mp_obj_t pybsd_enable (mp_obj_t self_in);
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
__attribute__ ((section (".boot")))
void pybsd_init0 (void) {
@@ -86,7 +86,7 @@ void pybsd_deinit (void) {
}
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
/// Initalizes the sd card driver
STATIC void pybsd_init (pybsd_obj_t *self) {
@@ -148,13 +148,13 @@ STATIC mp_obj_t pybsd_enable (mp_obj_t self_in) {
// do the init first
pybsd_init (self);
// try to mount the sd card on /SD
if (FR_OK != f_mount(self->fatfs, "/SD", 1)) {
// 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));
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);
@@ -172,10 +172,10 @@ STATIC mp_obj_t pybsd_disable (mp_obj_t self_in) {
if (self->enabled) {
self->enabled = false;
// unmount the sd card
f_mount (NULL, "/SD", 1);
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));
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);
@@ -186,8 +186,8 @@ STATIC mp_obj_t pybsd_disable (mp_obj_t self_in) {
// unregister it with the sleep module
pybsleep_remove (self);
// change the drive in case it was /SD
f_chdrive("/SFLASH");
// change the drive in case it was /sd
f_chdrive("/flash");
}
return mp_const_none;
}

View File

@@ -24,7 +24,6 @@
* THE SOFTWARE.
*/
#include <std.h>
#include <stdint.h>
#include <string.h>
@@ -124,6 +123,7 @@ STATIC nvic_reg_store_t *nvic_reg_store;
STATIC pybsleep_data_t pybsleep_data = {NULL, NULL, NULL, 0};
volatile arm_cm4_core_regs_t vault_arm_registers;
STATIC pybsleep_reset_cause_t pybsleep_reset_cause = PYB_SLP_PWRON_RESET;
STATIC pybsleep_reset_cause_t pybsleep_wake_reason = PYB_SLP_WAKED_PWRON;
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
@@ -180,6 +180,17 @@ void pybsleep_init0 (void) {
}
else {
pybsleep_reset_cause = PYB_SLP_HIB_RESET;
// set the correct wake reason
switch (MAP_PRCMHibernateWakeupCauseGet()) {
case PRCM_HIB_WAKEUP_CAUSE_SLOW_CLOCK:
pybsleep_wake_reason = PYB_SLP_WAKED_BY_RTC;
break;
case PRCM_HIB_WAKEUP_CAUSE_GPIO:
pybsleep_wake_reason = PYB_SLP_WAKED_BY_GPIO;
break;
default:
break;
}
}
break;
default:
@@ -411,15 +422,18 @@ STATIC void PRCMInterruptHandler (void) {
switch (MAP_PRCMLPDSWakeupCauseGet()) {
case PRCM_LPDS_HOST_IRQ:
mpcallback_handler(pybsleep_data.wlan_lpds_wake_cb);
pybsleep_wake_reason = PYB_SLP_WAKED_BY_WLAN;
break;
case PRCM_LPDS_GPIO:
mpcallback_handler(pybsleep_data.gpio_lpds_wake_cb);
pybsleep_wake_reason = PYB_SLP_WAKED_BY_GPIO;
break;
case PRCM_LPDS_TIMER:
// disable the timer as a wake-up source
pybsleep_data.timer_wake_pwrmode &= ~PYB_PWR_MODE_LPDS;
MAP_PRCMLPDSWakeupSourceDisable(PRCM_LPDS_TIMER);
mpcallback_handler(pybsleep_data.timer_lpds_wake_cb);
pybsleep_wake_reason = PYB_SLP_WAKED_BY_RTC;
break;
default:
break;
@@ -631,7 +645,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_sleep_reset_cause_obj, pyb_sleep_reset_caus
/// \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_const_none;
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);
@@ -647,13 +661,13 @@ STATIC const mp_map_elem_t pybsleep_locals_dict_table[] = {
{ 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_PWR_ON_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_POWER_ON), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) },
{ 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_PIN) },
{ 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) },
};
@@ -661,7 +675,7 @@ 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,
.name = MP_QSTR_Sleep,
.locals_dict = (mp_obj_t)&pybsleep_locals_dict,
};

View File

@@ -42,19 +42,17 @@ typedef enum {
PYB_SLP_HARD_RESET,
PYB_SLP_WDT_RESET,
PYB_SLP_HIB_RESET,
PYB_SLP_SOFT_RESET,
PYB_SLP_SOFT_RESET
} pybsleep_reset_cause_t;
typedef enum {
PYB_SLP_WAKED_PWRON = 0,
PYB_SLP_WAKED_BY_WLAN,
PYB_SLP_WAKED_BY_PIN,
PYB_SLP_WAKED_BY_GPIO,
PYB_SLP_WAKED_BY_RTC
} pybsleep_wake_reason_t;
typedef void (*WakeUpCB_t)(const mp_obj_t self);
typedef void (*DeinitCB_t)(const mp_obj_t self);
/******************************************************************************
DECLARE EXPORTED VARIABLES

View File

@@ -163,15 +163,15 @@ STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxda
/******************************************************************************/
/* Micro Python bindings */
/******************************************************************************/
STATIC void pyb_spi_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
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) {
print(env, "<SPI0, SPI.MASTER, baudrate=%u, config=%u, submode=%u, bits=%u>",
mp_printf(print, "<SPI0, SPI.MASTER, baudrate=%u, config=%u, submode=%u, bits=%u>",
self->baudrate, self->config, self->submode, (self->wlen * 8));
}
else {
print(env, "<SPI0>");
mp_print_str(print, "<SPI0>");
}
}

View File

@@ -312,37 +312,37 @@ STATIC void uart_callback_disable (mp_obj_t self_in) {
/******************************************************************************/
/* Micro Python bindings */
STATIC void pyb_uart_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
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) {
print(env, "<UART%u, baudrate=%u, bits=", self->uart_id, 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:
print(env, "5");
mp_print_str(print, "5");
break;
case UART_CONFIG_WLEN_6:
print(env, "6");
mp_print_str(print, "6");
break;
case UART_CONFIG_WLEN_7:
print(env, "7");
mp_print_str(print, "7");
break;
case UART_CONFIG_WLEN_8:
print(env, "8");
mp_print_str(print, "8");
break;
default:
break;
}
if ((self->config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_NONE) {
print(env, ", parity=None");
mp_print_str(print, ", parity=None");
} else {
print(env, ", parity=%u", (self->config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_EVEN ? 0 : 1);
mp_printf(print, ", parity=%u", (self->config & UART_CONFIG_PAR_MASK) == UART_CONFIG_PAR_EVEN ? 0 : 1);
}
print(env, ", stop=%u, timeout=%u, timeout_char=%u, read_buf_len=%u>",
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);
}
else {
print(env, "<UART%u>", self->uart_id);
mp_printf(print, "<UART%u>", self->uart_id);
}
}

View File

@@ -38,6 +38,7 @@
#define MICROPY_COMP_MODULE_CONST (1)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_ENABLE_FINALISER (1)
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0)
#define MICROPY_STACK_CHECK (0)
#define MICROPY_HELPER_REPL (1)
#define MICROPY_ENABLE_SOURCE_LINE (1)
@@ -47,6 +48,7 @@
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
#define MICROPY_OPT_COMPUTED_GOTO (0)
#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0)
#define MICROPY_CPYTHON_COMPAT (0)
/* Enable FatFS LFNs
0: Disable LFN feature.
@@ -54,21 +56,26 @@
2: Enable LFN with dynamic working buffer on the STACK.
3: Enable LFN with dynamic working buffer on the HEAP.
*/
#define MICROPY_ENABLE_LFN (0)
#define MICROPY_LFN_CODE_PAGE (1)
#define MICROPY_ENABLE_LFN (2)
#define MICROPY_LFN_CODE_PAGE (437) // 1=SFN/ANSI 437=LFN/U.S.(OEM)
#define MICROPY_STREAMS_NON_BLOCK (1)
#define MICROPY_MODULE_WEAK_LINKS (0)
#define MICROPY_CAN_OVERRIDE_BUILTINS (0)
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (0)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
#define MICROPY_PY_BUILTINS_FROZENSET (1)
#define MICROPY_PY_BUILTINS_EXECFILE (1)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (0)
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (0)
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (0)
#define MICROPY_PY_SYS_MAXSIZE (0)
#define MICROPY_PY_SYS_EXIT (1)
#define MICROPY_PY_SYS_STDFILES (1)
#define MICROPY_PY_CMATH (0)
#define MICROPY_PY_IO (1)
#define MICROPY_PY_IO_FILEIO (1)
#define MICROPY_PY_UBINASCII (1)
#define MICROPY_PY_UCTYPES (1)
#define MICROPY_PY_UZLIB (0)
#define MICROPY_PY_UJSON (1)
@@ -90,6 +97,7 @@ extern const struct _mp_obj_fun_builtin_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 mp_module_ubinascii;
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;
@@ -101,14 +109,22 @@ extern const struct _mp_obj_module_t mp_module_network;
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \
{ 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_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_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 }, \
#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
{ MP_OBJ_NEW_QSTR(MP_QSTR_binascii), (mp_obj_t)&mp_module_ubinascii }, \
{ 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_struct), (mp_obj_t)&mp_module_ustruct }, \
// extra constants
#define MICROPY_PORT_CONSTANTS \
@@ -128,6 +144,7 @@ extern const struct _mp_obj_module_t mp_module_network;
// type definitions for the specific machine
#define BYTES_PER_WORD (4)
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1))
#define MP_SSIZE_MAX (0x7FFFFFFF)
#define UINT_FMT "%u"
#define INT_FMT "%d"
@@ -138,6 +155,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;
void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len);
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
@@ -160,8 +180,13 @@ typedef long mp_off_t;
#include "mpconfigboard.h"
#define MICROPY_HAL_H "cc3200_hal.h"
#define MICROPY_PIN_DEFS_PORT_H "pin_defs_cc3200.h"
#define MICROPY_PORT_HAS_TELNET (1)
#define MICROPY_PORT_HAS_FTP (1)
#define MICROPY_PY_SYS_PLATFORM "WiPy"
#define MICROPY_PORT_WLAN_AP_SSID "wipy-wlan"
#define MICROPY_PORT_WLAN_AP_KEY "www.wipy.io"
#define MICROPY_PORT_WLAN_AP_SECURITY SL_SEC_TYPE_WPA_WPA2
#define MICROPY_PORT_WLAN_AP_CHANNEL 5
#endif // __INCLUDED_MPCONFIGPORT_H

View File

@@ -26,7 +26,6 @@
*/
#include <stdint.h>
#include <std.h>
#include "py/mpconfig.h"
#include MICROPY_HAL_H
@@ -127,7 +126,6 @@ soft_reset:
pin_init0();
readline_init0();
mod_network_init0();
wlan_init0();
#if MICROPY_HW_ENABLE_RNG
rng_init0();
#endif
@@ -135,10 +133,11 @@ soft_reset:
// we are alive, so let the world know it
mperror_enable_heartbeat();
#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 *)&pin_GPIO1, PIN_MODE_3, 0, PIN_TYPE_STD, PIN_STRENGTH_2MA);
pin_config ((pin_obj_t *)&pin_GPIO2, PIN_MODE_3, 0, PIN_TYPE_STD, PIN_STRENGTH_2MA);
pin_config ((pin_obj_t *)&pin_GPIO1, PIN_MODE_3, 0, PIN_TYPE_STD_PU, PIN_STRENGTH_2MA);
pin_config ((pin_obj_t *)&pin_GPIO2, PIN_MODE_3, 0, PIN_TYPE_STD_PU, PIN_STRENGTH_2MA);
// instantiate the stdio uart
mp_obj_t args[2] = {
mp_obj_new_int(MICROPY_STDIO_UART),
@@ -147,6 +146,9 @@ soft_reset:
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();
if (rstcause < PYB_SLP_SOFT_RESET) {
@@ -170,16 +172,16 @@ soft_reset:
// initialize the serial flash file system
mptask_init_sflash_filesystem();
// append the SFLASH paths to the system path
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_SFLASH));
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_SFLASH_slash_LIB));
// append the flash paths to the system path
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash));
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;
if (!safeboot) {
// run boot.py, if it exists
const char *boot_py = "BOOT.PY";
const char *boot_py = "boot.py";
res = f_stat(boot_py, NULL);
if (res == FR_OK) {
int ret = pyexec_file(boot_py);
@@ -204,7 +206,7 @@ soft_reset:
if (pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) {
const char *main_py;
if (MP_STATE_PORT(pyb_config_main) == MP_OBJ_NULL) {
main_py = "MAIN.PY";
main_py = "main.py";
} else {
main_py = mp_obj_str_get_str(MP_STATE_PORT(pyb_config_main));
}
@@ -241,7 +243,7 @@ soft_reset_exit:
// soft reset
pybsleep_signal_soft_reset();
printf("WiPy: soft reset\n");
mp_printf(&mp_plat_print, "PYB: soft reboot\n");
sflash_disk_flush();
@@ -270,6 +272,9 @@ STATIC void mptask_pre_init (void) {
// this one allocates memory for the nvic vault
pybsleep_pre_init();
// this one allocates mameory for the WLAN semaphore
wlan_pre_init();
#if MICROPY_HW_HAS_SDCARD
pybsd_init0();
#endif
@@ -286,38 +291,42 @@ STATIC void mptask_pre_init (void) {
}
STATIC void mptask_init_sflash_filesystem (void) {
FILINFO fno;
#if _USE_LFN
fno.lfname = NULL;
fno.lfsize = 0;
#endif
// Initialise the local flash filesystem.
// Create it if needed, and mount in on /sflash.
// Create it if needed, and mount in on /flash.
// try to mount the flash
FRESULT res = f_mount(sflash_fatfs, "/SFLASH", 1);
FRESULT res = f_mount(sflash_fatfs, "/flash", 1);
if (res == FR_NO_FILESYSTEM) {
// no filesystem, so create a fresh one
res = f_mkfs("/SFLASH", 1, 0);
res = f_mkfs("/flash", 1, 0);
if (res == FR_OK) {
// success creating fresh LFS
} else {
__fatal_error("failed to create /SFLASH");
__fatal_error("failed to create /flash");
}
// create empty main.py
mptask_create_main_py();
} else if (res == FR_OK) {
// mount sucessful
FILINFO fno;
if (FR_OK != f_stat("/SFLASH/MAIN.PY", &fno)) {
if (FR_OK != f_stat("/flash/main.py", &fno)) {
// create empty main.py
mptask_create_main_py();
}
} else {
__fatal_error("failed to create /SFLASH");
__fatal_error("failed to create /flash");
}
// The current directory is used as the boot up directory.
// It is set to the internal flash filesystem by default.
f_chdrive("/SFLASH");
f_chdrive("/flash");
// Make sure we have a /flash/boot.py. Create it if needed.
FILINFO fno;
res = f_stat("/SFLASH/BOOT.PY", &fno);
res = f_stat("/flash/boot.py", &fno);
if (res == FR_OK) {
if (fno.fattrib & AM_DIR) {
// exists as a directory
@@ -329,7 +338,7 @@ STATIC void mptask_init_sflash_filesystem (void) {
} else {
// doesn't exist, create fresh file
FIL fp;
f_open(&fp, "/SFLASH/BOOT.PY", FA_WRITE | FA_CREATE_ALWAYS);
f_open(&fp, "/flash/boot.py", FA_WRITE | FA_CREATE_ALWAYS);
UINT n;
f_write(&fp, fresh_boot_py, sizeof(fresh_boot_py) - 1 /* don't count null terminator */, &n);
// TODO check we could write n bytes
@@ -338,15 +347,15 @@ STATIC void mptask_init_sflash_filesystem (void) {
}
STATIC void mptask_enter_ap_mode (void) {
// Enable simplelink in low power mode
wlan_sl_enable (ROLE_AP, SERVERS_DEF_AP_SSID, strlen(SERVERS_DEF_AP_SSID), SERVERS_DEF_AP_SECURITY,
SERVERS_DEF_AP_KEY, strlen(SERVERS_DEF_AP_KEY), SERVERS_DEF_AP_CHANNEL);
// enable simplelink in low power mode
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);
}
STATIC void mptask_create_main_py (void) {
// create empty main.py
FIL fp;
f_open(&fp, "/SFLASH/MAIN.PY", FA_WRITE | FA_CREATE_ALWAYS);
f_open(&fp, "/flash/main.py", FA_WRITE | FA_CREATE_ALWAYS);
UINT n;
f_write(&fp, fresh_main_py, sizeof(fresh_main_py) - 1 /* don't count null terminator */, &n);
f_close(&fp);

View File

@@ -1,3 +1,30 @@
/*
* 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.
*/
// qstrs specific to this port
Q(__name__)
Q(help)
@@ -35,12 +62,15 @@ Q(mkdisk)
Q(enable)
Q(disable)
// Entries for sys.path
Q(/SFLASH)
Q(/SFLASH/LIB)
Q(/SD)
Q(/SD/LIB)
Q(/flash)
Q(/flash/lib)
#if MICROPY_HW_HAS_SDCARD
Q(/sd)
Q(/sd/lib)
#endif
// for module weak links
Q(binascii)
Q(re)
Q(json)
Q(heapq)
@@ -48,9 +78,17 @@ Q(heapq)
// for os module
Q(uos)
Q(os)
Q(sysname)
Q(nodename)
Q(release)
Q(version)
Q(machine)
Q(uname)
Q(/)
Q(SFLASH)
Q(SD)
Q(flash)
#if MICROPY_HW_HAS_SDCARD
Q(sd)
#endif
Q(chdir)
Q(getcwd)
Q(listdir)
@@ -72,19 +110,13 @@ Q(init)
Q(value)
Q(low)
Q(high)
Q(toggle)
Q(get_config)
Q(name)
Q(port)
Q(pin)
Q(cpu)
Q(mode)
Q(pull)
Q(index)
Q(strength)
Q(af)
Q(intenable)
Q(intdisable)
Q(intmode)
Q(swint)
Q(mode)
Q(type)
Q(strength)
Q(IN)
Q(OUT)
Q(STD)
@@ -143,10 +175,12 @@ Q(mem_write)
Q(ADC)
Q(read)
#if MICROPY_HW_HAS_SDCARD
// for SD class
Q(SD)
Q(enable)
Q(disable)
#endif
// for RTC class
Q(RTC)
@@ -190,6 +224,7 @@ Q(AF_INET6)
Q(SOCK_STREAM)
Q(SOCK_DGRAM)
Q(SOCK_RAW)
Q(IPPROTO_SEC)
Q(IPPROTO_TCP)
Q(IPPROTO_UDP)
Q(IPPROTO_RAW)
@@ -213,8 +248,16 @@ Q(connect)
Q(isconnected)
Q(disconnect)
Q(channel)
Q(rssi)
Q(ifconfig)
Q(urn)
Q(mode)
Q(config_ip)
Q(ip)
Q(subnet)
Q(gateway)
Q(dns)
Q(mac)
Q(STA)
Q(AP)
Q(P2P)
@@ -224,6 +267,8 @@ Q(WPA_WPA2)
Q(WPA_ENT)
Q(WPS_PBC)
Q(WPS_PIN)
Q(DYNAMIC)
Q(STATIC)
// for WDT class
Q(WDT)
@@ -256,7 +301,7 @@ Q(wake_reason)
Q(ACTIVE)
Q(SUSPENDED)
Q(HIBERNATING)
Q(PWR_ON_RESET)
Q(POWER_ON)
Q(HARD_RESET)
Q(WDT_RESET)
Q(HIB_RESET)

View File

@@ -25,16 +25,14 @@
*/
#include <stdint.h>
#include <std.h>
#include <string.h>
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/misc.h"
#include "simplelink.h"
#include "serverstask.h"
#include "modwlan.h"
#include "simplelink.h"
#include "debug.h"
#include "mpexception.h"
#include "telnet.h"
#include "ftp.h"
#include "pybwdt.h"
@@ -68,8 +66,8 @@ static servers_Data_t servers_data = {.enabled = false, .do_disable = false, .do
/******************************************************************************
DECLARE PUBLIC DATA
******************************************************************************/
char *servers_user;
char *servers_pass;
char servers_user[SERVERS_USER_PASS_LEN_MAX + 1];
char servers_pass[SERVERS_USER_PASS_LEN_MAX + 1];
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
@@ -78,8 +76,6 @@ void TASK_Servers (void *pvParameters) {
bool cycle = false;
ASSERT ((servers_user = mem_Malloc(SERVERS_USER_LEN_MAX + 1)) != NULL);
ASSERT ((servers_pass = mem_Malloc(SERVERS_PASS_LEN_MAX + 1)) != NULL);
strcpy (servers_user, SERVERS_DEF_USER);
strcpy (servers_pass, SERVERS_DEF_PASS);
@@ -88,25 +84,7 @@ void TASK_Servers (void *pvParameters) {
for ( ;; ) {
if (servers_data.enabled) {
if (servers_data.do_disable) {
// disable network services
telnet_disable();
ftp_disable();
// now clear the flags
servers_data.do_disable = false;
servers_data.enabled = false;
}
else {
if (cycle) {
telnet_run();
}
else {
ftp_run();
}
}
}
else if (servers_data.do_enable) {
if (servers_data.do_enable) {
// enable network services
telnet_enable();
ftp_enable();
@@ -114,6 +92,21 @@ void TASK_Servers (void *pvParameters) {
servers_data.enabled = true;
servers_data.do_enable = false;
}
else if (servers_data.do_disable) {
// disable network services
telnet_disable();
ftp_disable();
// now clear the flags
servers_data.do_disable = false;
servers_data.enabled = false;
}
if (cycle) {
telnet_run();
}
else {
ftp_run();
}
// move to the next cycle
cycle = cycle ? false : true;
@@ -124,16 +117,16 @@ void TASK_Servers (void *pvParameters) {
}
void servers_start (void) {
servers_data.do_disable = false;
servers_data.do_enable = true;
HAL_Delay (SERVERS_CYCLE_TIME_MS * 5);
}
void servers_stop (void) {
servers_data.do_enable = false;
servers_data.do_disable = true;
do {
HAL_Delay (SERVERS_CYCLE_TIME_MS);
} while (servers_are_enabled());
HAL_Delay (SERVERS_CYCLE_TIME_MS * 5);
}
bool servers_are_enabled (void) {
@@ -148,8 +141,8 @@ void servers_close_socket (int16_t *sd) {
}
void servers_set_login (char *user, char *pass) {
memcpy(servers_user, user, SERVERS_USER_LEN_MAX);
memcpy(servers_pass, pass, SERVERS_PASS_LEN_MAX);
memcpy(servers_user, user, SERVERS_USER_PASS_LEN_MAX);
memcpy(servers_pass, pass, SERVERS_USER_PASS_LEN_MAX);
}
/******************************************************************************

View File

@@ -31,18 +31,12 @@
DEFINE CONSTANTS
******************************************************************************/
#define SERVERS_PRIORITY 2
#define SERVERS_STACK_SIZE 944
#define SERVERS_STACK_SIZE 1072
#define SERVERS_SSID_LEN_MAX 16
#define SERVERS_KEY_LEN_MAX 16
#define SERVERS_USER_LEN_MAX 16
#define SERVERS_PASS_LEN_MAX 16
#define SERVERS_DEF_AP_SSID "micropy-wlan"
#define SERVERS_DEF_AP_SECURITY SL_SEC_TYPE_WPA_WPA2
#define SERVERS_DEF_AP_KEY "micropython"
#define SERVERS_DEF_AP_CHANNEL 6
#define SERVERS_USER_PASS_LEN_MAX 16
#define SERVERS_CYCLE_TIME_MS 5
@@ -53,8 +47,8 @@
/******************************************************************************
EXPORTED DATA
******************************************************************************/
extern char *servers_user;
extern char *servers_pass;
extern char servers_user[];
extern char servers_pass[];
/******************************************************************************
DECLARE PUBLIC FUNCTIONS

View File

@@ -25,7 +25,6 @@
*/
#include <stdint.h>
#include <std.h>
#include "py/mpconfig.h"
#include MICROPY_HAL_H
@@ -36,7 +35,7 @@
#include "debug.h"
#include "mpexception.h"
#include "serverstask.h"
#include "genhdr/py-version.h"
#include "genhdr/mpversion.h"
/******************************************************************************
DEFINE PRIVATE CONSTANTS
@@ -129,6 +128,7 @@ static void telnet_send_and_proceed (void *data, _i16 Len, telnet_connected_subs
static telnet_result_t telnet_send_non_blocking (void *data, _i16 Len);
static telnet_result_t telnet_recv_text_non_blocking (void *buff, _i16 Maxlen, _i16 *rxLen);
static void telnet_process (void);
static int telnet_process_credential (char *credential, _i16 rxLen);
static void telnet_parse_input (uint8_t *str, int16_t *len);
static bool telnet_send_with_retries (int16_t sd, const void *pBuf, int16_t len);
static void telnet_reset (void);
@@ -171,12 +171,14 @@ void telnet_run (void) {
telnet_send_and_proceed((void *)telnet_request_user, strlen(telnet_request_user), E_TELNET_STE_SUB_GET_USER);
break;
case E_TELNET_STE_SUB_GET_USER:
if (E_TELNET_RESULT_OK == telnet_recv_text_non_blocking(telnet_data.rxBuffer, TELNET_RX_BUFFER_SIZE, &rxLen)) {
// Skip /r/n
if (rxLen < 2 || memcmp(servers_user, (const char *)telnet_data.rxBuffer, MAX((rxLen - 2), strlen(servers_user)))) {
telnet_data.credentialsValid = false;
if (E_TELNET_RESULT_OK == telnet_recv_text_non_blocking(telnet_data.rxBuffer + telnet_data.rxWindex,
TELNET_RX_BUFFER_SIZE - telnet_data.rxWindex,
&rxLen)) {
int result;
if ((result = telnet_process_credential (servers_user, rxLen))) {
telnet_data.credentialsValid = result > 0 ? true : false;
telnet_data.substate.connected = E_TELNET_STE_SUB_REQ_PASSWORD;
}
telnet_data.substate.connected = E_TELNET_STE_SUB_REQ_PASSWORD;
}
break;
case E_TELNET_STE_SUB_REQ_PASSWORD:
@@ -188,16 +190,17 @@ void telnet_run (void) {
telnet_send_and_proceed((void *)telnet_options_pass, sizeof(telnet_options_pass), E_TELNET_STE_SUB_GET_PASSWORD);
break;
case E_TELNET_STE_SUB_GET_PASSWORD:
if (E_TELNET_RESULT_OK == telnet_recv_text_non_blocking(telnet_data.rxBuffer, TELNET_RX_BUFFER_SIZE, &rxLen)) {
// skip /r/n
if (rxLen < 2 || memcmp(servers_pass, (const char *)telnet_data.rxBuffer, MAX((rxLen - 2), strlen(servers_pass)))) {
telnet_data.credentialsValid = false;
}
if (telnet_data.credentialsValid) {
telnet_data.substate.connected = E_TELNET_STE_SUB_SND_REPL_OPTIONS;
}
else {
telnet_data.substate.connected = E_TELNET_STE_SUB_INVALID_LOGGIN;
if (E_TELNET_RESULT_OK == telnet_recv_text_non_blocking(telnet_data.rxBuffer + telnet_data.rxWindex,
TELNET_RX_BUFFER_SIZE - telnet_data.rxWindex,
&rxLen)) {
int result;
if ((result = telnet_process_credential (servers_pass, rxLen))) {
if ((telnet_data.credentialsValid = telnet_data.credentialsValid && (result > 0 ? true : false))) {
telnet_data.substate.connected = E_TELNET_STE_SUB_SND_REPL_OPTIONS;
}
else {
telnet_data.substate.connected = E_TELNET_STE_SUB_INVALID_LOGGIN;
}
}
}
break;
@@ -325,7 +328,7 @@ static bool telnet_create_socket (void) {
// Bind the socket to a port number
sServerAddress.sin_family = AF_INET;
sServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);
sServerAddress.sin_addr.s_addr = INADDR_ANY;
sServerAddress.sin_port = htons(TELNET_PORT);
ASSERT (sl_Bind(telnet_data.sd, (const SlSockAddr_t *)&sServerAddress, sizeof(sServerAddress)) == SL_SOC_OK);
@@ -427,6 +430,26 @@ static void telnet_process (void) {
}
}
static int telnet_process_credential (char *credential, _i16 rxLen) {
telnet_data.rxWindex += rxLen;
if (telnet_data.rxWindex >= SERVERS_USER_PASS_LEN_MAX) {
telnet_data.rxWindex = SERVERS_USER_PASS_LEN_MAX;
}
uint8_t *p = telnet_data.rxBuffer + SERVERS_USER_PASS_LEN_MAX;
// if a '\r' is found, or the length exceeds the max username length
if ((p = memchr(telnet_data.rxBuffer, '\r', telnet_data.rxWindex)) || (telnet_data.rxWindex >= SERVERS_USER_PASS_LEN_MAX)) {
uint8_t len = p - telnet_data.rxBuffer;
telnet_data.rxWindex = 0;
if ((len > 0) && (memcmp(credential, telnet_data.rxBuffer, MAX(len, strlen(credential))) == 0)) {
return 1;
}
return -1;
}
return 0;
}
static void telnet_parse_input (uint8_t *str, int16_t *len) {
int16_t b_len = *len;
uint8_t *b_str = str;
@@ -444,8 +467,9 @@ static void telnet_parse_input (uint8_t *str, int16_t *len) {
}
}
else {
_str += 3;
*len -= 3;
// in case we have received an incomplete telnet option, unlikely, but possible
_str += MIN(3, *len);
*len -= MIN(3, *len);
}
}
}

View File

@@ -27,7 +27,6 @@
#include <stdint.h>
#include <stdbool.h>
#include "std.h"
#include "fifo.h"

View File

@@ -24,7 +24,6 @@
* THE SOFTWARE.
*/
#include "std.h"
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_types.h"

View File

@@ -28,7 +28,6 @@
#include <stdbool.h>
#include <string.h>
#include <std.h>
#include "osi.h"
#include "fifo.h"
#include "socketfifo.h"

View File

@@ -24,21 +24,13 @@
* THE SOFTWARE.
*/
// This file is needed because in some cases we can't include stdio.h,
// because the CC3100 socket driver has name clashes with it.
typedef unsigned int size_t;
void *memcpy(void *dest, const void *src, size_t n);
void *memmove(void *dest, const void *src, size_t n);
void *memset(void *s, int c, size_t n);
size_t strlen(const char *str);
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
char *strcpy(char *dest, const char *src);
char *strcat(char *dest, const char *src);
char *strchr(const char *s, int c);
char *strstr(const char *haystack, const char *needle);
int printf(const char *fmt, ...);
int snprintf(char *str, size_t size, const char *fmt, ...);
// Convenience function, defined in main.c.
void stoupper (char *str);

View File

@@ -1,41 +1,32 @@
/*
* 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.
*/
// This file contains pin definitions that are specific to the cc3200 port.
// This file should only ever be #included by pybgpio.h and not directly.
//*****************************************************************************
// Define types
//*****************************************************************************
enum {
PORT_A0 = GPIOA0_BASE,
PORT_A1 = GPIOA1_BASE,
PORT_A2 = GPIOA2_BASE,
PORT_A3 = GPIOA3_BASE
};
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* 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.
*/
#ifndef VERSION_H_
#define VERSION_H_
#define WIPY_SW_VERSION_NUMBER "0.9.1"
#endif /* VERSION_H_ */

View File

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

View File

@@ -1,6 +1,14 @@
Micro Python libraries
======================
Functionality specific to the Micro Python implementation is available in
the following library.
.. toctree::
:maxdepth: 1
micropython.rst
Python standard libraries
-------------------------

View File

@@ -0,0 +1,37 @@
:mod:`micropython` -- access and control Micro Python internals
===============================================================
.. module:: micropython
:synopsis: access and control Micro Python internals
Functions
---------
.. function:: mem_info([verbose])
Print information about currently used memory. If the ``verbose`` argument
is given then extra information is printed.
The information that is printed is implementation dependent, but currently
includes the amount of stack and heap used. In verbose mode it prints out
the entire heap indicating which blocks are used and which are free.
.. function:: qstr_info([verbose])
Print information about currently interned strings. If the ``verbose``
argument is given then extra information is printed.
The information that is printed is implementation dependent, but currently
includes the number of interned strings and the amount of RAM they use. In
verbose mode it prints out the names of all RAM-interned strings.
.. function:: alloc_emergency_exception_buf(size)
Allocate ``size`` bytes of RAM for the emergency exception buffer (a good
size is around 100 bytes). The buffer is used to create exceptions in cases
when normal RAM allocation would fail (eg within an interrupt handler) and
therefore give useful traceback information in these situations.
A good way to use this function is to put it at the start of your main script
(eg boot.py or main.py) and then the emergency exception buffer will be active
for all the code following it.

View File

@@ -46,6 +46,10 @@ Functions
Remove a directory.
.. function:: rename(old_path, new_path)
Rename a file.
.. function:: stat(path)
Get the status of a file or directory.

View File

@@ -82,7 +82,7 @@ Methods
Turn off the CAN bus.
.. method:: can.setfilter(bank, mode, fifo, params)
.. method:: can.setfilter(bank, mode, fifo, params, \*, rtr)
Configure a filter bank:
@@ -107,6 +107,23 @@ Methods
|CAN.MASK32 |As with CAN.MASK16 but with only one 32 bit id/mask pair.|
+-----------+---------------------------------------------------------+
- ``rtr`` is an array of booleans that states if a filter should accept a
remote transmission request message. If this argument is not given
then it defaults to False for all entries. The length of the array
depends on the ``mode`` argument.
+-----------+----------------------+
|``mode`` |length of rtr array |
+===========+======================+
|CAN.LIST16 |4 |
+-----------+----------------------+
|CAN.LIST32 |2 |
+-----------+----------------------+
|CAN.MASK16 |2 |
+-----------+----------------------+
|CAN.MASK32 |1 |
+-----------+----------------------+
.. method:: can.clearfilter(bank)
Clear and disables a filter bank:
@@ -124,15 +141,30 @@ Methods
- ``fifo`` is an integer, which is the FIFO to receive on
- ``timeout`` is the timeout in milliseconds to wait for the receive.
Return value: buffer of data bytes.
Return value: A tuple containing four values.
.. method:: can.send(send, addr, \*, timeout=5000)
- The id of the message.
- A boolean that indicates if the message is an RTR message.
- The FMI (Filter Match Index) value.
- An array containing the data.
.. method:: can.send(data, id, \*, timeout=0, rtr=False)
Send a message on the bus:
- ``send`` is the data to send (an integer to send, or a buffer object).
- ``addr`` is the address to send to
- ``data`` is the data to send (an integer to send, or a buffer object).
- ``id`` is the id of the message to be sent.
- ``timeout`` is the timeout in milliseconds to wait for the send.
- ``rtr`` is a boolean that specifies if the message shall be sent as
a remote transmission request. If ``rtr`` is True then only the length
of ``data`` is used to fill in the DLC slot of the frame; the actual
bytes in ``data`` are unused.
If timeout is 0 the message is placed in a buffer in one of three hardware
buffers and the method returns immediately. If all three buffers are in use
an exception is thrown. If timeout is not 0, the method waits until the
message is transmitted. If the message can't be transmitted within the
specified time an exception is thrown.
Return value: ``None``.

View File

@@ -38,6 +38,17 @@ Methods
``subseconds`` counts down from 255 to 0
.. method:: rtc.wakeup(timeout, callback=None)
Set the RTC wakeup timer to trigger repeatedly at every ``timeout``
milliseconds. This trigger can wake the pyboard from both the sleep
states: :meth:`pyb.stop` and :meth:`pyb.standby`.
If ``timeout`` is ``None`` then the wakeup timer is disabled.
If ``callback`` is given then it is executed at every trigger of the
wakeup timer. ``callback`` must take exactly one argument.
.. method:: rtc.info()
Get information about the startup time and reset source.
@@ -46,3 +57,19 @@ Methods
start up.
- Bit 0x10000 is set if a power-on reset occurred.
- Bit 0x20000 is set if an external reset occurred
.. method:: rtc.calibration(cal)
Get or set RTC calibration.
With no arguments, ``calibration()`` returns the current calibration
value, which is an integer in the range [-511 : 512]. With one
argument it sets the RTC calibration.
The RTC Smooth Calibration mechanism addjusts the RTC clock rate by
adding or subtracting the given number of ticks from the 32768 Hz
clock over a 32 second period (corresponding to 2^20 clock ticks.)
Each tick added will speed up the clock by 1 part in 2^20, or 0.954
ppm; likewise the RTC clock it slowed by negative values. The
usable calibration range is:
(-511 * 0.954) ~= -487.5 ppm up to (512 * 0.954) ~= 488.5 ppm

View File

@@ -18,6 +18,13 @@ Example usage to toggle an LED at a fixed frequency::
tim.init(freq=2) # trigger at 2Hz
tim.callback(lambda t:pyb.LED(1).toggle())
Example using named function for the callback::
def tick(timer): # we will receive the timer object when being called
print(timer.counter()) # show current timer's counter value
tim = pyb.Timer(4, freq=1) # create a timer object using timer 4 - trigger at 1Hz
tim.callback(tick) # set the callback to our tick function
Further examples::
tim = pyb.Timer(4, freq=100) # freq in Hz
@@ -32,6 +39,10 @@ Further examples::
the servo driver, and Timer 6 is used for timed ADC/DAC reading/writing.
It is recommended to use the other timers in your programs.
*Note:* Memory can't be allocated during a callback (an interrupt) and so
exceptions raised within a callback don't give much information. See
:func:`micropython.alloc_emergency_exception_buf` for how to get around this
limitation.
Constructors
------------

View File

@@ -36,15 +36,49 @@ Methods
.. method:: usb_vcp.close()
This method does nothing. It exists so the USB_VCP object can act as
a file.
.. method:: usb_vcp.read([nbytes])
Read at most ``nbytes`` from the serial device and return them as a
bytes object. If ``nbytes`` is not specified then the method acts as
``readall()``.
.. method:: usb_vcp.readall()
Read all available bytes from the serial device and return them as
a bytes object.
.. method:: usb_vcp.readinto(buf, [maxlen])
Read bytes from the serial device and store them into ``buf``, which
should be a buffer-like object. At most ``len(buf)`` bytes are read.
If ``maxlen`` is given and then at most ``min(maxlen, len(buf))`` bytes
are read.
Returns the number of bytes read and stored into ``buf``.
.. method:: usb_vcp.readline()
Read a whole line from the serial device.
Returns a bytes object containing the data, including the trailing
newline character.
.. method:: usb_vcp.readlines()
Read as much data as possible from the serial device, breaking it into
lines.
Returns a list of bytes objects, each object being one of the lines.
Each line will include the newline character.
.. method:: usb_vcp.write(buf)
Write the bytes from ``buf`` to the serial device.
Returns the number of bytes written.
.. method:: usb_vcp.recv(data, \*, timeout=5000)
@@ -65,6 +99,3 @@ Methods
- ``timeout`` is the timeout in milliseconds to wait for the send.
Return value: number of bytes sent.
.. method:: usb_vcp.write(buf)

View File

@@ -133,14 +133,33 @@ Power related functions
.. function:: wfi()
Wait for an interrupt.
This executies a ``wfi`` instruction which reduces power consumption
of the MCU until an interrupt occurs, at which point execution continues.
Wait for an internal or external interrupt.
This executes a ``wfi`` instruction which reduces power consumption
of the MCU until any interrupt occurs (be it internal or external),
at which point execution continues. Note that the system-tick interrupt
occurs once every millisecond (1000Hz) so this function will block for
at most 1ms.
.. function:: stop()
Put the pyboard in a "sleeping" state.
This reduces power consumption to less than 500 uA. To wake from this
sleep state requires an external interrupt or a real-time-clock event.
Upon waking execution continues where it left off.
See :meth:`rtc.wakeup` to configure a real-time-clock wakeup event.
.. function:: standby()
Put the pyboard into a "deep sleep" state.
.. function:: stop()
This reduces power consumption to less than 50 uA. To wake from this
sleep state requires an external interrupt or a real-time-clock event.
Upon waking the system undergoes a hard reset.
See :meth:`rtc.wakeup` to configure a real-time-clock wakeup event.
Miscellaneous functions
-----------------------
@@ -162,6 +181,13 @@ Miscellaneous functions
Print out lots of information about the board.
.. 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:: mount(device, mountpoint, \*, readonly=False, mkfs=False)
Mount a block device and make it available as part of the filesystem.

View File

@@ -98,8 +98,8 @@ Module contents
.. class:: struct(descriptor, layout_type)
Create a "foreign data structure" object based on its descriptor (encoded
as a dictionary) and layout type.
Create a "foreign data structure" class based on its descriptor (encoded
as a dictionary) and layout type (see below).
.. data:: LITTLE_ENDIAN
@@ -140,6 +140,22 @@ Module contents
so it can be both written too, and you will access current value
at the given memory address.
Structure classes and instantiating structure objects
-----------------------------------------------------
Given structure descriptor and layout type, you can instantiate a
"structure class" using uctypes.struct() factory function. From it,
you can instantiate a specific structure instance at a given
memory address. Memory address usually comes from following sources:
* Predefined address, when accessing hardware registers on a baremetal
port. Lookup these addresses in datasheet for a particular MCU/SoC.
* As return value from a call to some FFI (Foreign Function Interface)
function.
* From uctypes.addressof(), when you want to pass arguments to FFI
function, or alternatively, to access some data for I/O (for example,
data read from file or network socket).
Structure objects
-----------------

View File

@@ -1,242 +1,242 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. xml to make Docutils-native XML files
echo. pseudoxml to make pseudoxml-XML files for display purposes
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\MicroPython.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\MicroPython.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdfja" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf-ja
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)
if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)
:end
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. xml to make Docutils-native XML files
echo. pseudoxml to make pseudoxml-XML files for display purposes
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\MicroPython.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\MicroPython.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdfja" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf-ja
cd %BUILDDIR%/..
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)
if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)
:end

View File

@@ -15,12 +15,16 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <std.h>
#include <string.h>
#include "cc3000_common.h"
#include "socket.h"
#include "inet_ntop.h"
// We can't include stdio.h because it defines _types_fd_set, but we
// need to use the CC3000 version of this type. So we must provide
// our own declaration of snprintf. Grrr.
int snprintf(char *str, size_t size, const char *fmt, ...);
#define IN6ADDRSZ 16
#define INADDRSZ 4
#define INT16SZ 2

View File

@@ -6,6 +6,9 @@ QSTR_DEFS = qstrdefsport.h #$(BUILD)/pins_qstr.h
# include py core make definitions
include ../py/py.mk
MAKE_FROZEN = ../tools/make-frozen.py
SCRIPTDIR = scripts
PORT = /dev/ttyACM0
CROSS_COMPILE = xtensa-lx106-elf-
ESP_SDK = $(shell $(CC) -print-sysroot)/usr
@@ -14,15 +17,20 @@ INC = -I.
INC += -I..
INC += -I../stmhal
INC += -I../lib/mp-readline
INC += -I../lib/netutils
INC += -I../lib/timeutils
INC += -I$(BUILD)
INC += -I$(ESP_SDK)/include
UART_OS = 1
CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \
-D__ets__ -DICACHE_FLASH \
-fno-inline-functions \
-Wl,-EL -mlongcalls -mtext-section-literals \
CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_XTENSA) $(COPT)
CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
$(CFLAGS_XTENSA) $(COPT)
LDFLAGS = -nostdlib -T esp8266.ld -Map=$(@:.elf=.map) --cref
LIBS = -L$(ESP_SDK)/lib -lmain -ljson -llwip -lpp -lnet80211 -lwpa -lphy -lnet80211
@@ -48,17 +56,23 @@ SRC_C = \
uart.c \
modpyb.c \
modpybpin.c \
modpybrtc.c \
modesp.c \
modutime.c \
utils.c \
$(BUILD)/frozen.c \
STM_SRC_C = $(addprefix stmhal/,\
printf.c \
string0.c \
pyexec.c \
pybstdio.c \
)
LIB_SRC_C = $(addprefix lib/,\
libc/string0.c \
mp-readline/readline.c \
netutils/netutils.c \
timeutils/timeutils.c \
)
SRC_S = \
@@ -74,6 +88,21 @@ OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
all: $(BUILD)/firmware-combined.bin
CONFVARS_FILE = $(BUILD)/confvars
ifeq ($(wildcard $(CONFVARS_FILE)),)
$(shell $(MKDIR) -p $(BUILD))
$(shell echo $(SCRIPTDIR) $(UART_OS) > $(CONFVARS_FILE))
else ifneq ($(shell cat $(CONFVARS_FILE)), $(SCRIPTDIR) $(UART_OS))
$(shell echo $(SCRIPTDIR) $(UART_OS) > $(CONFVARS_FILE))
endif
$(BUILD)/uart.o: $(CONFVARS_FILE)
$(BUILD)/frozen.c: $(wildcard $(SCRIPTDIR)/*) $(CONFVARS_FILE)
$(ECHO) "Generating $@"
$(Q)$(MAKE_FROZEN) $(SCRIPTDIR) > $@
.PHONY: deploy
deploy: $(BUILD)/firmware-combined.bin

View File

@@ -5,7 +5,7 @@ MEMORY
dport0_0_seg : org = 0x3ff00000, len = 0x10
dram0_0_seg : org = 0x3ffe8000, len = 0x14000
iram1_0_seg : org = 0x40100000, len = 0x8000
irom0_0_seg : org = 0x40210000, len = 0x40000
irom0_0_seg : org = 0x40210000, len = 0x5A000
}
/* define the top of RAM */
@@ -79,9 +79,13 @@ SECTIONS
*pyexec.o(.literal*, .text*)
*readline.o(.literal*, .text*)
*pybstdio.o(.literal*, .text*)
*modpyb.o(.literal*, .text*)
*gccollect.o(.literal* .text*)
*gchelper.o(.literal* .text*)
*modpyb.o(.literal*, .text*)
*modpybpin.o(.literal*, .text*)
*modpybrtc.o(.literal*, .text*)
*modesp.o(.literal* .text*)
*modutime.o(.literal* .text*)
/* we put as much rodata as possible in this section */
/* note that only rodata accessed as a machine word is allowed here */

View File

@@ -29,6 +29,7 @@
#include "etshal.h"
#include "uart.h"
#include "esp_mphal.h"
#include "user_interface.h"
extern void ets_wdt_disable(void);
extern void wdt_feed(void);
@@ -82,8 +83,7 @@ void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len) {
}
uint32_t HAL_GetTick(void) {
// TODO
return 0;
return system_get_time() / 1000;
}
void HAL_Delay(uint32_t Delay) {

View File

@@ -29,17 +29,12 @@
#include "py/gc.h"
#include "gccollect.h"
STATIC uint32_t stack_end;
// As we do not have control over the application entry point, there is no way
// to figure out the real stack base on runtime, so it needs to be hardcoded
#define STACK_END 0x40000000
mp_uint_t gc_helper_get_regs_and_sp(mp_uint_t *regs);
void gc_collect_init(void) {
mp_uint_t regs[8];
mp_uint_t sp = gc_helper_get_regs_and_sp(regs);
stack_end = sp;
//printf("stack=%p ram_end=%p %d\n", stack_end, &_ram_end);
}
void gc_collect(void) {
// start the GC
gc_collect_start();
@@ -53,7 +48,7 @@ void gc_collect(void) {
mp_uint_t sp = gc_helper_get_regs_and_sp(regs);
// trace the stack, including the registers (since they live on the stack in this function)
gc_collect_root((void**)sp, (stack_end - sp) / sizeof(uint32_t));
gc_collect_root((void**)sp, (STACK_END - sp) / sizeof(uint32_t));
// end the GC
gc_collect_end();

View File

@@ -37,5 +37,4 @@ extern uint32_t _bss_end;
extern uint32_t _heap_start;
extern uint32_t _heap_end;
void gc_collect_init(void);
void gc_collect(void);

View File

@@ -32,6 +32,7 @@
#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/stackctrl.h"
#include "py/frozenmod.h"
#include "py/gc.h"
#include "pyexec.h"
#include "gccollect.h"
@@ -39,40 +40,33 @@
STATIC char heap[16384];
void user_init(void) {
soft_reset:
STATIC void mp_reset(void) {
mp_stack_set_limit(10240);
mp_hal_init();
gc_init(heap, heap + sizeof(heap));
gc_collect_init();
mp_init();
mp_obj_list_init(mp_sys_path, 0);
mp_obj_list_init(mp_sys_argv, 0);
printf("\n");
#if MICROPY_REPL_EVENT_DRIVEN
pyexec_friendly_repl_init();
uart_task_init();
return;
goto soft_reset;
#else
for (;;) {
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
if (pyexec_raw_repl() != 0) {
break;
}
} else {
if (pyexec_friendly_repl() != 0) {
break;
}
}
}
goto soft_reset;
#if MICROPY_MODULE_FROZEN
mp_lexer_t *lex = mp_find_frozen_module("main", 4);
mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mp_globals_get(), mp_locals_get());
#endif
}
void soft_reset(void) {
mp_hal_stdout_tx_str("PYB: soft reset\r\n");
mp_hal_udelay(10000); // allow UART to flush output
mp_reset();
pyexec_event_repl_init();
}
void user_init(void) {
mp_reset();
mp_hal_stdout_tx_str("\r\n");
pyexec_event_repl_init();
uart_task_init();
}
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
return NULL;
}

View File

@@ -32,14 +32,456 @@
#include "py/obj.h"
#include "py/gc.h"
#include "py/runtime.h"
#include "py/pfenv.h"
#include MICROPY_HAL_H
#include "netutils.h"
#include "queue.h"
#include "user_interface.h"
#include "espconn.h"
#include "utils.h"
// Singleton instance of scan callback, meaning that there can be only
// one concurrent AP scan.
STATIC mp_obj_t scan_cb_obj;
STATIC const mp_obj_type_t esp_socket_type;
typedef struct _esp_socket_obj_t {
mp_obj_base_t base;
struct espconn *espconn;
mp_obj_t cb_connect;
mp_obj_t cb_recv;
mp_obj_t cb_sent;
mp_obj_t cb_disconnect;
uint8_t *recvbuf;
mp_uint_t recvbuf_len;
bool fromserver;
mp_obj_list_t *connlist;
} esp_socket_obj_t;
// Due to the onconnect callback not being able to recognize the parent esp_socket,
// we can have only one esp_socket listening at a time
// This should be solvable by some PIC hacking
STATIC esp_socket_obj_t *esp_socket_listening;
STATIC mp_obj_t esp_socket_make_new_base() {
esp_socket_obj_t *s = m_new_obj_with_finaliser(esp_socket_obj_t);
s->recvbuf = NULL;
s->base.type = (mp_obj_t)&esp_socket_type;
s->cb_connect = mp_const_none;
s->cb_recv = mp_const_none;
s->cb_disconnect = mp_const_none;
s->cb_sent = mp_const_none;
s->fromserver = false;
s->connlist = NULL;
return s;
}
// constructor esp_socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None)
// Arguments ignored as we do not support UDP (yet)
STATIC mp_obj_t esp_socket_make_new(mp_obj_t type_in, mp_uint_t n_args,
mp_uint_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 4, false);
esp_socket_obj_t *s = esp_socket_make_new_base();
s->espconn = m_new_obj(struct espconn);
espconn_create(s->espconn);
s->espconn->reverse = s;
// TODO: UDP Support
s->espconn->type = ESPCONN_TCP;
s->espconn->state = ESPCONN_NONE;
s->espconn->proto.tcp = m_new_obj(esp_tcp);
return s;
}
// method socket.close()
STATIC mp_obj_t esp_socket_close(mp_obj_t self_in) {
esp_socket_obj_t *s = self_in;
if (esp_socket_listening == s) {
esp_socket_listening = NULL;
}
if (s->espconn->state != ESPCONN_NONE && s->espconn->state != ESPCONN_CLOSE) {
espconn_disconnect(s->espconn);
}
if (s->connlist != NULL) {
mp_obj_list_set_len(s->connlist, 0);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket_close_obj, esp_socket_close);
// method socket.__del__()
STATIC mp_obj_t esp_socket___del__(mp_obj_t self_in) {
esp_socket_obj_t *s = self_in;
esp_socket_close(self_in);
if (s->fromserver) {
espconn_delete(s->espconn);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket___del___obj, esp_socket___del__);
// method socket.bind(address)
STATIC mp_obj_t esp_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
esp_socket_obj_t *s = self_in;
mp_uint_t port = netutils_parse_inet_addr(addr_in,
s->espconn->proto.tcp->remote_ip, NETUTILS_BIG);
s->espconn->proto.tcp->local_port = port;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_bind_obj, esp_socket_bind);
STATIC void esp_socket_recv_callback(void *arg, char *pdata, unsigned short len) {
struct espconn *conn = arg;
esp_socket_obj_t *s = conn->reverse;
if (s->cb_recv != mp_const_none) {
call_function_2_protected(s->cb_recv, s, mp_obj_new_bytes((byte *)pdata, len));
} else {
if (s->recvbuf == NULL) {
s->recvbuf = gc_alloc(len, false);
s->recvbuf_len = len;
if (s->recvbuf != NULL) {
memcpy(s->recvbuf, pdata, len);
}
} else {
s->recvbuf = gc_realloc(s->recvbuf, s->recvbuf_len + len);
if (s->recvbuf != NULL) {
memcpy(&s->recvbuf[s->recvbuf_len], pdata, len);
s->recvbuf_len += len;
}
}
if (s->recvbuf == NULL) {
esp_socket_close(s);
return;
}
}
}
STATIC void esp_socket_sent_callback(void *arg) {
struct espconn *conn = arg;
esp_socket_obj_t *s = conn->reverse;
if (s->cb_sent != mp_const_none) {
call_function_1_protected(s->cb_sent, s);
}
}
STATIC void esp_socket_disconnect_callback(void *arg) {
struct espconn *conn = arg;
esp_socket_obj_t *s = conn->reverse;
if (s->cb_disconnect != mp_const_none) {
call_function_1_protected(s->cb_disconnect, s);
}
esp_socket_close(s);
}
STATIC void esp_socket_connect_callback_server(void *arg) {
struct espconn *conn = arg;
esp_socket_obj_t *s = esp_socket_make_new_base();
s->espconn = conn;
s->fromserver = true;
conn->reverse = s;
espconn_regist_recvcb(conn, esp_socket_recv_callback);
espconn_regist_sentcb(conn, esp_socket_sent_callback);
espconn_regist_disconcb(conn, esp_socket_disconnect_callback);
espconn_regist_time(conn, 15, 0);
if (esp_socket_listening->cb_connect != mp_const_none) {
call_function_1_protected(esp_socket_listening->cb_connect, s);
} else {
mp_obj_list_append(esp_socket_listening->connlist, s);
}
}
STATIC void esp_socket_connect_callback_client(void *arg) {
struct espconn *conn = arg;
esp_socket_obj_t *s = conn->reverse;
if (s->cb_connect != mp_const_none) {
call_function_1_protected(s->cb_connect, s);
}
}
// method socket.listen(backlog)
STATIC mp_obj_t esp_socket_listen(mp_obj_t self_in, mp_obj_t backlog) {
esp_socket_obj_t *s = self_in;
if (esp_socket_listening != NULL) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
"only one espconn can listen at a time"));
}
esp_socket_listening = s;
s->connlist = mp_obj_new_list(0, NULL);
espconn_regist_connectcb(s->espconn, esp_socket_connect_callback_server);
espconn_accept(s->espconn);
espconn_regist_time(s->espconn, 1500, 0);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_listen_obj, esp_socket_listen);
// method socket.accept()
STATIC mp_obj_t esp_socket_accept(mp_obj_t self_in) {
esp_socket_obj_t *s = self_in;
if (s->connlist == NULL) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
"not listening"));
}
do {
mp_uint_t len;
mp_obj_t *items;
mp_obj_list_get(s->connlist, &len, &items);
if (len == 0) {
break;
}
esp_socket_obj_t *rs = items[0];
mp_obj_list_remove(s->connlist, rs);
if (rs->espconn->state != ESPCONN_CLOSE) {
return rs;
}
} while (true);
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
"no connection in queue"));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket_accept_obj, esp_socket_accept);
// method socket.connect(address)
STATIC mp_obj_t esp_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
esp_socket_obj_t *s = self_in;
if (s->espconn == NULL || s->espconn->state != ESPCONN_NONE) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
"transport endpoint is already connected or closed"));
}
espconn_regist_connectcb(s->espconn, esp_socket_connect_callback_client);
espconn_regist_recvcb(s->espconn, esp_socket_recv_callback);
espconn_regist_sentcb(s->espconn, esp_socket_sent_callback);
espconn_regist_disconcb(s->espconn, esp_socket_disconnect_callback);
s->espconn->proto.tcp->remote_port =
netutils_parse_inet_addr(addr_in, s->espconn->proto.tcp->remote_ip,
NETUTILS_BIG);
espconn_connect(s->espconn);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_connect_obj, esp_socket_connect);
// method socket.send(bytes)
STATIC mp_obj_t esp_socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
esp_socket_obj_t *s = self_in;
if (s->espconn->state == ESPCONN_NONE || s->espconn->state == ESPCONN_CLOSE) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
"not connected"));
}
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
espconn_sent(s->espconn, bufinfo.buf, bufinfo.len);
return mp_obj_new_int(bufinfo.len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_send_obj, esp_socket_send);
// method socket.recv(bufsize)
STATIC mp_obj_t esp_socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
esp_socket_obj_t *s = self_in;
if (s->recvbuf == NULL) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
"no data available"));
}
mp_uint_t mxl = mp_obj_get_int(len_in);
if (mxl >= s->recvbuf_len) {
mp_obj_t trt = mp_obj_new_bytes(s->recvbuf, s->recvbuf_len);
gc_free(s->recvbuf);
s->recvbuf = NULL;
return trt;
} else {
mp_obj_t trt = mp_obj_new_bytes(s->recvbuf, mxl);
memmove(s->recvbuf, &s->recvbuf[mxl], s->recvbuf_len - mxl);
s->recvbuf_len -= mxl;
s->recvbuf = gc_realloc(s->recvbuf, s->recvbuf_len);
return trt;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_recv_obj, esp_socket_recv);
// method socket.sendto(bytes, address)
STATIC mp_obj_t esp_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "UDP not supported"));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_socket_sendto_obj, esp_socket_sendto);
// method socket.recvfrom(bufsize)
STATIC mp_obj_t esp_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "UDP not supported"));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_recvfrom_obj, esp_socket_recvfrom);
STATIC mp_obj_t esp_socket_onconnect(mp_obj_t self_in, mp_obj_t lambda_in) {
esp_socket_obj_t *s = self_in;
s->cb_connect = lambda_in;
if (s->connlist != NULL) {
do {
mp_uint_t len;
mp_obj_t *items;
mp_obj_list_get(s->connlist, &len, &items);
if (len == 0) {
break;
}
esp_socket_obj_t *rs = items[0];
mp_obj_list_remove(s->connlist, rs);
if (s->espconn->state != ESPCONN_CLOSE) {
call_function_1_protected(s->cb_connect, rs);
}
} while (true);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_onconnect_obj, esp_socket_onconnect);
STATIC mp_obj_t esp_socket_onrecv(mp_obj_t self_in, mp_obj_t lambda_in) {
esp_socket_obj_t *s = self_in;
s->cb_recv = lambda_in;
if (s->recvbuf != NULL) {
call_function_2_protected(s->cb_recv, s,
mp_obj_new_bytes((byte *)s->recvbuf, s->recvbuf_len));
s->recvbuf = NULL;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_onrecv_obj, esp_socket_onrecv);
STATIC mp_obj_t esp_socket_onsent(mp_obj_t self_in, mp_obj_t lambda_in) {
esp_socket_obj_t *s = self_in;
s->cb_sent = lambda_in;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_onsent_obj, esp_socket_onsent);
STATIC mp_obj_t esp_socket_ondisconnect(mp_obj_t self_in, mp_obj_t lambda_in) {
esp_socket_obj_t *s = self_in;
s->cb_disconnect = lambda_in;
if (s->espconn->state == ESPCONN_CLOSE) {
call_function_1_protected(s->cb_disconnect, s);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_ondisconnect_obj, esp_socket_ondisconnect);
typedef struct _esp_getaddrinfo_cb_struct_t {
mp_obj_t lambda;
mp_uint_t port;
} esp_getaddrinfo_cb_struct_t;
STATIC esp_getaddrinfo_cb_struct_t esp_getaddrinfo_cb_struct;
STATIC void esp_getaddrinfo_cb(const char *name, ip_addr_t *ipaddr, void *arg) {
mp_obj_t namestr = mp_obj_new_str(name, strlen(name), true);
if (ipaddr != NULL) {
uint8_t ip[4];
ip[0] = (ipaddr->addr >> 24) & 0xff;
ip[1] = (ipaddr->addr >> 16) & 0xff;
ip[2] = (ipaddr->addr >> 8) & 0xff;
ip[3] = (ipaddr->addr >> 0) & 0xff;
mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(0);
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(0);
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
tuple->items[4] = netutils_format_inet_addr(ip,
esp_getaddrinfo_cb_struct.port, NETUTILS_LITTLE);
call_function_2_protected(esp_getaddrinfo_cb_struct.lambda, namestr, tuple);
} else {
call_function_2_protected(esp_getaddrinfo_cb_struct.lambda, namestr, mp_const_none);
}
}
STATIC mp_obj_t esp_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in,
mp_obj_t lambda_in) {
mp_uint_t hlen;
const char *host = mp_obj_str_get_data(host_in, &hlen);
ip_addr_t ipaddr;
esp_getaddrinfo_cb_struct.lambda = lambda_in;
esp_getaddrinfo_cb_struct.port = mp_obj_get_int(port_in);
err_t ret = espconn_gethostbyname(NULL, host, &ipaddr,
esp_getaddrinfo_cb);
if (ret == ESPCONN_OK) {
esp_getaddrinfo_cb(host, &ipaddr, NULL);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_getaddrinfo_obj, esp_getaddrinfo);
STATIC const mp_map_elem_t esp_socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&esp_socket___del___obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&esp_socket_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&esp_socket_bind_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&esp_socket_listen_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&esp_socket_accept_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&esp_socket_connect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&esp_socket_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&esp_socket_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&esp_socket_sendto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&esp_socket_recvfrom_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_onconnect), (mp_obj_t)&esp_socket_onconnect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_onrecv), (mp_obj_t)&esp_socket_onrecv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_onsent), (mp_obj_t)&esp_socket_onsent_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ondisconnect), (mp_obj_t)&esp_socket_ondisconnect_obj },
};
STATIC MP_DEFINE_CONST_DICT(esp_socket_locals_dict, esp_socket_locals_dict_table);
STATIC const mp_obj_type_t esp_socket_type = {
{ &mp_type_type },
.name = MP_QSTR_socket,
.make_new = esp_socket_make_new,
.locals_dict = (mp_obj_t)&esp_socket_locals_dict,
};
#define MODESP_INCLUDE_CONSTANTS (1)
static void error_check(bool status, const char *msg) {
if (!status) {
@@ -47,16 +489,6 @@ static void error_check(bool status, const char *msg) {
}
}
mp_obj_t call_function_1_protected(mp_obj_t fun, mp_obj_t arg) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
return mp_call_function_1(fun, arg);
} else {
mp_obj_print_exception(printf_wrapper, NULL, (mp_obj_t)nlr.ret_val);
return (mp_obj_t)nlr.ret_val;
}
}
STATIC void esp_scan_cb(scaninfo *si, STATUS status) {
//printf("in pyb_scan_cb: %d, si=%p, si->pbss=%p\n", status, si, si->pbss);
struct bss_info *bs;
@@ -69,13 +501,13 @@ STATIC void esp_scan_cb(scaninfo *si, STATUS status) {
t->items[3] = MP_OBJ_NEW_SMALL_INT(bs->rssi);
t->items[4] = MP_OBJ_NEW_SMALL_INT(bs->authmode);
t->items[5] = MP_OBJ_NEW_SMALL_INT(bs->is_hidden);
call_function_1_protected(scan_cb_obj, t);
call_function_1_protected(MP_STATE_PORT(scan_cb_obj), t);
}
}
}
STATIC mp_obj_t esp_scan(mp_obj_t cb_in) {
scan_cb_obj = cb_in;
MP_STATE_PORT(scan_cb_obj) = cb_in;
wifi_set_opmode(STATION_MODE);
wifi_station_scan(NULL, (scan_done_cb_t)esp_scan_cb);
return mp_const_none;
@@ -117,6 +549,23 @@ STATIC const mp_map_elem_t esp_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_disconnect), (mp_obj_t)&esp_disconnect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&esp_scan_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_status), (mp_obj_t)&esp_status_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_getaddrinfo_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&esp_socket_type },
#if MODESP_INCLUDE_CONSTANTS
{ MP_OBJ_NEW_QSTR(MP_QSTR_STAT_IDLE),
MP_OBJ_NEW_SMALL_INT(STATION_IDLE)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_STAT_CONNECTING),
MP_OBJ_NEW_SMALL_INT(STATION_CONNECTING)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_STAT_WRONG_PASSWORD),
MP_OBJ_NEW_SMALL_INT(STATION_WRONG_PASSWORD)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_STAT_NO_AP_FOUND),
MP_OBJ_NEW_SMALL_INT(STATION_NO_AP_FOUND)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_STAT_CONNECT_FAIL),
MP_OBJ_NEW_SMALL_INT(STATION_CONNECT_FAIL)},
{ MP_OBJ_NEW_QSTR(MP_QSTR_STAT_GOT_IP),
MP_OBJ_NEW_SMALL_INT(STATION_GOT_IP)},
#endif
};
STATIC MP_DEFINE_CONST_DICT(esp_module_globals, esp_module_globals_table);

View File

@@ -81,7 +81,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj, 0, 1, pyb_info);
STATIC mp_obj_t pyb_freq(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
// get
return mp_obj_new_int(mp_hal_get_cpu_freq());
return mp_obj_new_int(mp_hal_get_cpu_freq() * 1000000);
} else {
// set
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "can't change freq"));
@@ -108,13 +108,13 @@ STATIC mp_obj_t pyb_elapsed_millis(mp_obj_t start) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_millis_obj, pyb_elapsed_millis);
STATIC mp_obj_t pyb_micros(void) {
return MP_OBJ_NEW_SMALL_INT(0);
return MP_OBJ_NEW_SMALL_INT(system_get_time());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_micros_obj, pyb_micros);
STATIC mp_obj_t pyb_elapsed_micros(mp_obj_t start) {
uint32_t startMicros = mp_obj_get_int(start);
uint32_t currMicros = 0;
uint32_t currMicros = system_get_time();
return MP_OBJ_NEW_SMALL_INT((currMicros - startMicros) & 0x3fffffff);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_micros_obj, pyb_elapsed_micros);
@@ -159,6 +159,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_hard_reset), (mp_obj_t)&pyb_hard_reset_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pyb_pin_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RTC), (mp_obj_t)&pyb_rtc_obj },
};
STATIC MP_DEFINE_CONST_DICT(pyb_module_globals, pyb_module_globals_table);

View File

@@ -1 +1,2 @@
extern const mp_obj_type_t pyb_pin_type;
extern const mp_obj_base_t pyb_rtc_obj;

View File

@@ -65,11 +65,11 @@ STATIC const pyb_pin_obj_t pyb_pin_obj[] = {
{{&pyb_pin_type}, 15, 15, PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15},
};
STATIC void pyb_pin_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
STATIC void pyb_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_pin_obj_t *self = self_in;
// pin name
print(env, "Pin(%u)", self->pin_id);
mp_printf(print, "Pin(%u)", self->pin_id);
}
// pin.init(mode, pull=Pin.PULL_NONE, af=-1)

167
esp8266/modpybrtc.c Normal file
View File

@@ -0,0 +1,167 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2015 Josef Gajdusek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include "py/nlr.h"
#include "py/obj.h"
#include "py/runtime.h"
#include MICROPY_HAL_H
#include "timeutils.h"
#include "user_interface.h"
typedef struct _pyb_rtc_obj_t {
mp_obj_base_t base;
} pyb_rtc_obj_t;
#define MEM_MAGIC 0x75507921
#define MEM_DELTA_ADDR 64
#define MEM_CAL_ADDR (MEM_DELTA_ADDR + 2)
#define MEM_USER_MAGIC_ADDR (MEM_CAL_ADDR + 1)
#define MEM_USER_LEN_ADDR (MEM_USER_MAGIC_ADDR + 1)
#define MEM_USER_DATA_ADDR (MEM_USER_LEN_ADDR + 1)
#define MEM_USER_MAXLEN (512 - (MEM_USER_DATA_ADDR - MEM_DELTA_ADDR) * 4)
STATIC uint64_t pyb_rtc_raw_us(uint64_t cal) {
return system_get_rtc_time() * ((cal >> 12) * 1000 + (cal & 0xfff) / 4) / 1000;
};
void pyb_rtc_set_us_since_2000(uint64_t nowus) {
uint32_t cal = system_rtc_clock_cali_proc();
int64_t delta = nowus - pyb_rtc_raw_us(cal);
// As the calibration value jitters quite a bit, to make the
// clock at least somewhat practially usable, we need to store it
system_rtc_mem_write(MEM_CAL_ADDR, &cal, sizeof(cal));
system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta));
};
uint64_t pyb_rtc_get_us_since_2000() {
uint32_t cal;
int64_t delta;
system_rtc_mem_read(MEM_CAL_ADDR, &cal, sizeof(cal));
system_rtc_mem_read(MEM_DELTA_ADDR, &delta, sizeof(delta));
return pyb_rtc_raw_us(cal) + delta;
};
STATIC mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 1) {
// Get time
uint64_t msecs = pyb_rtc_get_us_since_2000() / 1000;
timeutils_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(msecs / 1000, &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(msecs % 1000)
};
return mp_obj_new_tuple(8, tuple);
} else {
// Set time
mp_obj_t *items;
mp_obj_get_array_fixed_n(args[1], 8, &items);
pyb_rtc_set_us_since_2000(
((uint64_t)timeutils_seconds_since_2000(
mp_obj_get_int(items[0]),
mp_obj_get_int(items[1]),
mp_obj_get_int(items[2]),
mp_obj_get_int(items[4]),
mp_obj_get_int(items[5]),
mp_obj_get_int(items[6])) * 1000 + mp_obj_get_int(items[7])) * 1000);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_datetime);
STATIC mp_obj_t pyb_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) {
uint8_t rtcram[MEM_USER_MAXLEN];
uint32_t len;
uint32_t magic;
if (n_args == 1) {
system_rtc_mem_read(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic));
if (magic != MEM_MAGIC) {
return mp_const_none;
}
system_rtc_mem_read(MEM_USER_LEN_ADDR, &len, sizeof(len));
system_rtc_mem_read(MEM_USER_DATA_ADDR, rtcram, len + (4 - len % 4));
return mp_obj_new_bytes(rtcram, len);
} else {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
if (bufinfo.len > MEM_USER_MAXLEN) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"buffer too long"));
}
magic = MEM_MAGIC;
system_rtc_mem_write(MEM_USER_MAGIC_ADDR, &magic, sizeof(len));
len = bufinfo.len;
system_rtc_mem_write(MEM_USER_LEN_ADDR, &len, sizeof(len));
int i = 0;
for (; i < bufinfo.len; i++) {
rtcram[i] = ((uint8_t *)bufinfo.buf)[i];
}
system_rtc_mem_write(MEM_USER_DATA_ADDR, rtcram, len + (4 - len % 4));
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_memory_obj, 1, 2, pyb_rtc_memory);
STATIC const mp_map_elem_t pyb_rtc_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_datetime), (mp_obj_t)&pyb_rtc_datetime_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_memory), (mp_obj_t)&pyb_rtc_memory_obj },
};
STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
STATIC const mp_obj_type_t pyb_rtc_type = {
{ &mp_type_type },
.name = MP_QSTR_RTC,
.locals_dict = (mp_obj_t)&pyb_rtc_locals_dict,
};
const mp_obj_base_t pyb_rtc_obj = {&pyb_rtc_type};

29
esp8266/modpybrtc.h Normal file
View File

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

132
esp8266/modutime.c Normal file
View File

@@ -0,0 +1,132 @@
/*
* 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 Josef Gajdusek
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <string.h>
#include "py/nlr.h"
#include "py/obj.h"
#include "py/gc.h"
#include "py/runtime.h"
#include MICROPY_HAL_H
#include "modpyb.h"
#include "modpybrtc.h"
#include "timeutils.h"
#include "user_interface.h"
/// \module time - time related functions
///
/// The `time` module provides functions for getting the current time and date,
/// and for sleeping.
/// \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)
/// month is 1-12
/// mday is 1-31
/// hour is 0-23
/// minute is 0-59
/// second is 0-59
/// weekday is 0-6 for Mon-Sun.
/// yearday is 1-366
STATIC mp_obj_t time_localtime(mp_uint_t n_args, const mp_obj_t *args) {
timeutils_struct_time_t tm;
mp_int_t seconds;
if (n_args == 0 || args[0] == mp_const_none) {
seconds = pyb_rtc_get_us_since_2000() / 1000 / 1000;
} else {
seconds = mp_obj_get_int(args[0]);
}
timeutils_seconds_since_2000_to_struct_time(seconds, &tm);
mp_obj_t tuple[8] = {
tuple[0] = mp_obj_new_int(tm.tm_year),
tuple[1] = mp_obj_new_int(tm.tm_mon),
tuple[2] = mp_obj_new_int(tm.tm_mday),
tuple[3] = mp_obj_new_int(tm.tm_hour),
tuple[4] = mp_obj_new_int(tm.tm_min),
tuple[5] = mp_obj_new_int(tm.tm_sec),
tuple[6] = mp_obj_new_int(tm.tm_wday),
tuple[7] = mp_obj_new_int(tm.tm_yday),
};
return mp_obj_new_tuple(8, tuple);
}
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;
mp_obj_get_array(tuple, &len, &elem);
// localtime generates a tuple of len 8. CPython uses 9, so we accept both.
if (len < 8 || len > 9) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "mktime needs a tuple of length 8 or 9 (%d given)", len));
}
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);
/// \function sleep(seconds)
/// Sleep for the given number of seconds.
STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
HAL_Delay(1000 * mp_obj_get_int(seconds_o));
return mp_const_none;
}
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) {
// get date and time
return mp_obj_new_int(pyb_rtc_get_us_since_2000() / 1000 / 1000);
}
MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);
STATIC const mp_map_elem_t time_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_utime) },
{ 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 },
};
STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table);
const mp_obj_module_t utime_module = {
.base = { &mp_type_module },
.name = MP_QSTR_utime,
.globals = (mp_obj_dict_t*)&time_module_globals,
};

View File

@@ -14,6 +14,7 @@
#define MICROPY_HELPER_REPL (1)
#define MICROPY_HELPER_LEXER_UNIX (0)
#define MICROPY_ENABLE_SOURCE_LINE (1)
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
@@ -36,6 +37,7 @@
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
#define MICROPY_MODULE_FROZEN (1)
// type definitions for the specific machine
@@ -52,6 +54,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;
void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len);
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
// extra built in names to add to the global namespace
extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
#define MICROPY_PORT_BUILTINS \
@@ -60,15 +65,24 @@ extern const struct _mp_obj_fun_builtin_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 esp_module;
extern const struct _mp_obj_module_t utime_module;
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&utime_module }, \
#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&utime_module }, \
#define MP_STATE_PORT MP_STATE_VM
#define MICROPY_PORT_ROOT_POINTERS \
const char *readline_hist[8];
const char *readline_hist[8]; \
\
/* Singleton instance of scan callback, meaning that there can
be only one concurrent AP scan. */ \
mp_obj_t scan_cb_obj; \
// We need to provide a declaration/definition of alloca()
#include <alloca.h>

View File

@@ -42,10 +42,34 @@ Q(sync)
Q(hard_reset)
Q(esp)
Q(socket)
Q(connect)
Q(disconnect)
Q(scan)
Q(status)
Q(getaddrinfo)
Q(send)
Q(sendto)
Q(recv)
Q(recvfrom)
Q(listen)
Q(accept)
Q(bind)
Q(settimeout)
Q(setblocking)
Q(setsockopt)
Q(close)
Q(protocol)
Q(onconnect)
Q(onrecv)
Q(onsent)
Q(ondisconnect)
Q(STAT_IDLE)
Q(STAT_CONNECTING)
Q(STAT_WRONG_PASSWORD)
Q(STAT_NO_AP_FOUND)
Q(STAT_CONNECT_FAIL)
Q(STAT_GOT_IP)
// Pin class
Q(Pin)
@@ -61,3 +85,15 @@ Q(OUT_OD)
Q(PULL_NONE)
Q(PULL_UP)
Q(PULL_DOWN)
// RTC
Q(RTC)
Q(datetime)
Q(memory)
// utime
Q(utime)
Q(localtime)
Q(mktime)
Q(sleep)
Q(time)

1
esp8266/scripts/main.py Normal file
View File

@@ -0,0 +1 @@
# This script is run on boot

View File

@@ -112,13 +112,13 @@ void uart_tx_one_char(uint8 uart, uint8 TxChar) {
* Returns : NONE
*******************************************************************************/
static void ICACHE_FLASH_ATTR
uart1_write_char(char c) {
uart_os_write_char(char c) {
if (c == '\n') {
uart_tx_one_char(UART1, '\r');
uart_tx_one_char(UART1, '\n');
uart_tx_one_char(UART_OS, '\r');
uart_tx_one_char(UART_OS, '\n');
} else if (c == '\r') {
} else {
uart_tx_one_char(UART1, c);
uart_tx_one_char(UART_OS, c);
}
}
@@ -191,7 +191,7 @@ void ICACHE_FLASH_ATTR uart_init(UartBautRate uart0_br, UartBautRate uart1_br) {
ETS_UART_INTR_ENABLE();
// install uart1 putc callback
os_install_putc1((void *)uart1_write_char);
os_install_putc1((void *)uart_os_write_char);
}
void ICACHE_FLASH_ATTR uart_reattach() {
@@ -200,10 +200,16 @@ void ICACHE_FLASH_ATTR uart_reattach() {
// Task-based UART interface
int pyexec_friendly_repl_process_char(int c);
#include "py/obj.h"
#include "stmhal/pyexec.h"
void soft_reset(void);
void uart_task_handler(os_event_t *evt) {
pyexec_friendly_repl_process_char(evt->par);
int ret = pyexec_event_repl_process_char(evt->par);
if (ret & PYEXEC_FORCED_EXIT) {
soft_reset();
}
}
void uart_task_init() {

50
esp8266/utils.c Normal file
View File

@@ -0,0 +1,50 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2015 Josef Gajdusek
* Copyright (c) 2015 Paul Sokolovsky
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#include "py/obj.h"
#include "py/nlr.h"
mp_obj_t call_function_1_protected(mp_obj_t fun, mp_obj_t arg) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
return mp_call_function_1(fun, arg);
} else {
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
return (mp_obj_t)nlr.ret_val;
}
}
mp_obj_t call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
return mp_call_function_2(fun, arg1, arg2);
} else {
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
return (mp_obj_t)nlr.ret_val;
}
}

29
esp8266/utils.h Normal file
View File

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

118
extmod/modmachine.c Normal file
View File

@@ -0,0 +1,118 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include <stdint.h>
#include "py/nlr.h"
#include "py/obj.h"
#if MICROPY_PY_MACHINE
STATIC mp_uint_t get_read_addr(mp_obj_t addr_o, uint align) {
mp_uint_t addr = mp_obj_int_get_truncated(addr_o);
if ((addr & (align - 1)) != 0) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "address %08x is not aligned to %d bytes", addr, align));
}
return addr;
}
STATIC mp_uint_t get_write_addr(mp_obj_t addr_o, uint align) {
mp_uint_t addr = mp_obj_int_get_truncated(addr_o);
if ((addr & (align - 1)) != 0) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "address %08x is not aligned to %d bytes", addr, align));
}
return addr;
}
typedef struct _machine_mem_obj_t {
mp_obj_base_t base;
unsigned elem_size; // in bytes
} machine_mem_obj_t;
STATIC void machine_mem_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
machine_mem_obj_t *self = self_in;
mp_printf(print, "<%u-bit memory>", 8 * self->elem_size);
}
STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
// TODO support slice index to read/write multiple values at once
machine_mem_obj_t *self = self_in;
if (value == MP_OBJ_NULL) {
// delete
return MP_OBJ_NULL; // op not supported
} else if (value == MP_OBJ_SENTINEL) {
// load
mp_uint_t addr = get_read_addr(index, self->elem_size);
uint32_t val;
switch (self->elem_size) {
case 1: val = (*(uint8_t*)addr); break;
case 2: val = (*(uint16_t*)addr); break;
default: val = (*(uint32_t*)addr); break;
}
return mp_obj_new_int(val);
} else {
// store
mp_uint_t addr = get_write_addr(index, self->elem_size);
uint32_t val = mp_obj_get_int(value);
switch (self->elem_size) {
case 1: (*(uint8_t*)addr) = val; break;
case 2: (*(uint16_t*)addr) = val; break;
default: (*(uint32_t*)addr) = val; break;
}
return mp_const_none;
}
}
STATIC const mp_obj_type_t machine_mem_type = {
{ &mp_type_type },
.name = MP_QSTR_mem,
.print = machine_mem_print,
.subscr = machine_mem_subscr,
};
STATIC const machine_mem_obj_t machine_mem8_obj = {{&machine_mem_type}, 1};
STATIC const machine_mem_obj_t machine_mem16_obj = {{&machine_mem_type}, 2};
STATIC const machine_mem_obj_t machine_mem32_obj = {{&machine_mem_type}, 4};
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_mem8), (mp_obj_t)&machine_mem8_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem16), (mp_obj_t)&machine_mem16_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem32), (mp_obj_t)&machine_mem32_obj },
};
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
const mp_obj_module_t mp_module_machine = {
.base = { &mp_type_module },
.name = MP_QSTR_machine,
.globals = (mp_obj_dict_t*)&machine_module_globals,
};
#endif // MICROPY_PY_MACHINE

View File

@@ -137,7 +137,7 @@ STATIC mp_obj_t uctypes_struct_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_u
return o;
}
STATIC void uctypes_struct_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
STATIC void uctypes_struct_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_uctypes_struct_t *self = self_in;
const char *typen = "unk";
@@ -154,7 +154,7 @@ STATIC void uctypes_struct_print(void (*print)(void *env, const char *fmt, ...),
} else {
typen = "ERROR";
}
print(env, "<struct %s %p>", typen, self->addr);
mp_printf(print, "<struct %s %p>", typen, self->addr);
}
// Get size of any type descriptor
@@ -482,13 +482,17 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
return MP_OBJ_NULL;
}
STATIC void uctypes_struct_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
mp_obj_t val = uctypes_struct_attr_op(self_in, attr, MP_OBJ_NULL);
*dest = val;
}
STATIC bool uctypes_struct_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t val) {
return uctypes_struct_attr_op(self_in, attr, val) != MP_OBJ_NULL;
STATIC void uctypes_struct_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
if (dest[0] == MP_OBJ_NULL) {
// load attribute
mp_obj_t val = uctypes_struct_attr_op(self_in, attr, MP_OBJ_NULL);
dest[0] = val;
} else {
// delete/store attribute
if (uctypes_struct_attr_op(self_in, attr, dest[1]) != MP_OBJ_NULL) {
dest[0] = MP_OBJ_NULL; // indicate success
}
}
}
STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
@@ -589,8 +593,7 @@ STATIC const mp_obj_type_t uctypes_struct_type = {
.name = MP_QSTR_struct,
.print = uctypes_struct_print,
.make_new = uctypes_struct_make_new,
.load_attr = uctypes_struct_load_attr,
.store_attr = uctypes_struct_store_attr,
.attr = uctypes_struct_attr,
.subscr = uctypes_struct_subscr,
};

View File

@@ -35,8 +35,9 @@
STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) {
vstr_t vstr;
vstr_init(&vstr, 8);
mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))vstr_printf, &vstr, obj, PRINT_JSON);
mp_print_t print;
vstr_init_print(&vstr, 8, &print);
mp_obj_print_helper(&print, obj, PRINT_JSON);
return mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps);

View File

@@ -51,15 +51,15 @@ typedef struct _mp_obj_match_t {
} mp_obj_match_t;
STATIC void match_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
STATIC void match_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_match_t *self = self_in;
print(env, "<match num=%d>", self->num_matches);
mp_printf(print, "<match num=%d>", self->num_matches);
}
STATIC mp_obj_t match_group(mp_obj_t self_in, mp_obj_t no_in) {
mp_obj_match_t *self = self_in;
mp_int_t no = mp_obj_int_get_truncated(no_in);
mp_int_t no = mp_obj_get_int(no_in);
if (no < 0 || no >= self->num_matches) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_IndexError, no_in));
}
@@ -86,10 +86,10 @@ STATIC const mp_obj_type_t match_type = {
.locals_dict = (mp_obj_t)&match_locals_dict,
};
STATIC void re_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_re_t *self = self_in;
print(env, "<re %p>", self);
mp_printf(print, "<re %p>", self);
}
STATIC mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
@@ -135,7 +135,7 @@ STATIC mp_obj_t re_split(uint n_args, const mp_obj_t *args) {
int maxsplit = 0;
if (n_args > 2) {
maxsplit = mp_obj_int_get_truncated(args[2]);
maxsplit = mp_obj_get_int(args[2]);
}
mp_obj_t retval = mp_obj_new_list(0, NULL);

View File

@@ -1,163 +1,21 @@
FatFs Module Source Files R0.10c (C)ChaN, 2014
FatFs Module Source Files R0.11
FILES
ffconf.h Configuration file for FatFs module.
ff.h Common include file for FatFs and application module.
ff.c FatFs module.
diskio.h Common include file for FatFs and disk I/O module.
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
integer.h Integer type definitions for FatFs.
option Optional external functions.
00readme.txt This file.
history.txt Revision history.
ffconf.h Configuration file for FatFs module.
ff.h Common include file for FatFs and application module.
ff.c FatFs module.
diskio.h Common include file for FatFs and disk I/O module.
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
integer.h Integer type definitions for FatFs.
option Optional external functions.
Low level disk I/O module is not included in this archive because the FatFs
module is only a generic file system layer and not depend on any specific
storage device. You have to provide a low level disk I/O module that written
to control your storage device.
to control the target storage device.
AGREEMENTS
FatFs module is an open source software to implement FAT file system to
small embedded systems. This is a free software and is opened for education,
research and commercial developments under license policy of following trems.
Copyright (C) 2014, ChaN, all right reserved.
* The FatFs module is a free software and there is NO WARRANTY.
* No restriction on use. You can use, modify and redistribute it for
personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
* Redistributions of source code must retain the above copyright notice.
REVISION HISTORY
Feb 26, 2006 R0.00 Prototype
Apr 29, 2006 R0.01 First release.
Jun 01, 2006 R0.02 Added FAT12.
Removed unbuffered mode.
Fixed a problem on small (<32M) patition.
Jun 10, 2006 R0.02a Added a configuration option _FS_MINIMUM.
Sep 22, 2006 R0.03 Added f_rename.
Changed option _FS_MINIMUM to _FS_MINIMIZE.
Dec 11, 2006 R0.03a Improved cluster scan algolithm to write files fast.
Fixed f_mkdir creates incorrect directory on FAT32.
Feb 04, 2007 R0.04 Supported multiple drive system. (FatFs)
Changed some APIs for multiple drive system.
Added f_mkfs. (FatFs)
Added _USE_FAT32 option. (Tiny-FatFs)
Apr 01, 2007 R0.04a Supported multiple partitions on a plysical drive. (FatFs)
Fixed an endian sensitive code in f_mkfs. (FatFs)
Added a capability of extending the file size to f_lseek.
Added minimization level 3.
Fixed a problem that can collapse a sector when recreate an
existing file in any sub-directory at non FAT32 cfg. (Tiny-FatFs)
May 05, 2007 R0.04b Added _USE_NTFLAG option.
Added FSInfo support.
Fixed some problems corresponds to FAT32. (Tiny-FatFs)
Fixed DBCS name can result FR_INVALID_NAME.
Fixed short seek (0 < ofs <= csize) collapses the file object.
Aug 25, 2007 R0.05 Changed arguments of f_read, f_write.
Changed arguments of f_mkfs. (FatFs)
Fixed f_mkfs on FAT32 creates incorrect FSInfo. (FatFs)
Fixed f_mkdir on FAT32 creates incorrect directory. (FatFs)
Feb 03, 2008 R0.05a Added f_truncate().
Added f_utime().
Fixed off by one error at FAT sub-type determination.
Fixed btr in f_read() can be mistruncated.
Fixed cached sector is not flushed when create and close without write.
Apr 01, 2008 R0.06 Added f_forward(). (Tiny-FatFs)
Added string functions: fputc(), fputs(), fprintf() and fgets().
Improved performance of f_lseek() on move to the same or following cluster.
Apr 01, 2009, R0.07 Merged Tiny-FatFs as a buffer configuration option.
Added long file name support.
Added multiple code page support.
Added re-entrancy for multitask operation.
Added auto cluster size selection to f_mkfs().
Added rewind option to f_readdir().
Changed result code of critical errors.
Renamed string functions to avoid name collision.
Apr 14, 2009, R0.07a Separated out OS dependent code on reentrant cfg.
Added multiple sector size support.
Jun 21, 2009, R0.07c Fixed f_unlink() may return FR_OK on error.
Fixed wrong cache control in f_lseek().
Added relative path feature.
Added f_chdir().
Added f_chdrive().
Added proper case conversion for extended characters.
Nov 03, 2009 R0.07e Separated out configuration options from ff.h to ffconf.h.
Added a configuration option, _LFN_UNICODE.
Fixed f_unlink() fails to remove a sub-dir on _FS_RPATH.
Fixed name matching error on the 13 char boundary.
Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
May 15, 2010, R0.08 Added a memory configuration option. (_USE_LFN)
Added file lock feature. (_FS_SHARE)
Added fast seek feature. (_USE_FASTSEEK)
Changed some types on the API, XCHAR->TCHAR.
Changed fname member in the FILINFO structure on Unicode cfg.
String functions support UTF-8 encoding files on Unicode cfg.
Aug 16,'10 R0.08a Added f_getcwd(). (_FS_RPATH = 2)
Added sector erase feature. (_USE_ERASE)
Moved file lock semaphore table from fs object to the bss.
Fixed a wrong directory entry is created on non-LFN cfg when the given name contains ';'.
Fixed f_mkfs() creates wrong FAT32 volume.
Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write().
f_lseek() reports required table size on creating CLMP.
Extended format syntax of f_printf function.
Ignores duplicated directory separators in given path names.
Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature.
Added f_fdisk(). (_MULTI_PARTITION = 2)
Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16.
Changed f_open() and f_opendir() reject null object pointer to avoid crash.
Changed option name _FS_SHARE to _FS_LOCK.
Jan 23,'13 R0.09b Added f_getlabel() and f_setlabel(). (_USE_LABEL)
Oct 02,'13 R0.10 Added selection of character encoding on the file. (_STRF_ENCODE)
Added f_closedir().
Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO)
Added forced mount feature with changes of f_mount().
Improved behavior of volume auto detection.
Improved write throughput of f_puts() and f_printf().
Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write().
Fixed f_write() can be truncated when the file size is close to 4GB.
Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect error code.
Jan 15,'14 R0.10a Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID)
Added a configuration option of minimum sector size. (_MIN_SS)
2nd argument of f_rename() can have a drive number and it will be ignored.
Fixed f_mount() with forced mount fails when drive number is >= 1.
Fixed f_close() invalidates the file object without volume lock.
Fixed f_closedir() returns but the volume lock is left acquired.
Fixed creation of an entry with LFN fails on too many SFN collisions.
Mar 19,'14 R0.10b Fixed a hard error in the disk I/O layer can collapse the directory entry.
Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN.
Nov 09,'14 R0.10c Added a configuration option for the platforms without RTC. (_FS_NORTC)
Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel().
Fixed a potential problem of FAT access that can appear on disk error.
Fixed null pointer dereference on attempting to delete the root direcotry.

View File

@@ -8,14 +8,14 @@
/*-----------------------------------------------------------------------*/
#include "diskio.h" /* FatFs lower layer API */
#include "usbdisk.h" /* Example: USB drive control */
#include "atadrive.h" /* Example: ATA drive control */
#include "sdcard.h" /* Example: MMC/SDC contorl */
#include "usbdisk.h" /* Example: Header file of existing USB MSD control module */
#include "atadrive.h" /* Example: Header file of existing ATA harddisk control module */
#include "sdcard.h" /* Example: Header file of existing MMC/SDC contorl module */
/* Definitions of physical drive number for each drive */
#define ATA 0 /* Example: Map ATA drive to drive number 0 */
#define MMC 1 /* Example: Map MMC/SD card to drive number 1 */
#define USB 2 /* Example: Map USB drive to drive number 2 */
#define ATA 0 /* Example: Map ATA harddisk to physical drive 0 */
#define MMC 1 /* Example: Map MMC/SD card to physical drive 1 */
#define USB 2 /* Example: Map USB MSD to physical drive 2 */
/*-----------------------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +1,23 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module include file R0.10c (C)ChaN, 2014
/ FatFs - FAT file system module include R0.11 (C)ChaN, 2015
/----------------------------------------------------------------------------/
/ FatFs module is a generic FAT file system module for small embedded systems.
/ This is a free software that opened for education, research and commercial
/ developments under license policy of following terms.
/ FatFs module is a free software that opened under license policy of
/ following conditions.
/
/ Copyright (C) 2014, ChaN, all right reserved.
/ Copyright (C) 2015, ChaN, all right reserved.
/
/ * The FatFs module is a free software and there is NO WARRANTY.
/ * No restriction on use. You can use, modify and redistribute it for
/ personal, non-profit or commercial product UNDER YOUR RESPONSIBILITY.
/ * Redistributions of source code must retain the above copyright notice.
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/----------------------------------------------------------------------------*/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/---------------------------------------------------------------------------*/
#ifndef _FATFS
#define _FATFS 80376 /* Revision ID */
#define _FATFS 32020 /* Revision ID */
#ifdef __cplusplus
extern "C" {
@@ -36,6 +38,7 @@ typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
// dpgeorge: make the partition config table const
extern const PARTITION VolToPart[]; /* Volume - Partition resolution table */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
@@ -154,11 +157,14 @@ typedef struct {
WCHAR* lfn; /* Pointer to the LFN working buffer */
WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
#endif
#if _USE_FIND
const TCHAR* pat; /* Pointer to the name matching pattern */
#endif
} DIR;
/* File status structure (FILINFO) */
/* File information structure (FILINFO) */
typedef struct {
DWORD fsize; /* File size */
@@ -215,11 +221,13 @@ FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
FRESULT f_closedir (DIR* dp); /* Close an open directory */
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
FRESULT f_chmod (const TCHAR* path, BYTE value, BYTE mask); /* Change attribute of the file/dir */
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of the file/dir */
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp of the file/dir */
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
@@ -239,6 +247,8 @@ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the fil
#define f_error(fp) ((fp)->err)
#define f_tell(fp) ((fp)->fptr)
#define f_size(fp) ((fp)->fsize)
#define f_rewind(fp) f_lseek((fp), 0)
#define f_rewinddir(dp) f_readdir((dp), 0)
#ifndef EOF
#define EOF (-1)

View File

@@ -1,8 +1,8 @@
/*---------------------------------------------------------------------------/
/ FatFs - FAT file system module configuration file R0.10c (C)ChaN, 2014
/ FatFs - FAT file system module configuration file R0.11 (C)ChaN, 2015
/---------------------------------------------------------------------------*/
#define _FFCONF 80376 /* Revision ID */
#define _FFCONF 32020 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Functions and Buffer Configurations
@@ -18,13 +18,13 @@
#define _FS_READONLY 0
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/ Read-only configuration removes basic writing API functions, f_write(),
/ f_sync(), f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(),
/ f_getfree() and optional writing functions as well. */
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/ and optional writing functions as well. */
#define _FS_MINIMIZE 0
/* This option defines minimization level to remove some API functions.
/* This option defines minimization level to remove some basic API functions.
/
/ 0: All basic functions are enabled.
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(),
@@ -42,9 +42,13 @@
/ 2: Enable with LF-CRLF conversion. */
#define _USE_FIND 0
/* This option switches filtered directory read feature and related functions,
/ f_findfirst() and f_findnext(). (0:Disable or 1:Enable) */
#define _USE_MKFS 0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable)
/ To enable it, also _FS_READONLY need to be set to 0. */
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
#define _USE_FASTSEEK 0
@@ -57,8 +61,8 @@
#define _USE_FORWARD 0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/* To enable it, also _FS_TINY need to be set to 1. */
/* This option switches f_forward() function. (0:Disable or 1:Enable)
/ To enable it, also _FS_TINY need to be set to 1. */
/*---------------------------------------------------------------------------/
@@ -69,32 +73,24 @@
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect setting of the code page can cause a file open failure.
/
/ 932 - Japanese Shift_JIS (DBCS, OEM, Windows)
/ 936 - Simplified Chinese GBK (DBCS, OEM, Windows)
/ 949 - Korean (DBCS, OEM, Windows)
/ 950 - Traditional Chinese Big5 (DBCS, OEM, Windows)
/ 1250 - Central Europe (Windows)
/ 1251 - Cyrillic (Windows)
/ 1252 - Latin 1 (Windows)
/ 1253 - Greek (Windows)
/ 1254 - Turkish (Windows)
/ 1255 - Hebrew (Windows)
/ 1256 - Arabic (Windows)
/ 1257 - Baltic (Windows)
/ 1258 - Vietnam (OEM, Windows)
/ 437 - U.S. (OEM)
/ 720 - Arabic (OEM)
/ 737 - Greek (OEM)
/ 775 - Baltic (OEM)
/ 850 - Multilingual Latin 1 (OEM)
/ 858 - Multilingual Latin 1 + Euro (OEM)
/ 852 - Latin 2 (OEM)
/ 855 - Cyrillic (OEM)
/ 866 - Russian (OEM)
/ 857 - Turkish (OEM)
/ 862 - Hebrew (OEM)
/ 874 - Thai (OEM, Windows)
/ 1 - ASCII (No extended character. Valid for only non-LFN configuration.) */
/ 1 - ASCII (No extended character. Non-LFN cfg. only)
/ 437 - U.S.
/ 720 - Arabic
/ 737 - Greek
/ 775 - Baltic
/ 850 - Multilingual Latin 1
/ 852 - Latin 2
/ 855 - Cyrillic
/ 857 - Turkish
/ 858 - Multilingual Latin 1 + Euro
/ 862 - Hebrew
/ 866 - Russian
/ 874 - Thai
/ 932 - Japanese Shift_JIS (DBCS)
/ 936 - Simplified Chinese GBK (DBCS)
/ 949 - Korean (DBCS)
/ 950 - Traditional Chinese Big5 (DBCS)
*/
#define _USE_LFN 0
@@ -163,7 +159,7 @@
/ number is bound to the same physical drive number and only an FAT volume found on
/ the physical drive will be mounted. When multi-partition feature is enabled (1),
/ each logical drive number is bound to arbitrary physical drive and partition
/ listed in the VolToPart[]. Also f_fdisk() funciton will be enabled. */
/ listed in the VolToPart[]. Also f_fdisk() funciton will be available. */
#define _MIN_SS 512
@@ -200,9 +196,9 @@
/---------------------------------------------------------------------------*/
#define _FS_NORTC 0
#define _NORTC_MON 11
#define _NORTC_MDAY 9
#define _NORTC_YEAR 2014
#define _NORTC_MON 2
#define _NORTC_MDAY 1
#define _NORTC_YEAR 2015
/* The _FS_NORTC option switches timestamp feature. If the system does not have
/ an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to disable
/ the timestamp feature. All objects modified by FatFs will have a fixed timestamp

180
lib/fatfs/history.txt Normal file
View File

@@ -0,0 +1,180 @@
----------------------------------------------------------------------------
Revision history of FatFs module
----------------------------------------------------------------------------
R0.00 (February 26, 2006)
Prototype.
R0.01 (April 29, 2006)
First stable version.
R0.02 (June 01, 2006)
Added FAT12 support.
Removed unbuffered mode.
Fixed a problem on small (<32M) partition.
R0.02a (June 10, 2006)
Added a configuration option (_FS_MINIMUM).
R0.03 (September 22, 2006)
Added f_rename().
Changed option _FS_MINIMUM to _FS_MINIMIZE.
R0.03a (December 11, 2006)
Improved cluster scan algorithm to write files fast.
Fixed f_mkdir() creates incorrect directory on FAT32.
R0.04 (February 04, 2007)
Added f_mkfs().
Supported multiple drive system.
Changed some interfaces for multiple drive system.
Changed f_mountdrv() to f_mount().
R0.04a (April 01, 2007)
Supported multiple partitions on a physical drive.
Added a capability of extending file size to f_lseek().
Added minimization level 3.
Fixed an endian sensitive code in f_mkfs().
R0.04b (May 05, 2007)
Added a configuration option _USE_NTFLAG.
Added FSINFO support.
Fixed DBCS name can result FR_INVALID_NAME.
Fixed short seek (<= csize) collapses the file object.
R0.05 (August 25, 2007)
Changed arguments of f_read(), f_write() and f_mkfs().
Fixed f_mkfs() on FAT32 creates incorrect FSINFO.
Fixed f_mkdir() on FAT32 creates incorrect directory.
R0.05a (February 03, 2008)
Added f_truncate() and f_utime().
Fixed off by one error at FAT sub-type determination.
Fixed btr in f_read() can be mistruncated.
Fixed cached sector is not flushed when create and close without write.
R0.06 (April 01, 2008)
Added fputc(), fputs(), fprintf() and fgets().
Improved performance of f_lseek() on moving to the same or following cluster.
R0.07 (April 01, 2009)
Merged Tiny-FatFs as a configuration option. (_FS_TINY)
Added long file name feature. (_USE_LFN)
Added multiple code page feature. (_CODE_PAGE)
Added re-entrancy for multitask operation. (_FS_REENTRANT)
Added auto cluster size selection to f_mkfs().
Added rewind option to f_readdir().
Changed result code of critical errors.
Renamed string functions to avoid name collision.
R0.07a (April 14, 2009)
Septemberarated out OS dependent code on reentrant cfg.
Added multiple sector size feature.
R0.07c (June 21, 2009)
Fixed f_unlink() can return FR_OK on error.
Fixed wrong cache control in f_lseek().
Added relative path feature.
Added f_chdir() and f_chdrive().
Added proper case conversion to extended character.
R0.07e (November 03, 2009)
Septemberarated out configuration options from ff.h to ffconf.h.
Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH.
Fixed name matching error on the 13 character boundary.
Added a configuration option, _LFN_UNICODE.
Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
R0.08 (May 15, 2010)
Added a memory configuration option. (_USE_LFN = 3)
Added file lock feature. (_FS_SHARE)
Added fast seek feature. (_USE_FASTSEEK)
Changed some types on the API, XCHAR->TCHAR.
Changed .fname in the FILINFO structure on Unicode cfg.
String functions support UTF-8 encoding files on Unicode cfg.
R0.08a (August 16, 2010)
Added f_getcwd(). (_FS_RPATH = 2)
Added sector erase feature. (_USE_ERASE)
Moved file lock semaphore table from fs object to the bss.
Fixed f_mkfs() creates wrong FAT32 volume.
R0.08b (January 15, 2011)
Fast seek feature is also applied to f_read() and f_write().
f_lseek() reports required table size on creating CLMP.
Extended format syntax of f_printf().
Ignores duplicated directory separators in given path name.
R0.09 (September 06, 2011)
f_mkfs() supports multiple partition to complete the multiple partition feature.
Added f_fdisk().
R0.09a (August 27, 2012)
Changed f_open() and f_opendir() reject null object pointer to avoid crash.
Changed option name _FS_SHARE to _FS_LOCK.
Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
R0.09b (January 24, 2013)
Added f_setlabel() and f_getlabel().
R0.10 (October 02, 2013)
Added selection of character encoding on the file. (_STRF_ENCODE)
Added f_closedir().
Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO)
Added forced mount feature with changes of f_mount().
Improved behavior of volume auto detection.
Improved write throughput of f_puts() and f_printf().
Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write().
Fixed f_write() can be truncated when the file size is close to 4GB.
Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect error code.
R0.10a (January 15, 2014)
Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID)
Added a configuration option of minimum sector size. (_MIN_SS)
2nd argument of f_rename() can have a drive number and it will be ignored.
Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10)
Fixed f_close() invalidates the file object without volume lock.
Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10)
Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07)
R0.10b (May 19, 2014)
Fixed a hard error in the disk I/O layer can collapse the directory entry.
Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN. (appeared at R0.07)
R0.10c (November 09, 2014)
Added a configuration option for the platforms without RTC. (_FS_NORTC)
Changed option name _USE_ERASE to _USE_TRIM.
Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b)
Fixed a potential problem of FAT access that can appear on disk error.
Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08)
R0.11 (February 09, 2015)
Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND)
Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c)
Fixed _FS_NORTC option does not work properly. (appeared at R0.10c)

View File

@@ -529,12 +529,45 @@ WCHAR ff_wtoupper ( /* Upper converted character */
WCHAR chr /* Input character */
)
{
static const WCHAR tbl_lower[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0x0FF, 0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F, 0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F, 0x121, 0x123, 0x125, 0x127, 0x129, 0x12B, 0x12D, 0x12F, 0x131, 0x133, 0x135, 0x137, 0x13A, 0x13C, 0x13E, 0x140, 0x142, 0x144, 0x146, 0x148, 0x14B, 0x14D, 0x14F, 0x151, 0x153, 0x155, 0x157, 0x159, 0x15B, 0x15D, 0x15F, 0x161, 0x163, 0x165, 0x167, 0x169, 0x16B, 0x16D, 0x16F, 0x171, 0x173, 0x175, 0x177, 0x17A, 0x17C, 0x17E, 0x192, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x3CA, 0x430, 0x431, 0x432, 0x433, 0x434, 0x435, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x441, 0x442, 0x443, 0x444, 0x445, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x451, 0x452, 0x453, 0x454, 0x455, 0x456, 0x457, 0x458, 0x459, 0x45A, 0x45B, 0x45C, 0x45E, 0x45F, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, 0xFF58, 0xFF59, 0xFF5A, 0 };
static const WCHAR tbl_upper[] = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0x178, 0x100, 0x102, 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112, 0x114, 0x116, 0x118, 0x11A, 0x11C, 0x11E, 0x120, 0x122, 0x124, 0x126, 0x128, 0x12A, 0x12C, 0x12E, 0x130, 0x132, 0x134, 0x136, 0x139, 0x13B, 0x13D, 0x13F, 0x141, 0x143, 0x145, 0x147, 0x14A, 0x14C, 0x14E, 0x150, 0x152, 0x154, 0x156, 0x158, 0x15A, 0x15C, 0x15E, 0x160, 0x162, 0x164, 0x166, 0x168, 0x16A, 0x16C, 0x16E, 0x170, 0x172, 0x174, 0x176, 0x179, 0x17B, 0x17D, 0x191, 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3AA, 0x410, 0x411, 0x412, 0x413, 0x414, 0x415, 0x416, 0x417, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x421, 0x422, 0x423, 0x424, 0x425, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B, 0x42C, 0x42D, 0x42E, 0x42F, 0x401, 0x402, 0x403, 0x404, 0x405, 0x406, 0x407, 0x408, 0x409, 0x40A, 0x40B, 0x40C, 0x40E, 0x40F, 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, 0xFF38, 0xFF39, 0xFF3A, 0 };
int i;
// dpgeorge: here we have a space optimised version of the original routine
static const WCHAR tbl_lower[] = {
0xA1, 0x00A2, 0x00A3, 0x00A5, 0x00AC, 0x00AF,
0xFF,
0x17A, 0x17C, 0x17E, 0x192,
0, // sentinel
};
for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ;
static const WCHAR tbl_upper[] = {
0x21, 0xFFE0, 0xFFE1, 0xFFE5, 0xFFE2, 0xFFE3,
0x178,
0x179, 0x17B, 0x17D, 0x191,
};
return tbl_lower[i] ? tbl_upper[i] : chr;
if ((0x61 <= chr && chr <= 0x7a)
|| (0xe0 <= chr && chr <= 0xfe && chr != 0xf7)
|| (0x3b1 <= chr && chr <= 0x3ca && chr != 0x3c2)
|| (0x430 <= chr && chr <= 0x44f)
|| (0xff41 <= chr && chr <= 0xff5a)) {
return chr - 0x20;
}
if ((chr & 1) != 0
&& ((0x101 <= chr && chr <= 0x137)
|| (0x14b <= chr && chr <= 0x177))) {
return chr - 1;
}
if ((chr & 1) == 0 && 0x13a <= chr && chr <= 0x148) {
return chr - 1;
}
if (0x451 <= chr && chr <= 0x45f && chr != 0x45d) {
return chr - 0x50;
}
if (0x2170 <= chr && chr <= 0x217f) {
return chr - 0x10;
}
int i;
for (i = 0; tbl_lower[i] && chr != tbl_lower[i]; i++) ;
return tbl_lower[i] ? tbl_upper[i] : chr;
}

View File

@@ -10,7 +10,7 @@
#include "cc949.c"
#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
#include "cc950.c"
#else /* Small character-set */
#else /* Single Byte Character-Set */
#include "ccsbcs.c"
#endif

View File

@@ -25,7 +25,7 @@
*/
#include <stdint.h>
#include "std.h"
#include <string.h>
#define likely(x) __builtin_expect((x), 1)
@@ -102,16 +102,30 @@ void *memset(void *s, int c, size_t n) {
return s;
}
int memcmp(const char *s1, const char *s2, size_t n) {
int memcmp(const void *s1, const void *s2, size_t n) {
const uint8_t *s1_8 = s1;
const uint8_t *s2_8 = s2;
while (n--) {
char c1 = *s1++;
char c2 = *s2++;
char c1 = *s1_8++;
char c2 = *s2_8++;
if (c1 < c2) return -1;
else if (c1 > c2) return 1;
}
return 0;
}
void *memchr(const void *s, int c, size_t n) {
if (n != 0) {
const unsigned char *p = s;
do {
if (*p++ == c)
return ((void *)(p - 1));
} while (--n != 0);
}
return 0;
}
size_t strlen(const char *str) {
int len = 0;
for (const char *s = str; *s; s++) {

View File

@@ -29,6 +29,7 @@
#include <string.h>
#include "py/mpstate.h"
#include "py/repl.h"
#include "readline.h"
#ifdef MICROPY_HAL_H
#include MICROPY_HAL_H
@@ -85,6 +86,7 @@ typedef struct _readline_t {
int hist_cur;
int cursor_pos;
char escape_seq_buf[1];
const char *prompt;
} readline_t;
STATIC readline_t rl;
@@ -133,6 +135,28 @@ int readline_process_char(int c) {
redraw_step_back = 1;
redraw_from_cursor = true;
}
#if MICROPY_HELPER_REPL
} else if (c == 9) {
// tab magic
const char *compl_str;
mp_uint_t compl_len = mp_repl_autocomplete(rl.line->buf + rl.orig_line_len, rl.cursor_pos - rl.orig_line_len, &mp_plat_print, &compl_str);
if (compl_len == 0) {
// no match
} else if (compl_len == (mp_uint_t)(-1)) {
// many matches
mp_hal_stdout_tx_str(rl.prompt);
mp_hal_stdout_tx_strn(rl.line->buf + rl.orig_line_len, rl.cursor_pos - rl.orig_line_len);
redraw_from_cursor = true;
} else {
// one match
for (int i = 0; i < compl_len; ++i) {
vstr_ins_byte(rl.line, rl.cursor_pos + i, *compl_str++);
}
// set redraw parameters
redraw_from_cursor = true;
redraw_step_forward = compl_len;
}
#endif
} else if (32 <= c && c <= 126) {
// printable character
vstr_ins_char(rl.line, rl.cursor_pos, c);
@@ -260,23 +284,26 @@ end_key:
return -1;
}
void readline_note_newline(void) {
void readline_note_newline(const char *prompt) {
rl.orig_line_len = rl.line->len;
rl.cursor_pos = rl.orig_line_len;
rl.prompt = prompt;
mp_hal_stdout_tx_str(prompt);
}
void readline_init(vstr_t *line) {
void readline_init(vstr_t *line, const char *prompt) {
rl.line = line;
rl.orig_line_len = line->len;
rl.escape_seq = ESEQ_NONE;
rl.escape_seq_buf[0] = 0;
rl.hist_cur = -1;
rl.cursor_pos = rl.orig_line_len;
rl.prompt = prompt;
mp_hal_stdout_tx_str(prompt);
}
int readline(vstr_t *line, const char *prompt) {
mp_hal_stdout_tx_str(prompt);
readline_init(line);
readline_init(line, prompt);
for (;;) {
int c = mp_hal_stdin_rx_chr();
int r = readline_process_char(c);

View File

@@ -33,6 +33,6 @@
void readline_init0(void);
int readline(vstr_t *line, const char *prompt);
void readline_init(vstr_t *line);
void readline_note_newline(void);
void readline_init(vstr_t *line, const char *prompt);
void readline_note_newline(const char *prompt);
int readline_process_char(int c);

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