Compare commits

..

602 Commits
v1.4 ... v1.4.5

Author SHA1 Message Date
Damien George
032b0e9369 docs: Bump version to 1.4.5. 2015-08-11 13:42:30 +01:00
Damien George
0d5d16074f py/makeversionhdr.py: Fallback to using docs version if no git repo.
Addresses issue #1420.
2015-08-11 12:27:38 +01:00
Daniel Campora
7027fd5343 cc3200: Make ADC API compatible with the pyboard. 2015-08-10 23:42:05 +02:00
Daniel Campora
7da2fdc3cd cc3200: On the first boot, always make AP ssid='wipy-wlan'.
On the first boot don't add the MAC address, this is to speed up
factory testing.
2015-08-09 22:16:45 +02:00
Daniel Campora
2673374d18 cc3200: Refactor PRCM special user bits implementation. 2015-08-09 22:15:18 +02:00
Daniel Campora
651c870d77 cc3200: Speed up file system checking during start-up. 2015-08-09 22:09:16 +02:00
Daniel Campora
aa3569cd57 cc3200: Add factory smoke test as part of the tools. 2015-08-09 19:22:26 +02:00
Daniel Campora
8cd9fedf58 cc3200: Add script to program the WiPy via UniFlash (windows only...). 2015-08-09 19:22:23 +02:00
Daniel Campora
e23ae63970 cc3200: Fix bug in ffconf regarding '/flash' string length.
This bug was introduced when renaming '/sflash' to '/flash'.
2015-08-09 19:22:21 +02:00
Daniel Campora
31f6a6fa70 cc3200: Enable bootloader safe boot on latest firmware.
The first safe boot level executes the latest firmware but skips
'main.py' and 'boot.py'.
2015-08-09 19:22:19 +02:00
Daniel Campora
e54a4f1f48 cc3200: Improve support for WEP security.
Key is always entered as a string, but if security is WEP, the key
is converted automatically to hex before connecting or configuring
the device as an AP.
2015-08-09 19:22:16 +02:00
Daniel Campora
d43019163d docs: Add i2c keywork arguments only indication. 2015-08-09 19:22:14 +02:00
Daniel Campora
00c4d6562e cc3200: Add nic.iwconfig() to set/get WLAN configuration.
Changes are based on this post:
https://github.com/micropython/micropython/issues/876#issuecomment-115255551

The constructor can optionally take the same params of iwconfig in
order to configure WiFi when creating the object. Params are
keyworkd only. The WiPy accepts:

- mode (int -> WLAN.AP or WLAN.STA)
- ssdi (string)
- security (int -> WLAN.OPEN, WLAN.WEP, WLAN.WPA, WLAN.WPA2)
- key (string)
- channel (int (1-11))
- antenna (int -> WLAN.INTERNAL, WLAN.EXTERNAL)
2015-08-09 19:22:12 +02:00
Damien George
e86b47175f tools: Make pyboard.py Python2 compatible. 2015-08-08 13:03:08 +01:00
Tom Soulanille
20f40c3229 tests: Remove over-specification of startup banner 2015-08-08 12:37:36 +01:00
stijn
dbfba6a20e tests: Fix exceptions when running cmdline tests on windows
- subprocess.check_output can only handle strings on windows, not bytes,
  so convert the arguments as such
- the pty module is for posix systems only so skip the tests needing it
  in case it is not available
2015-08-08 12:35:27 +01:00
stijn
7ede3ec4b1 tests: Always use forward slashes for paths
This is more consistent and fixes run_micropython on windows as it uses
forward slahses to compare paths
2015-08-08 12:35:27 +01:00
Dave Hylands
872f9af6ae stmhal: Use CMSIS_MCU definition from mpconfigboard.mk
This needs to land afte #1407 lands, since #1407 is where
the CMSIS_MCU was defined.
2015-08-07 08:54:14 +01:00
Dave Hylands
8f59bacb92 stamhal: Add definitions for MCU_SERIES_F4 and MCU_SERIES_F7 2015-08-07 08:52:42 +01:00
Dave Hylands
be66a9ecf6 stmhal: Generate modstm constants per build
This causes unnecessary constants to no longer be generated.
Some constants (like UART_BRR) are different between the F4 and F7
2015-08-07 08:46:43 +01:00
Damien George
4836bcc957 stmhal/cmsis: Replace non-ascii apostrophe with ascii apostrophe. 2015-08-07 08:46:43 +01:00
Tom Soulanille
89852d38ef run-tests: Test REPL emacs keys, but only if present.
Uses cmdline/repl_emacs_check.py to check for presence of emacs keys in
repl before doing full feature test.
2015-08-06 00:03:44 +01:00
Damien George
526dd54252 tests: Add test for pyboard SPI in slave mode, recv with no master.
See PR #1414.
2015-08-05 23:47:57 +01:00
Dave Hylands
8a1a5c236d stmhal: Fix hardfault when configured as a SPI slave 2015-08-05 23:42:05 +01:00
Dave Hylands
5e11d2b349 stmhal: Enable SPI support for F7 MCUs. 2015-08-05 23:38:49 +01:00
Dave Hylands
34fe5a30c6 stmhal: Enable I2C support for F7 MCUs. 2015-08-05 23:38:24 +01:00
blmorris
26664dd180 unix/mpconfigport.h: set MICROPY_PY_SYS_PLATFORM to "darwin" if compiled on OSX
This change allows micropython to return the same value as CPython for sys.platform
2015-08-05 21:18:33 +03:00
Damien George
4434e43fa1 stmhal: Add HALCOMMITS file with list of commits that touch the hal.
This file should be kept up to date with list of hal commits.
2015-08-03 00:55:36 +01:00
Dave Hylands
7a55c1a884 stmhal: Port of f4 hal commit 1d7fb82 to f7 hal 2015-08-03 00:49:36 +01:00
Dave Hylands
28e51c9eb1 stmhal: Port of f4 hal commit 09de030 to f7 hal 2015-08-03 00:49:36 +01:00
Dave Hylands
af9d885f8c stmhal: Port of f4 hal commit c568a2b to f7 hal 2015-08-03 00:49:35 +01:00
Dave Hylands
9e8eba797e stmhal: M7 Reset clocksources changed by DFU bootloader
The DFU bootloader on the ST32F7 chip changes the clocksource
for various possible boot sources (UART1, UART3, I2C1-3).
This commit resets those clock sources back to their cold
reset values.
2015-08-03 00:46:31 +01:00
Dave Hylands
8f1eced69d stmhal: Add STM32F7 support for USB serial and storage.
USB serial is now working for F7.

Internal file storage is now working for F7.  The flash is laid out a bit
differently to the F4 - 4 x 32K, 1 x 128K with the rest 256K, so the
internal storage is 96K.

Added more pind definitions for STM32F7DISC board.  Made USART1 be the
default HWUART repl.  The STLINK usb connector also looks like a USB
serial port which is attached to USART1 on the STM32F7DISC.
2015-08-03 00:39:27 +01:00
Damien George
751485fe6b stmhal: Add support for USART1 and conditional pins in make-pins.py.
Thanks to Dave Hylands for the patch.
2015-08-03 00:23:47 +01:00
Damien George
a632037866 stmhal: Add better support for UART having Tx and Rx on different ports.
Thanks to Dave Hylands for the patch.
2015-08-03 00:22:16 +01:00
Damien George
c0e39864c6 stmhal: Fix make-pins.py to allow Port K.
Thanks to Dave Hylands for the patch.
2015-08-03 00:18:40 +01:00
Damien George
6e552e15fa stmhal: Add debug capability to print out info about a hard fault.
Capability is #if'd off by default.

Thanks to Dave Hylands for the patch.
2015-08-03 00:14:51 +01:00
Damien George
0851751615 stmhal: Factor GPIO clock enable logic into mp_hal_gpio_clock_enable.
Extracted GPIO clock enable logic into mp_hal_gpio_clock_enable
and called from anyplace which might need to use GPIO functions
on ports other than A-D.

Thanks to Dave Hylands for the patch.
2015-08-03 00:14:48 +01:00
Damien George
6f1c00869c stmhal: Factor out USRSW boot-up code and support boards with 1 LED.
Thanks to Dave Hylands for the patch.
2015-08-03 00:14:44 +01:00
Damien George
1934dca6de bare-arm: Disable enumerate and reversed builtins to make port more bare. 2015-08-02 20:55:37 +01:00
Damien George
7a26e4f484 minimal: Use 1 byte for qstr hash, to make port more minimal. 2015-08-02 20:54:58 +01:00
Damien George
9a2913ed1c py/objlist: Make list += accept all arguments and add test. 2015-08-02 20:53:54 +01:00
Daniel Campora
c6926c374d cc3200: Make I2C and SPI API the same as in stmhal. 2015-08-02 20:22:15 +02:00
Paul Sokolovsky
3a2fb201a5 makeqstrdata.py: Typo fix in comment. 2015-07-31 14:58:14 +03:00
Damien George
a95b06fc6b drivers/onewire: Fix ds18x20.read_temp so it works when no rom given. 2015-07-30 23:10:39 +01:00
Dave Hylands
92d4b51ad5 stmhal: Add STM32F7DISC and associated changes. 2015-07-30 00:38:32 +01:00
Dave Hylands
7e7fb0b7a3 stmhal: Renamed startup/system/_it.[ch] file to generic names. 2015-07-30 00:38:29 +01:00
Dave Hylands
ea8bf81058 stmhal: Replace #include "stm32f4xx_hal.h" with #include STM32_HAL_H. 2015-07-30 00:38:25 +01:00
Damien George
f243851ccd stmhal: Expose uwTick in f7 hal. 2015-07-30 00:38:25 +01:00
Dave Hylands
7c934ae501 stmhal: Add hal and cmsis files from STM32Cube_FW_F7_V1.1.0.
All files were converted to linux line endings.
All trailing whitespace was removed using:
for f in f7/inc/* f7/src/*; do sed --in-place 's/[[:space:]]\+$//' $f; done
All non-ascii chars in comments were replaced with ascii equivalents or
removed.
2015-07-30 00:38:18 +01:00
Daniel Campora
aa58c7ec74 cc3200: Append last 2 bytes of the MAC address to the default SSID. 2015-07-30 00:43:16 +02:00
Daniel Campora
b56634e691 cc3200: On ssl.read() or ssl.readall() ignore ssl layer closed error. 2015-07-30 00:43:14 +02:00
Daniel Campora
fb3f9cff33 cc3200: Switch to 1 byte hash for QSTRs. 2015-07-30 00:43:13 +02:00
Daniel Campora
da33b31c7d docs/wipy: Correct nic.ifconfig() quickref example. 2015-07-30 00:43:11 +02:00
Daniel Campora
9a348fc840 cc3200: Add socket.makefile() 2015-07-30 00:43:10 +02:00
Daniel Campora
007878781c cc3200: Rename pins from GPIO to just GP.
This is how the names will be printed on the sticker that goes on top
of the EMI shield. The shorter names also help saving a few bytes of
RAM and ROM.
2015-07-30 00:43:08 +02:00
Damien George
cfc4c33801 py/compile: Give more precise line number for compile errors.
Previous to this patch there were some cases where line numbers for
errors were 0 (unknown).  Now the compiler attempts to give a better
line number where possible, in some cases giving the line number of the
closest statement, and other cases the line number of the inner-most
scope of the error (eg the line number of the start of the function).
This helps to give good (and sometimes exact) line numbers for
ViperTypeError exceptions.

This patch also makes sure that the first compile error (eg SyntaxError)
that is encountered is reported (previously it was the last one that was
reported).
2015-07-29 22:16:01 +00:00
Damien George
28596edf07 py/repl: Don't look inside strings for unmatched brackets/quotes.
When looking to see if the REPL input needs to be continued on the next
line, don't look inside strings for unmatched ()[]{} ''' or """.

Addresses issue #1387.
2015-07-29 15:21:42 +00:00
Damien George
7ccdf8be77 tools/pyboard.py: Fix read timeout calc to work with shorter sleep. 2015-07-29 00:21:22 +01:00
Damien George
f5d04750db stmhal: Put fs_user_mount pointer in root ptr section of global state.
Should fix issue #1393.
2015-07-27 23:52:56 +01:00
Damien George
92e9a5e0a7 stmhal: Check if user block device is mounted before accessing it.
In particular this fixes a bug where pyb.sync (and os.sync) fail because
they try to sync the user mounted device even if it's not mounted.
2015-07-27 23:40:19 +01:00
Damien George
84d59c2873 py: For viper compile errors, add traceback with function and filename.
ViperTypeError now includes filename and function name where the error
occurred.  The line number is the line number of the start of the
function definition, which is the best that can be done without a lot
more work.

Partially addresses issue #1381.
2015-07-27 22:20:00 +01:00
Damien George
d8a7f8bff2 py: Disable REPL EMACS key bindings by default. 2015-07-26 15:49:13 +01:00
Tom Soulanille
3dd0b69e46 run-tests: Use PTY when running REPL tests. 2015-07-26 15:23:11 +01:00
Tom Soulanille
7d588b0c7c lib/mp-readline: Add emacs-style control characters for cursor movement.
Disabled by default.  Adds 108 bytes to Thumb2 arch when enabled.
2015-07-26 15:22:13 +01:00
Daniel Campora
cd14188bc8 tools: Add telnet support to pyboard.py.
The adapter class "TelnetToSerial" is used to access the Telnet
connection using the same API as with the serial connection. The
function pyboard.run-test() has been removed to made the module
generic and because this small test is no longer needed.
2015-07-26 14:02:34 +01:00
Damien George
db109ca0fc tools/pyboard.py: Speed up reading of chars by decreasing sleep period. 2015-07-25 22:49:25 +01:00
Damien George
f1236734bb tools/pyboard.py: Make enter_raw_repl stricter and more reliable.
When looking for chars to indicate raw repl is active, look for the full
string of chars to improve reliability of entering raw repl correctly.

Previous to this patch there was the possibility that raw repl was
entered in a dirty state, where not all input chars from previous
invocation were drained.
2015-07-25 22:46:07 +01:00
Damien George
9de53bf788 tools/pyboard.py: Fix parsing of returned error so last chr is not lost. 2015-07-25 22:44:56 +01:00
Damien George
3900fed849 tests: Skip parser test if "compile" builtin is not available. 2015-07-24 22:37:26 +01:00
Damien George
96f0dd3cbc py/parse: Fix handling of empty input so it raises an exception. 2015-07-24 15:05:56 +00:00
Damien George
fa7c61dfab py/parse: De-duplicate and simplify code for parser "or" rule. 2015-07-24 14:35:57 +00:00
Damien George
d241c2a592 py/lexer: Raise SyntaxError when str hex escape sequence is malformed.
Addresses issue #1390.
2015-07-23 23:20:37 +01:00
Damien George
f17e663493 py: Issue an error when compiling Viper functions with more than 4 args.
Otherwise it can be very hard to track down bugs.
2015-07-23 14:30:37 +01:00
Damien George
e45c1dbd6f py: Allow viper functions to take up to 4 arguments.
Addresses issue #1380.
2015-07-23 14:11:29 +01:00
Damien George
7693ef3bd6 stmhal: Allow ADC.read_timed to take Timer object in place of freq.
This allows a user-specified Timer for the triggering of the ADC read,
mirroring the new behaviour of DAC.write_timed.

Addresses issue #1129.
2015-07-22 19:41:13 +01:00
Damien George
99a21dc05d stmhal: Add stm32fxxx_hal_i2s_ex.c to hal/f2 (dummy) and hal/f4. 2015-07-21 23:49:19 +01:00
Damien George
abc24c1876 stmhal: Allow DAC.write_timed to take Timer object in place of freq.
This allows the DAC to use a user-specified Timer for the triggering
(instead of the default Timer(6)), while still supporting original
behaviour.

Addresses issues #1129 and #1388.
2015-07-21 23:39:49 +01:00
Damien George
6f5e0fe955 stmhal: Clean up DAC code a little. 2015-07-21 22:05:56 +01:00
Delio Brignoli
6a388aaa7c py: reduce array slice assignment code size 2015-06-06 22:17:24 +02:00
blmorris
2af846e711 stmhal/boards/stm32fxx_prefix.c: Fix alt function number calculation
This prevented pin_find_af* functions from being able to find some
of the alternate functions in the pin struct
2015-07-20 16:19:12 +01:00
Damien George
4915c2b871 py: Small code space optimisations for memoryview slice assigment.
Also adds #if guards to allow uPy core to compile without memoryview
enabled, but with slice assignment enabled.
2015-07-20 16:12:26 +01:00
Delio Brignoli
cceff157dd qemu-arm: Enable array slice assignment to get memoryview1 test to pass. 2015-07-20 15:53:22 +01:00
Delio Brignoli
32aba40830 py: Implement memoryview slice assignment.
Adds ability to do "memcpy" with memoryview objects, such as:
m1[0:3] = m2[2:5].
2015-07-20 15:53:22 +01:00
Damien George
f576057274 stmhal: Add CMSIS device header files for STM32F2xx series. 2015-07-20 12:33:05 +01:00
Wojtek Siudzinski
0621eca05e stmhal: Add STM32CubeF2 version 1.1.0, in hal/f2 directory.
Only those files which are needed by the stmhal port are added.

Also includes a dummy file (stm32f2xx_hal_pcd_ex.c) to keep the build
system the same for f4 and f2 MCU series.
2015-07-20 12:32:09 +01:00
Damien George
a39df51d8a stmhal: Update Makefile and board configs to compile with relocated hal. 2015-07-20 12:30:18 +01:00
Damien George
e4d43401eb stmhal: Move HAL Cube files to f4/ subdir, keeping only those we use.
This is in preparation for supporting other MCU series, such as
STM32F2xx.  Directory structure for the HAL is now hal/f4/{inc,src},
where "f4" will in the future be different for other series.

HAL source/header files that are not use are removed to reduce the size
of the code.
2015-07-20 12:30:18 +01:00
Damien George
d136737872 CODECONVENTIONS: Add a short section about how to allocate heap memory. 2015-07-20 12:18:16 +01:00
Damien George
75b1d881ec esp8266: Use m_new/m_renew/m_del funcs instead of private gc_xxx. 2015-07-20 12:14:21 +01:00
Damien George
c3bd9415cc py: Make qstr hash size configurable, defaults to 2 bytes.
This patch makes configurable, via MICROPY_QSTR_BYTES_IN_HASH, the
number of bytes used for a qstr hash.  It was originally fixed at 2
bytes, and now defaults to 2 bytes.  Setting it to 1 byte will save
ROM and RAM at a small expense of hash collisions.
2015-07-20 11:03:13 +00:00
Sebastian Plamauer
1e8ca3a3cf modbuiltins: Implement round() to precision. 2015-07-19 21:49:44 +03:00
Paul Sokolovsky
ab14c30493 esp8266: modesp: Update for gc_realloc() refactor.
TODO: Contributed code in modesp incorrectly uses private gc_* API.
2015-07-19 00:28:16 +03:00
Daniel Campora
f22b35e4e5 cc3200: Add socket.sendall() (aliases to send()).
Simplelink's socket send checks for the size of the packet and sends
it in chunks if the size is too large.
2015-07-17 11:38:01 +02:00
Daniel Campora
a243d6b057 cc3200: Make socket stream methods return POSIX error codes. 2015-07-16 22:39:35 +02:00
Daniel Campora
f738424403 cc3200: Remove superflous assignment since the result is not used. 2015-07-15 14:45:24 +02:00
Daniel Campora
753a8e8bc4 cc3200: Create /flash/cert folder if it doesn't exist. 2015-07-15 14:25:35 +02:00
Daniel Campora
e955089da0 cc3200: Implement new OTA mechanism with 2 firmware update slots. 2015-07-15 14:25:28 +02:00
Dave Hylands
9309e609cd stmhal: Add qstr definition for ifconfig when building for WizNet 2015-07-14 23:00:29 +01:00
Damien George
ade9a05236 py: Improve allocation policy of qstr data.
Previous to this patch all interned strings lived in their own malloc'd
chunk.  On average this wastes N/2 bytes per interned string, where N is
the number-of-bytes for a quanta of the memory allocator (16 bytes on 32
bit archs).

With this patch interned strings are concatenated into the same malloc'd
chunk when possible.  Such chunks are enlarged inplace when possible,
and shrunk to fit when a new chunk is needed.

RAM savings with this patch are highly varied, but should always show an
improvement (unless only 3 or 4 strings are interned).  New version
typically uses about 70% of previous memory for the qstr data, and can
lead to savings of around 10% of total memory footprint of a running
script.

Costs about 120 bytes code size on Thumb2 archs (depends on how many
calls to gc_realloc are made).
2015-07-14 22:56:32 +01:00
Paul Sokolovsky
c48740e20b unix: modsocket: Implement inet_pton() in preference of inet_aton().
inet_pton supports both ipv4 and ipv6 addresses. Interface is also extensible
for other address families, but underlying libc inet_pton() function isn't
really extensible (e.g., it doesn't return length of binary address, i.e. it's
really hardcoded to AF_INET and AF_INET6). But anyway, on Python side, we could
extend it to support other addresses.
2015-07-15 00:06:03 +03:00
Paul Sokolovsky
b178dccb9c unix: modsocket: Implement recvfrom().
Required to implement UDP servers.
2015-07-14 01:47:02 +03:00
Paul Sokolovsky
3b83aeb403 unix: modsocket: Implement sendto().
sendto() turns out to be mandatory function to work with UDP. It may seem
that connect(addr) + send() would achieve the same effect, but what connect()
appears to do is to set source address filter on a socket to its argument.
Then everything falls apart: socket sends to a broad-/multi-cast address,
but reply is sent from real peer address, which doesn't match filter set
by connect(), so local socket never sees a reply.
2015-07-12 13:53:35 +03:00
Paul Sokolovsky
115afdb07d unix: socket.getaddrinfo: Port is unsigned value.
Treating it as signed lead to buffer overflow for ports >= 32768.
2015-07-11 00:06:10 +03:00
Daniel Campora
cf814b2d34 cc3200: Refactor and clean-up socket closing code. 2015-07-10 11:37:50 +02:00
Daniel Campora
ecb7f9fe58 cc3200: Set simplelink time and date when enabling WLAN. 2015-07-10 11:37:48 +02:00
Daniel Campora
fa47bebfbc cc3200: Add struct weak link for ustruct. 2015-07-10 11:37:46 +02:00
Paul Sokolovsky
8eb802a55b unix: socket.getaddrinfo: Accept family & socktype arguments.
This usually allows to get just a single address entry.
2015-07-10 01:50:23 +03:00
Daniel Campora
af33ebb13b cc3200: Increment telnet Tx retry delay on every try. 2015-07-09 17:30:17 +02:00
Daniel Campora
9220dc466a cc3200: Correct udelay us to ticks calculation. 2015-07-08 13:13:37 +02:00
Daniel Campora
d18ced9cdd cc3200: Use alternative HAL_Delay also when interrupts are disabled. 2015-07-08 12:48:35 +02:00
Damien George
7463442e58 docs: Update pyb.Accel doc to reflect changes and explain filtered_xyz. 2015-07-08 11:10:51 +01:00
Paul Sokolovsky
354d17523f modmachine: Implement physical memory access using /dev/mem (Linux, etc).
This requires root access. And on recent Linux kernels, with
CONFIG_STRICT_DEVMEM option enabled, only address ranges listed in
/proc/iomem can be accessed. The above compiled-time option can be
however overriden with boot-time option "iomem=relaxed".

This also removed separate read/write paths - there unlikely would
be a case when they're different.
2015-07-08 11:37:23 +03:00
Daniel Campora
a0a3de60be cc3200: Translate simplelink's socket error numbers to POSIX values. 2015-07-07 16:13:54 +02:00
Daniel Campora
5685b565c3 cc3200: Create /flash/sys and /flash/lib directories while booting. 2015-07-07 16:13:40 +02:00
Daniel Campora
76e52b5daf cc3200: Make update-wipy.py more robust. 2015-07-07 16:11:48 +02:00
Daniel Campora
fa655ce196 cc3200: Improve interrupt handling and fix bug in HAL_Delay(). 2015-07-07 16:11:05 +02:00
Daniel Campora
194c8c761e cc3200: Increment interrupt stack size from 2K to 3K. 2015-07-07 16:10:10 +02:00
Dave Hylands
11115e4d23 stmhal: Add I2S support to make-pins.py 2015-07-07 10:15:37 +01:00
Dave Hylands
c91727b75a tools: Fix pydfu.py to work with old and new versions of PyUSB
Update pydfu.py to match with the version from openmv.

I just updated the openmv version to work with both of the
PyUSB 1.0.0.b1 and 1.0.0.b2

See: https://github.com/walac/pyusb/blob/master/ReleaseNotes.rst
2015-07-06 09:56:12 -07:00
Dave Hylands
9f76dcd682 py: Prevent many extra vstr allocations.
I checked the entire codebase, and every place that vstr_init_len
was called, there was a call to mp_obj_new_str_from_vstr after it.

mp_obj_new_str_from_vstr always tries to reallocate a new buffer
1 byte larger than the original to store the terminating null
character.

In many cases, if we allocated the initial buffer to be 1 byte
longer, we can prevent this extra allocation, and just reuse
the originally allocated buffer.

Asking to read 256 bytes and only getting 100 will still cause
the extra allocation, but if you ask to read 256 and get 256
then the extra allocation will be optimized away.

Yes - the reallocation is optimized in the heap to try and reuse
the buffer if it can, but it takes quite a few cycles to figure
this out.

Note by Damien: vstr_init_len should now be considered as a
string-init convenience function and used only when creating
null-terminated objects.
2015-07-06 17:29:27 +01:00
Damien George
ef7dd8db2d py/repl: Fix case where shorter names are shadowed by longer names.
Previous to this patch, if "abcd" and "ab" were possible completions
to tab-completing "a", then tab would expand to "abcd" straight away
if this identifier appeared first in the dict.
2015-07-06 14:00:09 +01:00
Paul Sokolovsky
6ab8b63bdd tools/make-frozen.py: Use Python2-compatible shebang. 2015-07-06 14:48:29 +03:00
Damien George
68e8b595de tests: Catch ValueError instead of any exception to properly test error. 2015-07-06 11:35:08 +00:00
Damien George
722d4842df extmod/modubinascii: Re-use error string to reduce code size.
Drops Thumb2 arch size by 24 bytes.
2015-07-06 11:34:29 +00:00
Paul Sokolovsky
de575c80b9 tools/make-frozen.py: Actually make Python2-compatible. 2015-07-06 14:27:57 +03:00
Paul Sokolovsky
3a2e9f20f6 tools/make-frozen.py: Add Python2 compatibility. 2015-07-06 14:09:16 +03:00
Paul Sokolovsky
7e66b859b2 modstruct: Raise NotImplementedError for unsupported repeat specification. 2015-07-05 22:44:14 +03:00
Daniel Campora
aaf7c5b35e cc3200/README.md: Improve make deploy instructions. 2015-07-04 16:39:05 +02:00
Daniel Campora
c030e77861 cc3200: Enable base64 methods from modubinascii. 2015-07-04 16:33:54 +02:00
Daniel Campora
219a74c014 cc3200/README.md: Add notes about deploying a new software version. 2015-07-04 16:32:49 +02:00
Paul Sokolovsky
7370fd5560 ubinascii: Fix a shadowed variable case. 2015-07-04 13:13:10 +03:00
Paul Sokolovsky
e284a95cc3 ubinascii: b2a_base64: Optimize away a modulo operation. 2015-07-04 12:36:46 +03:00
Galen Hazelwood
616986a5f3 extmod: Add a2b_base64 and b2a_base64 functions to ubinascii. 2015-07-04 12:26:52 +03:00
Paul Sokolovsky
b19d273beb esp8266: Allow to easily override programming baudrate. 2015-07-04 00:36:10 +03:00
Daniel Campora
31b40eebe8 cc3200: Fix socket recv and recvfrom return value type. 2015-07-02 23:17:22 +02:00
Damien George
035deae1c6 py/objarray.c: Allow to build with debugging and bytearray but no array. 2015-07-02 16:26:57 +01:00
Daniel Campora
5161239c9f cc3200: time.sleep() now receives seconds, like CPython. 2015-07-02 17:23:22 +02:00
Daniel Campora
9a65fa304c cc3200: Add modussl, ssl sockets subclassed from normal sockets.
Stream methods were added to normal sockets as in the unix port.
2015-07-02 16:30:00 +02:00
Daniel Campora
7c1c9af5d4 cc3200: Code clean-up on pybpin. 2015-07-02 16:29:51 +02:00
Daniel Campora
4f8eeaedef cc3200: Set WLAN date/time via the rtc.datetime method().
WLAN needs time info when validating certificates.
2015-07-02 16:29:43 +02:00
Daniel Campora
d680e28a11 cc3200: Optimize check for WLAN AP mode. 2015-07-02 16:15:59 +02:00
Daniel Campora
7fd538c1b6 cc3200: Raise an exception if trying to scan for networks in AP mode. 2015-07-02 15:03:58 +02:00
Daniel Campora
f522849a4d cc3200: Add socket.timeout and socket.error exceptions. 2015-07-02 11:53:15 +02:00
Daniel Campora
077812b2ab py: Add TimeoutError exception subclassed from OSError.
The TimeoutError is useful for some modules, specially the the
socket module. TimeoutError can then be alised to socket.timeout
and then Python code can differentiate between socket.error and
socket.timeout.
2015-07-02 11:53:08 +02:00
Daniel Campora
bdf958df30 docs/wipy: Update safe boot comments to match actual behaviour. 2015-06-30 22:27:50 +02:00
Daniel Campora
70fc42cb28 cc3200: Add CA, certificate and key files to the updater list. 2015-06-30 22:11:15 +02:00
Daniel Campora
5ebf39784a cc3200: Correct socket settimeout time format. 2015-06-29 11:01:11 +02:00
Paul Sokolovsky
9780e55274 builtinimport: Fix running package submodule with -m.
When "micropython -m pkg.mod" command was used, relative imports in pkg.mod
didn't work, because pkg.mod.__name__ was set to __main__, and the fact that
it's a package submodule was missed. This is an original workaround to this
issue. TODO: investigate and compare how CPython deals with this issue.
2015-06-29 00:26:45 +03:00
Daniel Campora
4f5b896a0b cc3200: Adapt update-wipy.py timing to improve stability. 2015-06-28 14:14:24 +02:00
Daniel Campora
813b581127 cc3200: Add Pin.name() method. 2015-06-28 14:14:22 +02:00
Daniel Campora
778413168b cc3200: Enable more features to improve compatibility with stmhal. 2015-06-28 14:14:20 +02:00
Damien George
0807139c1d stmhal: Add config option for storage to use second flash segment.
When enabled this allows the internal storage to be split over 2
contiguous regions of flash (two segments), and so the storage can be
increased.

This option is disabled by default, giving original behaviour.
2015-06-27 23:27:23 +01:00
Damien George
fa1cdb09fc docs: Fix duplicate label error for network.WLAN. 2015-06-27 13:42:00 +01:00
Damien George
8cc8f280eb docs: Make index link point to "index.html" irrespective of port. 2015-06-27 13:41:24 +01:00
Paul Sokolovsky
9896314f5b tests: Add test for relative import without package context. 2015-06-27 00:40:22 +03:00
Paul Sokolovsky
c4045f57e3 builtinimport: Catch case when relative import happens without active package.
CPython raises SystemError in this case, but we don't have that enabled, so
raise ImportError.
2015-06-27 00:40:21 +03:00
Paul Sokolovsky
6557a096d6 runtime: Improve mp_import_name() debug logging. 2015-06-27 00:40:21 +03:00
Paul Sokolovsky
f44cc517a2 objstr: Add note that replace() is nicely optimized.
Doesn't allocate memory and returns original string if no replacements are
to be made.
2015-06-26 17:35:12 +03:00
Damien George
abfd4da287 docs: Add link from pyboard asm tutorial to asm reference. 2015-06-26 12:35:17 +01:00
Damien George
59fba2d6ea py: Remove mp_load_const_bytes and instead load precreated bytes object.
Previous to this patch each time a bytes object was referenced a new
instance (with the same data) was created.  With this patch a single
bytes object is created in the compiler and is loaded directly at execute
time as a true constant (similar to loading bignum and float objects).
This saves on allocating RAM and means that bytes objects can now be
used when the memory manager is locked (eg in interrupts).

The MP_BC_LOAD_CONST_BYTES bytecode was removed as part of this.

Generated bytecode is slightly larger due to storing a pointer to the
bytes object instead of the qstr identifier.

Code size is reduced by about 60 bytes on Thumb2 architectures.
2015-06-25 14:42:13 +00:00
Damien George
ed570e4b2a py: Remove mp_load_const_str and replace uses with inlined version. 2015-06-25 13:58:41 +00:00
Paul Sokolovsky
484adac0bb tools: Update upip to 0.5.4.
Recognize and handle "package not found" error.
2015-06-25 15:32:14 +03:00
Garrett Berg
f64e080d9a CODECONVENTIONS.md: add documentation on putting comments in code. 2015-06-25 10:56:39 +01:00
Damien George
e44c1d3ace tests: Split out json float tests to separate files. 2015-06-25 10:50:00 +01:00
Daniel Campora
186b355b28 tests: Add support for the WiPy in run-tests script.
The --pyboard param has been replaced by --target which defaults to
'unix'. Possible values at this moment are 'unix', 'pyboard' and
'wipy'. Now is also possible to select the baud rate of the serial
device when calling the script.
2015-06-25 10:45:25 +01:00
Damien George
0d3e309ebc docs: Add link in references index to Thumb2 assembler docs. 2015-06-25 00:24:19 +01:00
Damien George
2110dc5a6d docs: Add reference for Thumb2 inline assembler.
Thanks to Peter Hinch for contributing this.
2015-06-25 00:21:35 +01:00
Damien George
aef3846c13 docs: Add "reference" directory for putting docs about the language. 2015-06-25 00:20:57 +01:00
Daniel Campora
4af5424242 tests: Adapt misc/features.py tests for ports without floating point. 2015-06-24 17:53:29 +01:00
blmorris
c5175526dd stmhal/dma.c: Modify dma_init() to accept init struct as an argument
This removes hard-coded DMA init params from dma_init(), instead defining
these parameters in a DMA_InitTypeDef struct that gets passed as an
argument to dma_init()
This makes dma_init more generic so it can be used for I2S and SD Card,
which require different initialization parameters.
2015-06-24 17:48:52 +01:00
Damien George
3299f687f5 CODECONVENTIONS.md: Mention macro and enum names. 2015-06-24 17:35:27 +01:00
stijn
9c7d183a94 CODECONVENTIONS.md: Add function/variable/argument naming convention 2015-06-24 17:35:27 +01:00
Daniel Campora
d02f671737 cc3200: Add deploy target and improve robustness of update-wipy.py. 2015-06-24 15:26:05 +02:00
Daniel Campora
d709622bd2 tests: Adapt basics/memoryerror.py for ports with lower heap sizes. 2015-06-24 15:25:59 +02:00
Daniel Campora
e64afde073 cc3200: Create tools folder and add update-wipy.py script.
This script is used by Jenkins to update the WiPy with the newly
built firmware before running the tests. It's not placed in the
common tools folder because it is very WiPy specific.
2015-06-24 12:36:38 +02:00
Damien George
2a1090a637 py: Clarify comment in parsenum.c about ValueError vs SyntaxError. 2015-06-23 16:08:51 +00:00
Daniel Campora
228c68a9cd py: Change exception type to ValueError when error reporting is terse.
Addresses issue #1347
2015-06-23 15:30:49 +02:00
Damien George
6e1dfb0d1a stmhal: Reorganise code for parsing keyword args in I2C methods.
To make it the same as SPI and UART.
2015-06-22 23:46:22 +01:00
Damien George
de8b585ab7 esp8266: Make pyb.RTC a type, and pyb.RTC() constructs an RTC object.
This is the standard way of doing things, one should construct a
peripheral object (even if it's a singleton).

See issue #1330.
2015-06-22 23:03:17 +01:00
Damien George
c4b592d379 bare-arm, minimal, qemu-arm: Make do_str() take parse-input-kind as arg.
The do_str() function is provided essentially as documentation to show
how to compile and execute a string.  This patch makes do_str take an
extra arg to specify how the string should be interpreted: either as a
single line (ie from a REPL) or as multiple lines (ie from a file).
2015-06-22 22:38:47 +01:00
Paul Sokolovsky
fe99ea9aab README: Add quick information about builtin upip package manager.
Also, simplify dependencies info now that we no longer require GNU
readline.
2015-06-22 20:06:12 +03:00
Damien George
7f19a39a3b py: Cast argument for printf to int, to be compatible with more ports.
This allows stmhal to be compiled with MICROPY_DEBUG_PRINTERS.
2015-06-22 17:40:12 +01:00
Paul Sokolovsky
a06c38b486 tests: Add testcase for open(..., "a"). 2015-06-21 00:05:09 +03:00
Ari Suutari
63b9e598a3 unix: Add O_WRONLY | O_CREAT to open call when opening file for append ("a").
To comply with Python semantics.
2015-06-21 00:03:26 +03:00
Bill Owens
60ccb41fac esp8266: Move status() from esp module to network 2015-06-20 23:35:55 +03:00
Damien George
06593fb0f2 py: Use a wrapper to explicitly check self argument of builtin methods.
Previous to this patch a call such as list.append(1, 2) would lead to a
seg fault.  This is because list.append is a builtin method and the first
argument to such methods is always assumed to have the correct type.

Now, when a builtin method is extracted like this it is wrapped in a
checker object which checks the the type of the first argument before
calling the builtin function.

This feature is contrelled by MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG and
is enabled by default.

See issue #1216.
2015-06-20 16:39:39 +01:00
Paul Sokolovsky
a193ced7fa esp8266: README: Typo fix. 2015-06-19 21:09:53 +03:00
Damien George
c8870b7c69 py: Make showbc decode UNPACK_EX, and use correct range for unop/binop. 2015-06-18 15:12:17 +00:00
Paul Sokolovsky
b6a08208e1 esp8266: Explicit warning that port is experimental and subject to change. 2015-06-18 11:46:43 +03:00
Paul Sokolovsky
fb4b800820 README: Mention esp8266 port. 2015-06-18 11:44:04 +03:00
Radomir Dopieralski
0cba23716d ESP8266: Update the README.md to reflect what works 2015-06-18 11:42:05 +03:00
Paul Sokolovsky
b85bf25e97 CODECONVENTIONS.md: 16-bit ports exist now. 2015-06-18 11:40:48 +03:00
Paul Sokolovsky
2474c2ae94 CODECONVENTIONS.md: Header files no longer follow Plan 9 conventions. 2015-06-18 11:38:09 +03:00
Daniel Campora
92d95cc9d3 cc3200: Remove --specs=nano.specs linker flag. 2015-06-18 09:01:37 +02:00
Bill Owens
7c61249ae6 esp8266: Updated documentation for scan() and moved to network 2015-06-17 23:16:28 +03:00
Bill Owens
686516f90a esp8266: Move scan from esp module to network 2015-06-17 23:13:12 +03:00
Daniel Campora
ea2cc2b907 docs: Add more documentation for the CC3200 in the pyb module. 2015-06-16 15:45:24 +02:00
Daniel Campora
cdfa11f550 cc3200: In Timer.callback() only use value param if in edge count mode. 2015-06-16 15:34:46 +02:00
Damien George
e78a8c94b6 docs: Bump version to 1.4.4. 2015-06-15 23:54:22 +01:00
Damien George
f6518a7bd5 tests: Check that machine module exists and print SKIP if it doesn't. 2015-06-15 23:35:15 +01:00
Damien George
d59ca4efdb tools/pyboard.py: Change logic for when raw ">" prompt is parsed.
In raw REPL ">" indicates the prompt.  We originally read this character
upon entering the raw REPL, and after reading the last bit of the
output.  This patch changes the logic so the ">" is read only just
before trying to send the next command.  To make this work (and as an
added feature) the input buffer is now flushed upon entering raw REPL.

The main reason for this change is so that pyboard.py recognises the EOF
when sys.exit() is called on the pyboard.  Ie, if you run pyboard.py
with a script that calls sys.exit(), then pyboard.py will exit after
the sys.exit() is called.
2015-06-15 23:28:04 +01:00
Bill Owens
3ce212e0a6 esp8266: Changed esp_scan to keep the current WiFi operating mode but throw an exception if WiFi is in AP only mode 2015-06-14 10:57:08 +03:00
Damien George
e9ce00d874 py: Implement divmod for mpz bignum. 2015-06-13 23:38:28 +01:00
Damien George
c5029bcbf3 py: Add MP_BINARY_OP_DIVMOD to simplify and consolidate divmod builtin. 2015-06-13 23:36:30 +01:00
Damien George
6f49520042 py: Implement second arg for math.log (optional value for base). 2015-06-13 22:35:25 +01:00
Radomir Dopieralski
05c6fbcae6 esp8266: Fix the documentation for esp.connect() and esp.disconnect()
Since the commit that moved those two functions failed to update
the documentation, this is a fix for that.
2015-06-13 23:03:06 +03:00
Paul Sokolovsky
dd0e24f4b0 pip-micropython: Add deprecation notice, but still leave for reference. 2015-06-13 21:39:57 +03:00
Paul Sokolovsky
32eb4b9055 esp8266: Move connect/disconnect from "esp" module to network. 2015-06-12 17:45:28 +03:00
Paul Sokolovsky
ee3fec3167 esp8266: Add skeleton "network" module.
MicroPython "network" module interface requires it to contains classes
to instantiate. But as we have a static network interace, make WLAN()
"constructor" just return module itself, and just make all methods
module-global functions.
2015-06-12 17:45:20 +03:00
Paul Sokolovsky
431603ad69 esp8266: esp_connect(): The function is now vararg.
Fixes regression from a previous commit.
2015-06-12 14:26:44 +03:00
Paul Sokolovsky
a19ba5fea0 py: Rebuild port if mpconfigport.mk changed (if any).
mpconfigport.mk contains configuration options which affect the way
MicroPython is linked. In this regard, it's "stronger" configuration
dependency than even mpconfigport.h, so if we rebuild everything on
mpconfigport.h change, we certianly should of that on mpconfigport.mk
change too.
2015-06-11 11:08:39 +03:00
Daniel Campora
f28ed55aeb cc3200/README.md: Specify the board name in the build command. 2015-06-11 09:26:36 +02:00
Daniel Campora
0a903be7d0 README.md: Correct port names in the documentation build command. 2015-06-11 09:15:07 +02:00
Daniel Campora
cfcf47c064 docs: Add initial draft documentation for the WiPy.
This makes all common files "port-aware" using the .. only directive.
2015-06-10 23:37:56 +02:00
Daniel Campora
b630de1103 cc3200: Rename os.mkdisk() to os.mkfs(). 2015-06-10 23:35:45 +02:00
Daniel Campora
1811c6bccf cc3200: Remove Timer.AB constant.
Timer.A and Timer.B can be ORed for this purpose.
2015-06-10 23:35:43 +02:00
Daniel Campora
e2dc7ac2a9 cc3200: Clarify notes about the extended functionality of uhashlib. 2015-06-10 23:35:41 +02:00
Daniel Campora
95cc1ff542 cc3200: Re-name pyb.hard_reset() to pyb.reset(). 2015-06-10 23:35:40 +02:00
Daniel Campora
330e21c986 cc3200: Use the pull up/down resistors on the antenna selection pins. 2015-06-10 23:35:38 +02:00
Daniel Campora
f960d753e4 cc3200: Fix bootloader build error. 2015-06-10 23:35:36 +02:00
Daniel Campora
3319780e96 cc3200: Add sendbreak method to the UART. 2015-06-10 23:35:35 +02:00
Daniel Campora
8a6d93aeed cc3200: Make UART API more similar to stmhal. 2015-06-10 23:35:33 +02:00
Daniel Campora
640d00ea9d cc3200: Change MP_OBJ_NULL for mp_const_none in params default value. 2015-06-10 23:35:32 +02:00
Daniel Campora
071d47fa3b cc3200: Only kick the WDT if it's actually running. 2015-06-10 23:35:30 +02:00
Daniel Campora
6148f8b7d2 cc3200: Add contructor to the HeartBeat class. 2015-06-10 23:35:28 +02:00
Damien George
76285469d3 stmhal: Make I2C use DMA when interrupts are enabled. 2015-06-10 14:01:44 +01:00
Damien George
3d30d605f5 stmhal: Factor out DMA initialisation code from spi.c.
This is so that the DMA can be shared by multiple peripherals.
2015-06-10 14:01:44 +01:00
Damien George
7ed58cb663 py: Support unicode (utf-8 encoded) identifiers in Python source.
Enabled simply by making the identifier lexing code 8-bit clean.
2015-06-09 10:58:07 +00:00
Damien George
6e56bb623c py: Fallback to stack alloca for Python-stack if heap alloc fails.
If heap allocation for the Python-stack of a function fails then we may
as well allocate the Python-stack on the C stack.  This will allow to
run more code without using the heap.
2015-06-08 22:07:27 +01:00
Daniel Campora
371f4ba6b3 cc3200: Wrap antenna_init0() with #if MICROPY_HW_ANTENNA_DIVERSITY. 2015-06-08 10:38:19 +02:00
Damien George
0aa5e75000 stmhal: Break immediately from USB CDC busy wait loop if IRQs disabled.
If IRQs are disabled then the USB CDC buffer will never be
drained/filled and the sys-tick timer will never increase, so we should
not busy wait in this case.
2015-06-07 23:48:07 +01:00
Daniel Campora
491c321720 cc3200: Re-config antenna selection when waking from suspended mode. 2015-06-07 13:28:47 +02:00
Daniel Campora
b4a41a8f70 cc3200: Add missing antenna diversity source files. 2015-06-07 00:42:40 +02:00
Daniel Campora
a3acaa000c cc3200: Add antenna selection feature to WLAN. 2015-06-07 00:06:27 +02:00
Paul Sokolovsky
098f5ae221 micropython-upip: Mark as binary file and re-commit. 2015-06-06 23:09:23 +03:00
Paul Sokolovsky
1406d9ccde upip: Upgrade to 0.5.3 to follow uctypes.struct() signature change. 2015-06-06 23:03:28 +03:00
Paul Sokolovsky
06e85ecfa6 docs/uctype: Update for constructor argument order changes.
Also, other small cleanups/improvements.
2015-06-06 22:58:04 +03:00
Paul Sokolovsky
1679696612 moductypes: Swap address and descriptor args in constructor.
Now address comes first, and args related to struct type are groupped next.
Besides clear groupping, should help catch errors eagerly (e.g. forgetting
to pass address will error out).

Also, improve args number checking/reporting overall.
2015-06-06 22:57:54 +03:00
Paul Sokolovsky
07408cbd1f unix: Make micropython -m <module> work for frozen modules.
This requires some special handling, which was previosuly applied only to
the main code path.
2015-06-06 00:10:58 +03:00
Damien George
d7192fe68c py: Expose KeyboardInterrupt in builtins module. 2015-06-05 10:46:22 +01:00
Damien George
3eece29807 docs: Change "Micro Python" to "MicroPython" in all places in docs. 2015-06-04 23:53:26 +01:00
Damien George
601cfea6a3 docs: Update license date range to include 2015. 2015-06-04 23:47:10 +01:00
Daniel Campora
7ca1bd314b docs: Generate a separate docs build for each port.
Using Damien's approach where conf.py and topindex.html are
shared by all ports.
2015-06-04 23:44:35 +01:00
Damien George
031278f661 unix: Allow to cat a script into stdin from the command line.
See issue #1306.
2015-06-04 23:42:45 +01:00
Paul Sokolovsky
9724a0538b windows/README: Add notes on running under Wine.
After enabling line editing support on Windows console, this is no longer
trivial.
2015-06-04 19:29:51 +03:00
stijn
87ad80edf9 windows: Implement the mp_hal_xxx functions and enable mp-readline 2015-06-04 19:22:13 +03:00
Damien George
567b349c2b py: Implement native multiply operation in viper emitter. 2015-06-04 14:00:29 +00:00
Damien George
4d9cad180d py: Implement implicit cast to obj for viper load/store index/value.
This allows to do "ar[i]" and "ar[i] = val" in viper when ar is a Python
object and i and/or val are native viper types (eg ints).

Patch also includes tests for this feature.
2015-06-04 11:52:16 +01:00
Daniel Campora
a3cf4ea2f6 cc3200: Do not kick the watchdog inside the idle task. 2015-06-04 10:13:55 +02:00
Daniel Campora
71f85cc330 cc3200: Close ftp and telnet server sockets if listening fails. 2015-06-04 10:13:53 +02:00
Damien George
53a8aeb6e7 stmhal: Fix slow SPI DMA transfers by removing wfi from DMA wait loop.
Addresses issue #1268.
2015-06-03 23:20:23 +01:00
Damien George
80f638fe19 tests: Add test for recursive iternext stack overflow. 2015-06-03 22:41:06 +01:00
Damien George
953c23b1bc py: Add stack check to mp_iternext, since it can be called recursively.
Eg, builtin map can map over a map, etc, and call iternext deeply.

Addresses issue #1294.
2015-06-03 22:19:41 +01:00
Damien George
181adc6a4e unix: Update .gitignore; now ignores coverage build. 2015-06-03 17:47:31 +01:00
Paul Sokolovsky
c36635c112 unix: Prepare upip frozen modules under build/. 2015-06-03 19:28:31 +03:00
Paul Sokolovsky
f8a39e3bb1 tools/make-frozen.py: Handle trailing slash in argument more reliably. 2015-06-03 19:28:31 +03:00
Damien George
0e6c89a5c8 tools: Add codestats.sh to compute code statistics such as size, speed. 2015-06-03 15:38:43 +00:00
Daniel Campora
cc20482aa9 cc3200: Add method to configure the servers timeout.
With network.server_timeout(secs) the timeout can be changed.
The default value is 300 secs. Minimmum accpeted is 5 secs.
Without params the function returns the current configured timeout.
2015-06-03 17:31:21 +02:00
Paul Sokolovsky
a546acda8c unix: Uncompress upip tarball to build directory. 2015-06-03 01:55:54 +03:00
Paul Sokolovsky
a32538bb66 esp8266: Do not call espconn_create in constructor of esp.socket.
Turns out this is supposed to be called only for UDP connections.

Patch by Josef Gajdusek.
2015-06-02 22:40:06 +03:00
Daniel Campora
2ffb6e1b15 cc3200: Fix 'MP_QSTR_sd' undeclared error when building for the LAUNCHXL. 2015-06-02 13:11:01 +02:00
Paul Sokolovsky
32ce72cb9e docs/uctypes: Typo fix. 2015-06-02 10:35:06 +03:00
Paul Sokolovsky
f8bce131c0 docs/uctypes: Fix API description errors.
"Structure class" is its descriptor, encoded as a dictionary. Then,
uctypes.struct() instantiates an actual object, and thus requires memory
address.
2015-06-02 10:30:01 +03:00
Paul Sokolovsky
0df20da4dd tools: Add upip 0.5.2 tarball.
So unix version, which now includes upip as a frozen module, can be built
without Internet connection.
2015-06-02 01:32:07 +03:00
Paul Sokolovsky
9456732b86 unix: Include upip as fronzen modules inside the standard interpreter.
MicroPython doesn't come with standard library included, so it is important
to be able to easily install needed package in a seamless manner. Bundling
package manager (upip) inside an executable solves this issue.

upip is bundled only with standard executable, not "minimal" or "fast"
builds.
2015-06-02 01:32:07 +03:00
Paul Sokolovsky
2fc1e64319 esp8266: Fix lost chars problem when block-xfering data (e.g., when pasting).
Pasting more or less sizable text into ESP8266 REPL leads to random chars
missing in the received input. Apparent cause is that using RTOS messages
to pass individual chars one by one is to slow and leads to UART FIFO
overflow. So, instead of passing chars one by one, use RTOS msg to signal
that input data is available in FIFO, and then let task handler to read
data directly from FIFO.

With this change, lost chars problem is gone, but the pasted text is
truncated after some position. At least 500 chars can be pasted reliably
(at 115200 baud), but 1K never pastes completely.
2015-06-01 23:57:19 +03:00
Dave Hylands
3ac2d06bd1 stmhal: Add support for UART5
I tested this on my CERB40 board and it seems to be working fine.
2015-06-01 00:14:46 +01:00
Paul Sokolovsky
18fda7b42f frozenmod: Include header with function prototypes. 2015-05-31 23:02:04 +03:00
Damien George
db52fd8e4d py: Wrap qstr defs in quotes to protect from C preprocessor.
This patch converts Q(abc) to "Q(abc)" to protect the abc from the
C preprocessor, then converts back after the preprocessor is finished.
So now we can safely put includes in mpconfig(port).h, and also
preprocess qstrdefsport.h (latter is now done also in this patch).

Addresses issue #1252.
2015-05-30 23:14:34 +01:00
Damien George
0ec8cf8e80 py/parsenum.c: Rename "raise" func to "raise_exc" to avoid name clash.
"raise" is a common word that was found to exist in a vendor's stdlib.
2015-05-30 23:13:16 +01:00
Damien George
4e4772bb5b py: Add further autodetection of endianess in mpconfig.h.
This patch was needed for gcc 4.4.
2015-05-30 23:12:30 +01:00
Damien George
26b512ea1b py: Get makeqstrdata.py and makeversionhdr.py running under Python 2.6.
These scripts should run under as wide a range of Python versions as
possible.
2015-05-30 23:11:16 +01:00
Josef Gajdusek
7d8edeff4e esp8266: Update to SDK version 1.1.0 (MIT-licensed).
1. Updated linker script, now user app appears to contain exception vector
table and oesn't work (faults) without it.
2. Commened out support for GPIO pulldown, which was removed in this SDK
version without clear explanation, but apparently because it was released
without proper validation, and now turns out it doesn't work as expected,
or there's a different function there.
2015-05-30 20:58:59 +03:00
Radomir Dopieralski
78ccb44a90 docs: Document esp module for ESP8266.
I document as much as I could guess from experiments and reading the
code for the ``esp`` module for the ESP8266 port of Micropython.

For now the tag has to be set manually with -t option when building,
when we have properly split documentation, there will be a separate
config file for esp8266 with that the tag "port_esp8266" set.

To build use:

make SPHINXOPTS="-t port_esp8266" html
2015-05-30 12:49:58 +01:00
stijn
278d22ce8f lib/mp-readline: Allow overriding implementation of cursor functions
Default implementation uses VT100-style sequences which are not implemented
by all terminals out there
2015-05-30 13:38:34 +03:00
stijn
9a522dda6e lib/mp-readline: Add implementation for deleting a character
xterm and others use the ESC[~3 sequence when pressing the delete key
2015-05-30 13:38:24 +03:00
stijn
100004eeaf unix: Print an extra newline to the output on ctrl-D
This assures the terminal prints it's prompt on a fresh line instead of
appending it to the uPy prompt after exit.
2015-05-30 13:38:17 +03:00
Paul Sokolovsky
6a664cb114 unix: minimal: Don't use readline support.
After switching to builtin readline support, "minimal" no longer builds, and
minimal doesn't really need readline support.
2015-05-30 13:13:43 +03:00
Paul Sokolovsky
51726b4d43 unix: Allow to override default sys.path value.
Using MICROPY_PY_SYS_PATH_DEFAULT macro define. A usecase is building a
distribution package, which should not have user home path by default in
sys.path. In such case, MICROPY_PY_SYS_PATH_DEFAULT can be defined on
make command-line (using CFLAGS_EXTRA).
2015-05-30 01:07:58 +03:00
Paul Sokolovsky
c02dc8b2c9 tools/make-frozen.py: Open files in binary mode. 2015-05-30 00:39:00 +03:00
Paul Sokolovsky
a8e7c03171 tools/make-frozen.py: Preserve directory hierarchy.
Currently, frozen packages are not supported, but eventually they should be,
so make sure to store complete directory hierarchy.
2015-05-30 00:23:46 +03:00
Paul Sokolovsky
f5ae384d4f bootstrap_upip.sh: Allow to install into a path given by argument. 2015-05-29 22:35:45 +03:00
Daniel Campora
84d11b5e53 cc3200: Add period set method to the Timer class. 2015-05-29 15:54:46 +02:00
Daniel Campora
417205623a cc3200: Fix incorrect type for the wake cause variable. 2015-05-29 15:54:16 +02:00
Daniel Campora
2f2c0a13fb cc3200: Clean up WLAN API. Make WLAN.info() an attrtuple. 2015-05-29 15:48:41 +02:00
Daniel Campora
622f241317 cc3200: Rename pyb.reset() to pyb.hard_reset() and add pyb.unique_id(). 2015-05-29 10:22:20 +02:00
Josef Gajdusek
286ced4c2f esp8266: Add a bunch of miscellaneous methods 2015-05-28 21:38:46 +03:00
Josef Gajdusek
25a8a42447 esp8266: Add pyb.ADC class 2015-05-28 21:31:37 +03:00
Josef Gajdusek
492fd5cb6b esp8266: Enable setting CPU frequency to 160MHz 2015-05-28 21:28:29 +03:00
Damien George
a16715ac62 tests: Add special tests to test mp_printf function to improve coverage. 2015-05-28 14:25:07 +00:00
Damien George
9ede4dcfbb tests: Add some tests for printing floats to improve coverage. 2015-05-28 14:24:47 +00:00
Damien George
79474c6b16 py: Remove unnecessary extra handling of padding of nan/inf.
C's printf will pad nan/inf differently to CPython.  Our implementation
originally conformed to C, now it conforms to CPython's way.

Tests for this are also added in this patch.
2015-05-28 14:22:12 +00:00
Damien George
2cae0f6290 py: Reduce size of mp_printf by eliminating unnecessary code.
Saves around 120 bytes on Thumb2 archs.
2015-05-28 13:54:56 +00:00
Daniel Campora
78744c4f7a cc3200: Remove WIPY-SD variant, and make the WiPy the default board. 2015-05-28 13:22:26 +02:00
Daniel Campora
2abb58d758 cc3200: Rename Pin.get_config() to Pin.info(). 2015-05-28 13:10:46 +02:00
Daniel Campora
1580e331ef cc3200: Make small changes in WLAN to improve the API. 2015-05-28 13:10:44 +02:00
Damien George
6d1ff7e966 tests: Add tests to create valid and invalid UART, I2C, SPI, CAN busses. 2015-05-28 11:06:12 +01:00
Damien George
17d9b5006d stmhal: Fix off-by-one error when checking for valid I2C and SPI bus. 2015-05-28 11:05:44 +01:00
Damien George
5a57447a8c ACKNOWLEDGEMENTS: Add 1 backer name to the file. 2015-05-28 08:20:36 +01:00
Dave Hylands
669dbca959 tools: Allow pyboard constructor to take a baudrate parameter.
This allows pyboard.py to be used over a UART interface
rather than just over a USB serial interface.
2015-05-27 23:01:28 +01:00
Damien George
70446f46c2 stmhal: Allow to name SPI busses, and give them names for pyboard. 2015-05-27 17:21:42 +01:00
Damien George
0e6f5e08e1 stmhal: Allow to name I2C busses, and give them names for pyboard. 2015-05-27 17:16:26 +01:00
Damien George
1775b65e07 stmhal: Remove PYBVxx defines and use config vars for UART/CAN names.
Now all stmhal-based boards can name their peripherals (if they want) to
any string.
2015-05-27 16:51:04 +01:00
Damien George
9ae3fc6523 unix: Add option to use uPy readline, and enable by default.
This gets uPy readline working with unix port, with tab completion and
history.  GNU readline is still supported, configure using
MICROPY_USE_READLINE variable.
2015-05-27 15:59:43 +01:00
Damien George
4a10214be2 unix: Factor out stdio and ctrl-C code to unix_mphal.c file. 2015-05-27 15:52:35 +01:00
Damien George
2acfb7c002 lib/mp-readline: Export readline_push_history function. 2015-05-27 15:06:17 +01:00
Daniel Campora
c754d8011d cc3200: Simplify SPI polarity and phase checks in constructor. 2015-05-27 09:45:32 +02:00
Daniel Campora
95104b0fbd cc3200: Add note about old revisions of the CC3200-LAUNCHXL. 2015-05-27 09:45:30 +02:00
Daniel Campora
d07de2d307 cc3200: Move the STDIO UART pin configuration to mpconfigboard.h. 2015-05-27 09:45:29 +02:00
Daniel Campora
9414f92fa9 cc3200: Fix I2C and SPI module references. 2015-05-27 09:45:27 +02:00
Daniel Campora
8096be089e cc3200: Add make_new method to the WDT. 2015-05-27 09:45:25 +02:00
Daniel Campora
fca3493442 cc3200: Add make_new method to the RTC, like in stmhal. 2015-05-27 09:45:24 +02:00
Daniel Campora
5a0c5f8fea cc3200: Use the WDT stall feature in debug mode only. 2015-05-27 09:45:22 +02:00
Daniel Campora
ec1f0e7551 cc3200: Use MCU reset instead of SOC reset.
I have seen the CC3200 hanging a couple of times, and according to TI
itself the SOC reset is not reliable, which explains my observations.
2015-05-27 09:45:21 +02:00
Josef Gajdusek
967f3230f5 esp8266: Move initialization to system_init_done_cb
Initializing too early caused some of the API functions (wifi_*) to fail
when called in main.py
2015-05-26 22:22:08 +03:00
Josef Gajdusek
59610c4004 esp8266: Add uos module
Currently implements only .uname()
2015-05-26 22:18:07 +03:00
Daniel Campora
fabe79f7af cc3200: Clean up exception handling. 2015-05-26 12:29:20 +02:00
Daniel Campora
124aa000af cc3200: Use polarity and phase instead of submode in the SPI construct. 2015-05-26 11:30:48 +02:00
Daniel Campora
2dd47239de cc3200: Make API more similar to stmhal.
In general the changes are:

1. Peripheral (UART, SPI, ADC, I2C, Timer) IDs start from 1, not zero.
2. Make I2C and SPI require the ID even when there's only one bus.
3. Make I2C and SPI accept 'mode' parameter even though only MASTER
   is supported.
2015-05-25 21:47:19 +02:00
Daniel Campora
6545336206 cc3200: Make the WDT aware of the servers sleep/wake state. 2015-05-25 21:14:54 +02:00
Daniel Campora
5cd34aca27 cc3200: Use the correct ADC channel index when creating the object. 2015-05-25 21:14:46 +02:00
Daniel Campora
95f19b4542 cc3200: Remove duplicated checks for boot.py and main.py existency. 2015-05-25 21:14:39 +02:00
Daniel Campora
90d7c4ef3d cc3200: Make HeartBeat.disable() thread safe. 2015-05-25 21:14:31 +02:00
Damien George
1a97f6721f py: Make makeversionhdr.py extract version from docs/conf.py if no git.
Addresses issue #1285.
2015-05-25 13:26:47 +01:00
Damien George
3c4b5d4281 stmhal: Implement sys.std{in,out,err}.buffer, for raw byte mode.
It's configurable and only enabled for stmhal port.
2015-05-24 14:31:33 +01:00
Dave Hylands
968b7dd173 stmhal: Detect disk full condition 2015-05-24 14:07:11 +01:00
Daniel Campora
3cb804de26 cc3200: Remove NIC abstraction layer.
That layer is nice, but the CC3200 doesn't need it and getting rid of
it saves ~200 bytes, which are more than welcome.
2015-05-24 11:44:08 +02:00
Daniel Campora
9f8c5456be cc3200: Reset the servers and close user sockets on WLAN disconection.
This is needed to avoid half-open connections.
2015-05-24 11:44:06 +02:00
Damien George
0d31bbc7fa stmhal: Make pendsv variable non-static so gcc-5 doesn't opt it away. 2015-05-23 17:42:58 +01:00
Daniel Campora
ed56b0baba cc3200: Finally unlock the full wake on WLAN feature set. 2015-05-22 19:53:33 +02:00
Daniel Campora
18030bd85d cc3200: Add own ubinascii module.
The reason to have our owm ubinascii module is so that later we
can add crc32 support using the hardware engine.
2015-05-22 09:56:11 +02:00
Daniel Campora
7bd273b818 extmod: Actually expose the ubinascii python methods. 2015-05-22 09:56:09 +02:00
Dave Hylands
a3a14b9db7 lib: Fix some issues in timeutils
In particular, dates prior to Mar 1, 2000 are screwed up.

The easiest way to see this is to do:

>>> import time
>>> time.localtime(0)
(2000, 1, 1, 0, 0, 0, 5, 1)
>>> time.localtime(1)
(2000, 1, 2, 233, 197, 197, 6, 2)

With this patch, we instead get:
>>> import time
>>> time.localtime(1)
(2000, 1, 1, 0, 0, 1, 5, 1)

Doh - In C % is NOT a modulo operator, it's a remainder operator.
2015-05-21 23:31:50 +03:00
Daniel Campora
6f1cffeb28 py: Remove hexdigest QSTR since the method has been removed as well. 2015-05-21 18:52:39 +02:00
Daniel Campora
7506db4ccb cc3200: Remove uhashlib.hexdigest(). 2015-05-21 18:51:57 +02:00
Paul Sokolovsky
2fddc68fdf moduhashlib: Remove not implemented .hexdigest().
Effect can be easily achieved by ubinsacii.hexlify(hash.digest()).
2015-05-21 17:20:26 +03:00
Daniel Campora
0f716aced7 extmod: Expose mod_binascii_hexlify() and mod_binascii_unhexlify(). 2015-05-21 17:19:41 +03:00
Damien George
a3c96c9252 pic16bit: Add readinto and readlines to qstrs. 2015-05-20 23:12:43 +01:00
Daniel Campora
e800db562f cc3200: Add uhashlib. Supports SHA1 and SHA256. 2015-05-20 11:44:24 +02:00
Daniel Campora
5e38b48dd6 cc3200: Fix time.localtime() so that it returns the correct fields. 2015-05-20 11:44:22 +02:00
Daniel Campora
56053c37cf cc3200: Rewrite WLAN.ifconfig(). Add WLAN.info() and WLAN.connections(). 2015-05-20 11:44:21 +02:00
Daniel Campora
514ba15d6a cc3200: Disable UCTYPES and enable ARRAY_SLICE_ASSIGN. 2015-05-20 11:44:19 +02:00
Dave Hylands
afaa66b657 py: Minor improvement to unichar_isxdigit
This drops the size of unicode_isxdigit from 0x1e + 0x02 filler to
0x14 bytes (so net code reduction of 12 bytes) and will make
unicode_is_xdigit perform slightly faster.
2015-05-20 09:31:22 +01:00
Dave Hylands
3ad94d6072 extmod: Add ubinascii.unhexlify
This also pulls out hex_digit from py/lexer.c and makes unichar_hex_digit
2015-05-20 09:29:22 +01:00
Dave Hylands
97ce883217 tools: Add exec_raw_no_follow to pyboard.py. 2015-05-18 11:39:57 +01:00
stijn
861670ba2a py: Implement mp_format_float for doubles and use where appropriate
This allows using (almost) the same code for printing floats everywhere,
removes the dependency on sprintf and uses just snprintf and
applies an msvc-specific fix for snprintf in a single place so
nan/inf are now printed correctly.
2015-05-17 21:47:11 +01:00
Kaspar Schleiser
f5dd6f7f37 py/binary: Make return type of mp_binary_get_size size_t instead of int.
Fixes sign-compare warning.
2015-05-17 18:12:19 +01:00
Kaspar Schleiser
b5cef5c7ea py/objobject: Don't make locals_dict if there's nothing to go in it. 2015-05-17 17:48:47 +01:00
Kaspar Schleiser
cf5112b26f py: Change _mp_obj_fun_builtin_t.fun to function pointer.
ISO C forbids conversion between function pointers and void*, gcc
-pedantic triggers a warning.
2015-05-17 17:42:04 +01:00
Damien George
44e7cbf019 py: Clean up declarations of str type/funcs that are also in unicode.
Background: trying to make an amalgamation of all the code gave some
errors with redefined types and inconsistent use of static.
2015-05-17 16:44:24 +01:00
Daniel Campora
6f848b6dba cc3200: Set the timer edge count interrupt value in the calbback const. 2015-05-17 16:11:12 +02:00
Daniel Campora
95a4f61499 cc3200: Make sure RTC wake value is >= 1ms. 2015-05-17 16:09:27 +02:00
Daniel Campora
c27dc38e85 cc3200: Re-name 'intmode' to 'mode' in the callback API. 2015-05-17 14:49:17 +02:00
Daniel Campora
cd3f2523f1 cc3200: Disable WLAN.urn() by default.
Can be enabled by defining MICROPY_PORT_WLAN_URN=1 in mpconfigport.h.
2015-05-17 14:20:24 +02:00
Daniel Campora
a379b6ed11 cc3200: Add optional timeout param to WLAN.connect(). 2015-05-17 14:05:44 +02:00
Daniel Campora
fb9e4cf463 cc3200: Make sure to handle all pending pin interrupts.
When entering the interrupt handler of a given GPIO port, more than
one pin could have pending interrupts, therefore care must be taken
to service each interrupt one by one before leaving.
2015-05-17 13:42:15 +02:00
Daniel Campora
8e611e8414 cc3200: Add Timer module. Supports free running, PWM and capture modes. 2015-05-17 12:34:49 +02:00
Daniel Campora
9466e154b4 cc3200: Fix power mode param check in the UART callback constructor. 2015-05-17 12:26:40 +02:00
Daniel Campora
2b62707051 cc3200: Add os.rename() 2015-05-17 12:22:17 +02:00
Paul Sokolovsky
ebf8dc6b03 Revert "unix: Include stdio.h to allow easy debugging with printf()."
This reverts commit 8fbabab1a8. Turned to
cause problems on MacOSX.
2015-05-17 09:59:06 +03:00
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
933 changed files with 202806 additions and 52354 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

@@ -261,6 +261,7 @@ today. The names appear in order of pledging.
503 skakz
504 Chad Cooper
505 Makhan Virdi, mlvirdi.com, InfinityXLabs.com, USA
506 Glenn Ruben Bakke, Norway
507 Alasdair Allan
509 dlbrandon
511 Dr J Garcia, Sweden
@@ -339,6 +340,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 +377,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 +420,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 +481,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 +695,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 +895,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

View File

@@ -33,16 +33,17 @@ Braces:
closing brace.
Header files:
- Try to stick to the Plan 9 header style, where header files do not
include other header files.
- Don't protect a header file from multiple inclusion with #if directives.
- Header files should be protected from multiple inclusion with #if
directives. See an existing header for naming convention.
Type names and declarations:
- When defining a type, put '_t' after it.
Names:
- Use underscore_case, not camelCase for all names.
- Use CAPS_WITH_UNDERSCORE for enums and macros.
- When defining a type use underscore_case and put '_t' after it.
Integer types: Micro Python runs on 32 and 64 bit machines (and one day
maybe 16 bit), so it's important to use the correctly-sized (and signed)
integer types. The general guidelines are:
Integer types: Micro Python runs on 16, 32, and 64 bit machines, so it's
important to use the correctly-sized (and signed) integer types. The
general guidelines are:
- For most cases use mp_int_t for signed and mp_uint_t for unsigned
integer values. These are guaranteed to be machine-word sized and
therefore big enough to hold the value from a Micro Python small-int
@@ -51,19 +52,31 @@ integer types. The general guidelines are:
- You can use int/uint, but remember that they may be 16-bits wide.
- If in doubt, use mp_int_t/mp_uint_t.
Comments:
- Be concise and only write comments for things that are not obvious.
- Use `// ` prefix, NOT `/* ... */`. No extra fluff.
Memory allocation:
- Use m_new, m_renew, m_del (and friends) to allocate and free heap memory.
These macros are defined in py/misc.h.
Examples
--------
Braces and spaces:
Braces, spaces, names and comments:
int foo(int x, int y) {
if (x < y) {
foo(y, x);
#define TO_ADD (123)
// This function will always recurse indefinitely and is only used to show
// coding style
int foo_function(int x, int some_value) {
if (x < some_value) {
foo(some_value, x);
} else {
foo(x + 1, y - 1);
foo(x + TO_ADD, some_value - 1);
}
for (int i = 0; i < x; i++) {
for (int my_counter = 0; my_counter < x; my_counter++) {
}
}

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,9 @@ 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.
- esp8266/ -- an experimental port for ESP8266 WiFi modules.
- unix-cpy/ -- a version of Micro Python that outputs bytecode (for testing).
- tests/ -- test framework and test scripts.
- tools/ -- various tools, including the pyboard.py module.
@@ -62,7 +65,7 @@ as ARM and MIPS. Making full-featured port to another architecture requires
writing some assembly code for the exception handling and garbage collection.
Alternatively, fallback implementation based on setjmp/longjmp can be used.
To build:
To build (*):
$ cd unix
$ make
@@ -76,10 +79,19 @@ Run complete testsuite:
$ make test
Debian/Ubuntu/Mint derivative Linux distros will require build-essentials and
libreadline-dev packages installed. To build FFI (Foreign Function Interface)
module, libffi-dev and pkg-config packages are required. If you have problems
with some dependencies, they can be disabled in unix/mpconfigport.mk .
Unix version comes with a builtin package manager called upip, e.g.:
$ ./micropython -m upip install micropython-pystone
$ ./micropython -m pystone
Browse available modules on
[PyPI](https://pypi.python.org/pypi?%3Aaction=search&term=micropython).
Standard library modules come from
[micropython-lib](https://github.com/micropython/micropython-lib) project.
(*) Debian/Ubuntu/Mint derivative Linux distros will require build-essentials,
libffi-dev and pkg-config packages installed. If you have problems with some
dependencies, they can be disabled in unix/mpconfigport.mk .
The STM version
---------------
@@ -119,6 +131,8 @@ preferably in a virtualenv:
In `micropython/docs`, build the docs:
make html
make MICROPY_PORT=<port_name> BUILDDIR=<port_name>/build html
You'll find the index page at `micropython/docs/build/html/index.html`.
Where `<port_name>` can be `unix`, `pyboard`, `wipy` or `esp8266`.
You'll find the index page at `micropython/docs/<port_name>/build/html/index.html`.

View File

@@ -6,9 +6,8 @@
#include "py/compile.h"
#include "py/runtime.h"
#include "py/repl.h"
#include "py/pfenv.h"
void do_str(const char *src) {
void do_str(const char *src, mp_parse_input_kind_t input_kind) {
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
if (lex == NULL) {
return;
@@ -17,19 +16,20 @@ void do_str(const char *src) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
qstr source_name = lex->source_name;
mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT);
mp_parse_node_t pn = mp_parse(lex, input_kind);
mp_obj_t module_fun = mp_compile(pn, source_name, MP_EMIT_OPT_NONE, true);
mp_call_function_0(module_fun);
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);
}
}
int main(int argc, char **argv) {
mp_init();
do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\n')");
do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\\n')", MP_PARSE_SINGLE_INPUT);
do_str("for i in range(10):\n print(i)", MP_PARSE_FILE_INPUT);
mp_deinit();
return 0;
}

View File

@@ -2,6 +2,7 @@
// options to control how Micro Python is built
#define MICROPY_QSTR_BYTES_IN_HASH (1)
#define MICROPY_ALLOC_PATH_MAX (512)
#define MICROPY_EMIT_X64 (0)
#define MICROPY_EMIT_THUMB (0)
@@ -18,15 +19,19 @@
#define MICROPY_ENABLE_SOURCE_LINE (0)
#define MICROPY_ENABLE_DOC_STRING (0)
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0)
#define MICROPY_PY_BUILTINS_BYTEARRAY (0)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (0)
#define MICROPY_PY_BUILTINS_ENUMERATE (0)
#define MICROPY_PY_BUILTINS_FROZENSET (0)
#define MICROPY_PY_BUILTINS_REVERSED (0)
#define MICROPY_PY_BUILTINS_SET (0)
#define MICROPY_PY_BUILTINS_SLICE (0)
#define MICROPY_PY_BUILTINS_PROPERTY (0)
#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

@@ -1,10 +1,11 @@
# Select the board to build for: if not given on the command line,
# then default to LAUNCHXL
BOARD ?= LAUNCHXL
# then default to WIPY
BOARD ?= WIPY
ifeq ($(wildcard boards/$(BOARD)/.),)
$(error Invalid BOARD specified)
endif
# Make 'release' the default build type
BTYPE ?= release
# If the build directory is not given, make it reflect the board name.
@@ -20,7 +21,7 @@ CFLAGS = -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTE
CFLAGS += -g -ffunction-sections -fdata-sections -fno-common -fsigned-char -mno-unaligned-access
CFLAGS += -Iboards/$(BOARD)
LDFLAGS = -Wl,-nostdlib -Wl,--gc-sections -Wl,-Map=$@.map --specs=nano.specs
LDFLAGS = -Wl,-nostdlib -Wl,--gc-sections -Wl,-Map=$@.map
ifeq ($(BTARGET), application)
# qstr definitions (must come before including py.mk)

View File

@@ -1,6 +1,6 @@
# Build Instructions for the CC3200
Currently the CC3200 port of Micro Python builds under Linux and OSX and not under Windows.
Currently the CC3200 port of Micro Python builds under Linux and OSX **but not under Windows**.
The tool chain required for the build can be found at <https://launchpad.net/gcc-arm-embedded>.
@@ -13,29 +13,42 @@ In order to debug the port specific code, optimizations need to be disabled on t
port file (check the Makefile for specific details). You can use CCS from TI.
Use the CC3200.ccxml file supplied with this distribution for the debuuger configuration.
```bash
make BTARGET=application BTYPE=debug
make BTARGET=application BTYPE=debug BOARD=LAUNCHXL
```
## To build an image suitable to be flashed to the device:
```bash
make BTARGET=application BTYPE=release
make BTARGET=application BTYPE=release BOARD=LAUNCHXL
```
## Building the bootloader
```bash
make BTARGET=bootloader BTYPE=release
make BTARGET=bootloader BTYPE=release BOARD=LAUNCHXL
```
## Regarding old revisions of the CC3200-LAUNCHXL
First silicon (pre-release) revisions of the CC3200 had issues with the ram blocks, and Micro Python cannot run
there. Make sure to use a **v4.1 (or higer) LAUNCHXL board** when trying this port, otherwise it won't work.
## Flashing the CC3200
- 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).
- Mark the following files for erasing: `/cert/ca.pem`, `/cert/client.pm`, `/cert/private.key` and `/tmp/pac.bin`.
- 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.pem`, `/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.
## Updating the board to with new software version
- Make sure the board is running and connected to the same network as the computer.
```bash
make BTARGET=application BTYPE=release BOARD=LAUNCHXL WIPY_IP=192.168.1.1 WIPY_USER=micro WIPY_PWD=python deploy
```
If `WIPY_IP`, `WIPY_USER` or `WIPY_PWD` are omitted the default values (the ones shown above) will be used.
## Playing with MicroPython and the CC3200:
Once the software is running, you have two options to access the MicroPython REPL:
@@ -43,15 +56,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 +76,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

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

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
@@ -73,6 +75,7 @@ APP_HAL_SRC_C = $(addprefix hal/,\
)
APP_MISC_SRC_C = $(addprefix misc/,\
antenna.c \
FreeRTOSHooks.c \
pin_named_pins.c \
help.c \
@@ -80,14 +83,16 @@ APP_MISC_SRC_C = $(addprefix misc/,\
mperror.c \
mpexception.c \
mpsystick.c \
pin_defs_cc3200.c \
)
APP_MODS_SRC_C = $(addprefix mods/,\
modnetwork.c \
moduhashlib.c \
modubinascii.c \
modpyb.c \
moduos.c \
modusocket.c \
modussl.c \
modutime.c \
modwlan.c \
pybadc.c \
@@ -97,6 +102,7 @@ APP_MODS_SRC_C = $(addprefix mods/,\
pybsd.c \
pybsleep.c \
pybspi.c \
pybtimer.c \
pybuart.c \
pybwdt.c \
)
@@ -122,6 +128,7 @@ APP_TELNET_SRC_C = $(addprefix telnet/,\
)
APP_UTIL_SRC_C = $(addprefix util/,\
cryptohash.c \
fifo.c \
gccollect.c \
random.c \
@@ -140,7 +147,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 +165,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))
@@ -188,6 +198,7 @@ $(BUILD)/FreeRTOS/Source/%.o: CFLAGS += -Os
$(BUILD)/ftp/%.o: CFLAGS += -Os
$(BUILD)/hal/%.o: CFLAGS += -Os
$(BUILD)/misc/%.o: CFLAGS += -Os
$(BUILD)/mods/%.o: CFLAGS += -Os
$(BUILD)/py/%.o: CFLAGS += -Os
$(BUILD)/simplelink/%.o: CFLAGS += -Os
$(BUILD)/drivers/cc3100/%.o: CFLAGS += -Os
@@ -205,8 +216,18 @@ endif
SHELL = bash
APP_SIGN = appsign.sh
UPDATE_WIPY ?= tools/update-wipy.py
WIPY_IP ?= '192.168.1.1'
WIPY_USER ?= 'micro'
WIPY_PWD ?= 'python'
all: $(BUILD)/MCUIMG.BIN
all: $(BUILD)/mcuimg.bin
.PHONY: deploy
deploy: $(BUILD)/mcuimg.bin
$(ECHO) "Writing $< to the board"
$(Q)$(PYTHON) $(UPDATE_WIPY) --verify --ip $(WIPY_IP) --user $(WIPY_USER) --password $(WIPY_PWD) --file $<
$(BUILD)/application.axf: $(OBJ) $(LINKER_SCRIPT)
$(ECHO) "LINK $@"
@@ -217,7 +238,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

@@ -33,18 +33,23 @@
#define MICROPY_HW_HAS_SDCARD (0)
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ANTENNA_DIVERSITY (0)
#define MICROPY_STDIO_UART PYB_UART_0
#define MICROPY_STDIO_UART 1
#define MICROPY_STDIO_UART_BAUD 115200
#define MICROPY_STDIO_UART_RX_BUF_SIZE 128
#define MICROPY_STDIO_UART_TX_PIN (pin_GP1)
#define MICROPY_STDIO_UART_RX_PIN (pin_GP2)
#define MICROPY_STDIO_UART_TX_PIN_AF PIN_MODE_3
#define MICROPY_STDIO_UART_RX_PIN_AF PIN_MODE_3
#define MICROPY_SYS_LED_PRCM PRCM_GPIOA1
#define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA2
#define MICROPY_SYS_LED_PORT GPIOA1_BASE
#define MICROPY_SAFE_BOOT_PORT GPIOA2_BASE
#define MICROPY_SYS_LED_GPIO pin_GPIO9
#define MICROPY_SYS_LED_PIN_NUM PIN_64 // GPIO9
#define MICROPY_SAFE_BOOT_PIN_NUM PIN_15 // GPIO22
#define MICROPY_SYS_LED_GPIO pin_GP9
#define MICROPY_SYS_LED_PIN_NUM PIN_64 // GP9
#define MICROPY_SAFE_BOOT_PIN_NUM PIN_15 // GP22
#define MICROPY_SYS_LED_PORT_PIN GPIO_PIN_1
#define MICROPY_SAFE_BOOT_PORT_PIN GPIO_PIN_6

View File

@@ -1,51 +0,0 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2015 Daniel Campora
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#define LAUNCHXL
#define MICROPY_HW_BOARD_NAME "WiPy-SD"
#define MICROPY_HW_MCU_NAME "CC3200"
#define MICROPY_HW_HAS_SDCARD (1)
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_STDIO_UART PYB_UART_0
#define MICROPY_STDIO_UART_BAUD 115200
#define MICROPY_STDIO_UART_RX_BUF_SIZE 128
#define MICROPY_SYS_LED_PRCM PRCM_GPIOA3
#define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA3
#define MICROPY_SYS_LED_PORT GPIOA3_BASE
#define MICROPY_SAFE_BOOT_PORT GPIOA3_BASE
#define MICROPY_SYS_LED_GPIO pin_GPIO25
#define MICROPY_SYS_LED_PIN_NUM PIN_21 // GPIO25 (SOP2)
#define MICROPY_SAFE_BOOT_PIN_NUM PIN_18 // GPIO28
#define MICROPY_SYS_LED_PORT_PIN GPIO_PIN_1
#define MICROPY_SAFE_BOOT_PORT_PIN GPIO_PIN_4
#define MICROPY_PORT_SFLASH_BLOCK_COUNT 96

View File

@@ -1,25 +0,0 @@
L2,GPIO2
L3,GPIO1
L4,GPIO23
L5,GPIO24
L6,GPIO11
L7,GPIO12
L8,GPIO13
L9,GPIO14
L10,GPIO15
L11,GPIO16
L12,GPIO17
L13,GPIO22
L14,GPIO28
R4,GPIO10
R5,GPIO9
R6,GPIO8
R7,GPIO7
R8,GPIO6
R9,GPIO30
R10,GPIO31
R11,GPIO3
R12,GPIO0
R13,GPIO4
R14,GPIO5
HBL,GPIO25
1 L2 GPIO2
2 L3 GPIO1
3 L4 GPIO23
4 L5 GPIO24
5 L6 GPIO11
6 L7 GPIO12
7 L8 GPIO13
8 L9 GPIO14
9 L10 GPIO15
10 L11 GPIO16
11 L12 GPIO17
12 L13 GPIO22
13 L14 GPIO28
14 R4 GPIO10
15 R5 GPIO9
16 R6 GPIO8
17 R7 GPIO7
18 R8 GPIO6
19 R9 GPIO30
20 R10 GPIO31
21 R11 GPIO3
22 R12 GPIO0
23 R13 GPIO4
24 R14 GPIO5
25 HBL GPIO25

View File

@@ -25,26 +25,23 @@
* THE SOFTWARE.
*/
#define LAUNCHXL
#define WIPY
#define MICROPY_HW_BOARD_NAME "WiPy"
#define MICROPY_HW_MCU_NAME "CC3200"
#define MICROPY_HW_HAS_SDCARD (0)
#define MICROPY_HW_HAS_SDCARD (1)
#define MICROPY_HW_ENABLE_RNG (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_STDIO_UART PYB_UART_0
#define MICROPY_STDIO_UART_BAUD 115200
#define MICROPY_STDIO_UART_RX_BUF_SIZE 128
#define MICROPY_HW_ANTENNA_DIVERSITY (1)
#define MICROPY_SYS_LED_PRCM PRCM_GPIOA3
#define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA3
#define MICROPY_SYS_LED_PORT GPIOA3_BASE
#define MICROPY_SAFE_BOOT_PORT GPIOA3_BASE
#define MICROPY_SYS_LED_GPIO pin_GPIO25
#define MICROPY_SYS_LED_PIN_NUM PIN_21 // GPIO25 (SOP2)
#define MICROPY_SAFE_BOOT_PIN_NUM PIN_18 // GPIO28
#define MICROPY_SYS_LED_GPIO pin_GP25
#define MICROPY_SYS_LED_PIN_NUM PIN_21 // GP25 (SOP2)
#define MICROPY_SAFE_BOOT_PIN_NUM PIN_18 // GP28
#define MICROPY_SYS_LED_PORT_PIN GPIO_PIN_1
#define MICROPY_SAFE_BOOT_PORT_PIN GPIO_PIN_4

View File

@@ -1,25 +1,25 @@
L2,GPIO2
L3,GPIO1
L4,GPIO23
L5,GPIO24
L6,GPIO11
L7,GPIO12
L8,GPIO13
L9,GPIO14
L10,GPIO15
L11,GPIO16
L12,GPIO17
L13,GPIO22
L14,GPIO28
R4,GPIO10
R5,GPIO9
R6,GPIO8
R7,GPIO7
R8,GPIO6
R9,GPIO30
R10,GPIO31
R11,GPIO3
R12,GPIO0
R13,GPIO4
R14,GPIO5
HBL,GPIO25
L2,GP2
L3,GP1
L4,GP23
L5,GP24
L6,GP11
L7,GP12
L8,GP13
L9,GP14
L10,GP15
L11,GP16
L12,GP17
L13,GP22
L14,GP28
R4,GP10
R5,GP9
R6,GP8
R7,GP7
R8,GP6
R9,GP30
R10,GP31
R11,GP3
R12,GP0
R13,GP4
R14,GP5
HBL,GP25
1 L2 GPIO2 GP2
2 L3 GPIO1 GP1
3 L4 GPIO23 GP23
4 L5 GPIO24 GP24
5 L6 GPIO11 GP11
6 L7 GPIO12 GP12
7 L8 GPIO13 GP13
8 L9 GPIO14 GP14
9 L10 GPIO15 GP15
10 L11 GPIO16 GP16
11 L12 GPIO17 GP17
12 L13 GPIO22 GP22
13 L14 GPIO28 GP28
14 R4 GPIO10 GP10
15 R5 GPIO9 GP9
16 R6 GPIO8 GP8
17 R7 GPIO7 GP7
18 R8 GPIO6 GP6
19 R9 GPIO30 GP30
20 R10 GPIO31 GP31
21 R11 GPIO3 GP3
22 R12 GPIO0 GP0
23 R13 GPIO4 GP4
24 R14 GPIO5 GP5
25 HBL GPIO25 GP25

View File

@@ -1,25 +1,25 @@
Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,ADC
1,GPIO10,GPIO10,GPIO10,I2C_SCL,,GT_PWM06,,,SDCARD_CLK,UART1_TX,,,,,GT_CCP01,,,,
2,GPIO11,GPIO11,GPIO11,I2C_SDA,,GT_PWM07,pXCLK(XVCLK),,SDCARD_CMD,UART1_RX,,,,,GT_CCP02,McAFSX,,,
3,GPIO12,GPIO12,GPIO12,,,McACLK,pVS(VSYNC),I2C_SCL,,UART0_TX,,,,,GT_CCP03,,,,
4,GPIO13,GPIO13,GPIO13,,,,pHS(HSYNC),I2C_SDA,,UART0_RX,,,,,GT_CCP04,,,,
5,GPIO14,GPIO14,GPIO14,,,,pDATA8(CAM_D4),2C_SCL,,GSPI_CLK,,,,,GT_CCP05,,,,
6,GPIO15,GPIO15,GPIO15,,,,pDATA9(CAM_D5),I2C_SDA,,GSPI_MISO,,,,,,GT_CCP06,,,
7,GPIO16,GPIO16,GPIO16,,,,pDATA10(CAM_D6),UART1_TX,,GSPI_MOSI,,,,,,GT_CCP07,,,
8,GPIO17,GPIO17,GPIO17,,,,pDATA11(CAM_D7),UART1_RX,,GSPI_CS,,,,,,,,,
1,GP10,GP10,GP10,I2C_SCL,,GT_PWM06,,,SDCARD_CLK,UART1_TX,,,,,GT_CCP01,,,,
2,GP11,GP11,GP11,I2C_SDA,,GT_PWM07,pXCLK(XVCLK),,SDCARD_CMD,UART1_RX,,,,,GT_CCP02,McAFSX,,,
3,GP12,GP12,GP12,,,McACLK,pVS(VSYNC),I2C_SCL,,UART0_TX,,,,,GT_CCP03,,,,
4,GP13,GP13,GP13,,,,pHS(HSYNC),I2C_SDA,,UART0_RX,,,,,GT_CCP04,,,,
5,GP14,GP14,GP14,,,,pDATA8(CAM_D4),2C_SCL,,GSPI_CLK,,,,,GT_CCP05,,,,
6,GP15,GP15,GP15,,,,pDATA9(CAM_D5),I2C_SDA,,GSPI_MISO,,,,,,GT_CCP06,,,
7,GP16,GP16,GP16,,,,pDATA10(CAM_D6),UART1_TX,,GSPI_MOSI,,,,,,GT_CCP07,,,
8,GP17,GP17,GP17,,,,pDATA11(CAM_D7),UART1_RX,,GSPI_CS,,,,,,,,,
9,VDD_DIG1,VDD_DIG1,VDD_DIG1,,,,,,,,,,,,,,,,
10,VIN_IO1,VIN_IO1,VIN_IO1,,,,,,,,,,,,,,,,
11,FLASH_SPI_CLK,FLASH_SPI_CLK,FLASH_SPI_CLK,,,,,,,,,,,,,,,,
12,FLASH_SPI_DOUT,FLASH_SPI_DOUT,FLASH_SPI_DOUT,,,,,,,,,,,,,,,,
13,FLASH_SPI_DIN,FLASH_SPI_DIN,FLASH_SPI_DIN,,,,,,,,,,,,,,,,
14,FLASH_SPI_CS,FLASH_SPI_CS,FLASH_SPI_CS,,,,,,,,,,,,,,,,
15,GPIO22,GPIO22,GPIO22,,,,,GT_CCP04,,McAFSX,,,,,,,,,
16,GPIO23,TDI,GPIO23,TDI,UART1_TX,,,,,,,2C_SCL,,,,,,,
17,GPIO24,TDO,GPIO24,TDO,UART1_RX,,GT_CCP06,PWM0,McAFSX,,,I2C_SDA,,,,,,,
18,GPIO28,GPIO28,GPIO28,,,,,,,,,,,,,,,,
15,GP22,GP22,GP22,,,,,GT_CCP04,,McAFSX,,,,,,,,,
16,GP23,TDI,GP23,TDI,UART1_TX,,,,,,,2C_SCL,,,,,,,
17,GP24,TDO,GP24,TDO,UART1_RX,,GT_CCP06,PWM0,McAFSX,,,I2C_SDA,,,,,,,
18,GP28,GP28,GP28,,,,,,,,,,,,,,,,
19,TCK,TCK,,TCK,,,,,,,GT_PWM03,,,,,,,,
20,GPIO29,TMS,GPIO29,TMS,,,,,,,,,,,,,,,
21,GPIO25,SOP2,GPIO25,,McAFSX,,,,,,,GT_PWM02,,,,,,,
20,GP29,TMS,GP29,TMS,,,,,,,,,,,,,,,
21,GP25,SOP2,GP25,,McAFSX,,,,,,,GT_PWM02,,,,,,,
22,WLAN_XTAL_N,WLAN_XTAL_N,WLAN_XTAL_N,,,,,,,,,,,,,,,,
23,WLAN_XTAL_P,WLAN_XTAL_P,WLAN_XTAL_P,,,,,,,,,,,,,,,,
24,VDD_PLL,VDD_PLL,VDD_PLL,,,,,,,,,,,,,,,,
@@ -43,24 +43,24 @@ Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF1
42,DCDC_PA_OUT,DCDC_PA_O UT,DCDC_PA_O UT,,,,,,,,,,,,,,,,
43,DCDC_DIG_SW,DCDC_DIG_ SW,DCDC_DIG_ SW,,,,,,,,,,,,,,,,
44,VIN_DCDC_DIG,VIN_DCDC_ DIG,VIN_DCDC_ DIG,,,,,,,,,,,,,,,,
45,GPIO31,DCDC_ANA2_SW_P,GPIO31,,UART1_RX,,,,McAXR0,GSPI_CLK,,UART0_RX,,,McAFSX,,,,
45,GP31,DCDC_ANA2_SW_P,GP31,,UART1_RX,,,,McAXR0,GSPI_CLK,,UART0_RX,,,McAFSX,,,,
46,DCDC_ANA2_SW_N,DCDC_ANA2_SW_N,DCDC_ANA2_SW_N,,,,,,,,,,,,,,,,
47,VDD_ANA2,VDD_ANA2,VDD_ANA2,,,,,,,,,,,,,,,,
48,VDD_ANA1,VDD_ANA1,VDD_ANA1,,,,,,,,,,,,,,,,
49,VDD_RAM,VDD_RAM,VDD_RAM,,,,,,,,,,,,,,,,
50,GPIO0,GPIO0,GPIO0,,,UART0_RTS,McAXR0,,McAXR1,GT_CCP00,,GSPI_CS,UART1_RTS,,UART0_CTS,,,,
50,GP0,GP0,GP0,,,UART0_RTS,McAXR0,,McAXR1,GT_CCP00,,GSPI_CS,UART1_RTS,,UART0_CTS,,,,
51,RTC_XTAL_P,RTC_XTAL_P,RTC_XTAL_P,,,,,,,,,,,,,,,,
52,RTC_XTAL_N,RTC_XTAL_N,GPIO32,,McACLK,,McAXR0,,UART0_RTS,,GSPI_MOSI,,,,,,,,
53,GPIO30,GPIO30,GPIO30,,McACLK,McAFSX,GT_CCP05,,,GSPI_MISO,,UART0_TX,,,,,,,
52,RTC_XTAL_N,RTC_XTAL_N,GP32,,McACLK,,McAXR0,,UART0_RTS,,GSPI_MOSI,,,,,,,,
53,GP30,GP30,GP30,,McACLK,McAFSX,GT_CCP05,,,GSPI_MISO,,UART0_TX,,,,,,,
54,VIN_IO2,VIN_IO2,VIN_IO2,,,,,,,,,,,,,,,,
55,GPIO1,GPIO1,GPIO1,,,GSPI_MISO,pCLK (PIXCLK),,UART1_TX,GT_CCP01,,,,,,,,,
55,GP1,GP1,GP1,,,GSPI_MISO,pCLK (PIXCLK),,UART1_TX,GT_CCP01,,,,,,,,,
56,VDD_DIG2,VDD_DIG2,VDD_DIG2,,,,,,,,,,,,,,,,
57,GPIO2,GPIO2,GPIO2,,,UART0_RX,,,UART1_RX,GT_CCP02,,,,,,,,,ADC_CH0
58,GPIO3,GPIO3,GPIO3,,,,pDATA7(CAM_D3),,UART1_TX,,,,,,,,,,ADC_CH1
59,GPIO4,GPIO4,GPIO4,,,,pDATA6(CAM_D2),,UART1_RX,,,,,,,,,,ADC_CH2
60,GPIO5,GPIO5,GPIO5,,,,pDATA5(CAM_D1),,McAXR1,GT_CCP05,,,,,,,,,ADC_CH3
61,GPIO6,GPIO6,GPIO6,,,UART1_CTS,pDATA4(CAM_D0),UART0_RTS,UART0_CTS,GT_CCP06,,,,,,,,,
62,GPIO7,GPIO7,GPIO7,,,UART1_RTS,,,,,,,UART0_RTS,UART0_TX,,McACLKX,,,
63,GPIO8,GPIO8,GPIO8,,,,,,SDCARD_IRQ,McAFSX,,,,,GT_CCP06,,,,
64,GPIO9,GPIO9,GPIO9,,,GT_PWM05,,,SDCARD_DATA,McAXR0,,,,,GT_CCP00,,,,
57,GP2,GP2,GP2,,,UART0_RX,,,UART1_RX,GT_CCP02,,,,,,,,,ADC_CH0
58,GP3,GP3,GP3,,,,pDATA7(CAM_D3),,UART1_TX,,,,,,,,,,ADC_CH1
59,GP4,GP4,GP4,,,,pDATA6(CAM_D2),,UART1_RX,,,,,,,,,,ADC_CH2
60,GP5,GP5,GP5,,,,pDATA5(CAM_D1),,McAXR1,GT_CCP05,,,,,,,,,ADC_CH3
61,GP6,GP6,GP6,,,UART1_CTS,pDATA4(CAM_D0),UART0_RTS,UART0_CTS,GT_CCP06,,,,,,,,,
62,GP7,GP7,GP7,,,UART1_RTS,,,,,,,UART0_RTS,UART0_TX,,McACLKX,,,
63,GP8,GP8,GP8,,,,,,SDCARD_IRQ,McAFSX,,,,,GT_CCP06,,,,
64,GP9,GP9,GP9,,,GT_PWM05,,,SDCARD_DATA,McAXR0,,,,,GT_CCP00,,,,
65,GND_TAB,GND_TAB,GND_TAB,,,,,,,,,,,,,,,,
1 Pin Name Default AF0 AF1 AF2 AF3 AF4 AF5 AF6 AF7 AF8 AF9 AF10 AF11 AF12 AF13 AF14 AF15 ADC
2 1 GPIO10 GP10 GPIO10 GP10 GPIO10 GP10 I2C_SCL GT_PWM06 SDCARD_CLK UART1_TX GT_CCP01
3 2 GPIO11 GP11 GPIO11 GP11 GPIO11 GP11 I2C_SDA GT_PWM07 pXCLK(XVCLK) SDCARD_CMD UART1_RX GT_CCP02 McAFSX
4 3 GPIO12 GP12 GPIO12 GP12 GPIO12 GP12 McACLK pVS(VSYNC) I2C_SCL UART0_TX GT_CCP03
5 4 GPIO13 GP13 GPIO13 GP13 GPIO13 GP13 pHS(HSYNC) I2C_SDA UART0_RX GT_CCP04
6 5 GPIO14 GP14 GPIO14 GP14 GPIO14 GP14 pDATA8(CAM_D4) 2C_SCL GSPI_CLK GT_CCP05
7 6 GPIO15 GP15 GPIO15 GP15 GPIO15 GP15 pDATA9(CAM_D5) I2C_SDA GSPI_MISO GT_CCP06
8 7 GPIO16 GP16 GPIO16 GP16 GPIO16 GP16 pDATA10(CAM_D6) UART1_TX GSPI_MOSI GT_CCP07
9 8 GPIO17 GP17 GPIO17 GP17 GPIO17 GP17 pDATA11(CAM_D7) UART1_RX GSPI_CS
10 9 VDD_DIG1 VDD_DIG1 VDD_DIG1
11 10 VIN_IO1 VIN_IO1 VIN_IO1
12 11 FLASH_SPI_CLK FLASH_SPI_CLK FLASH_SPI_CLK
13 12 FLASH_SPI_DOUT FLASH_SPI_DOUT FLASH_SPI_DOUT
14 13 FLASH_SPI_DIN FLASH_SPI_DIN FLASH_SPI_DIN
15 14 FLASH_SPI_CS FLASH_SPI_CS FLASH_SPI_CS
16 15 GPIO22 GP22 GPIO22 GP22 GPIO22 GP22 GT_CCP04 McAFSX
17 16 GPIO23 GP23 TDI GPIO23 GP23 TDI UART1_TX 2C_SCL
18 17 GPIO24 GP24 TDO GPIO24 GP24 TDO UART1_RX GT_CCP06 PWM0 McAFSX I2C_SDA
19 18 GPIO28 GP28 GPIO28 GP28 GPIO28 GP28
20 19 TCK TCK TCK GT_PWM03
21 20 GPIO29 GP29 TMS GPIO29 GP29 TMS
22 21 GPIO25 GP25 SOP2 GPIO25 GP25 McAFSX GT_PWM02
23 22 WLAN_XTAL_N WLAN_XTAL_N WLAN_XTAL_N
24 23 WLAN_XTAL_P WLAN_XTAL_P WLAN_XTAL_P
25 24 VDD_PLL VDD_PLL VDD_PLL
43 42 DCDC_PA_OUT DCDC_PA_O UT DCDC_PA_O UT
44 43 DCDC_DIG_SW DCDC_DIG_ SW DCDC_DIG_ SW
45 44 VIN_DCDC_DIG VIN_DCDC_ DIG VIN_DCDC_ DIG
46 45 GPIO31 GP31 DCDC_ANA2_SW_P GPIO31 GP31 UART1_RX McAXR0 GSPI_CLK UART0_RX McAFSX
47 46 DCDC_ANA2_SW_N DCDC_ANA2_SW_N DCDC_ANA2_SW_N
48 47 VDD_ANA2 VDD_ANA2 VDD_ANA2
49 48 VDD_ANA1 VDD_ANA1 VDD_ANA1
50 49 VDD_RAM VDD_RAM VDD_RAM
51 50 GPIO0 GP0 GPIO0 GP0 GPIO0 GP0 UART0_RTS McAXR0 McAXR1 GT_CCP00 GSPI_CS UART1_RTS UART0_CTS
52 51 RTC_XTAL_P RTC_XTAL_P RTC_XTAL_P
53 52 RTC_XTAL_N RTC_XTAL_N GPIO32 GP32 McACLK McAXR0 UART0_RTS GSPI_MOSI
54 53 GPIO30 GP30 GPIO30 GP30 GPIO30 GP30 McACLK McAFSX GT_CCP05 GSPI_MISO UART0_TX
55 54 VIN_IO2 VIN_IO2 VIN_IO2
56 55 GPIO1 GP1 GPIO1 GP1 GPIO1 GP1 GSPI_MISO pCLK (PIXCLK) UART1_TX GT_CCP01
57 56 VDD_DIG2 VDD_DIG2 VDD_DIG2
58 57 GPIO2 GP2 GPIO2 GP2 GPIO2 GP2 UART0_RX UART1_RX GT_CCP02 ADC_CH0
59 58 GPIO3 GP3 GPIO3 GP3 GPIO3 GP3 pDATA7(CAM_D3) UART1_TX ADC_CH1
60 59 GPIO4 GP4 GPIO4 GP4 GPIO4 GP4 pDATA6(CAM_D2) UART1_RX ADC_CH2
61 60 GPIO5 GP5 GPIO5 GP5 GPIO5 GP5 pDATA5(CAM_D1) McAXR1 GT_CCP05 ADC_CH3
62 61 GPIO6 GP6 GPIO6 GP6 GPIO6 GP6 UART1_CTS pDATA4(CAM_D0) UART0_RTS UART0_CTS GT_CCP06
63 62 GPIO7 GP7 GPIO7 GP7 GPIO7 GP7 UART1_RTS UART0_RTS UART0_TX McACLKX
64 63 GPIO8 GP8 GPIO8 GP8 GPIO8 GP8 SDCARD_IRQ McAFSX GT_CCP06
65 64 GPIO9 GP9 GPIO9 GP9 GPIO9 GP9 GT_PWM05 SDCARD_DATA McAXR0 GT_CCP00
66 65 GND_TAB GND_TAB GND_TAB

View File

@@ -10,14 +10,14 @@ import csv
def parse_port_pin(name_str):
"""Parses a string and returns a (port, gpio_bit) tuple."""
if len(name_str) < 5:
raise ValueError("Expecting pin name to be at least 5 characters")
if name_str[:4] != 'GPIO':
raise ValueError("Expecting pin name to start with GPIO")
if not name_str[4:].isdigit():
if len(name_str) < 3:
raise ValueError("Expecting pin name to be at least 3 characters")
if name_str[:2] != 'GP':
raise ValueError("Expecting pin name to start with GP")
if not name_str[2:].isdigit():
raise ValueError("Expecting numeric GPIO number")
port = int(int(name_str[4:]) / 8)
gpio_bit = 1 << int(int(name_str[4:]) % 8)
port = int(int(name_str[2:]) / 8)
gpio_bit = 1 << int(int(name_str[2:]) % 8)
return (port, gpio_bit)

View File

@@ -19,6 +19,7 @@ BOOT_CPPDEFINES = -Dgcc -DBOOTLOADER -DTARGET_IS_CC3200 -DSL_TINY
BOOT_HAL_SRC_C = $(addprefix hal/,\
cpu.c \
interrupt.c \
gpio.c \
pin.c \
prcm.c \
shamd5.c \
@@ -42,6 +43,7 @@ BOOT_CC3100_SRC_C = $(addprefix drivers/cc3100/,\
)
BOOT_MISC_SRC_C = $(addprefix misc/,\
antenna.c \
mperror.c \
)
@@ -50,7 +52,7 @@ BOOT_SL_SRC_C = $(addprefix simplelink/,\
)
BOOT_UTIL_SRC_C = $(addprefix util/,\
hash.c \
cryptohash.c \
)
BOOT_MAIN_SRC_C = \
@@ -60,17 +62,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 +130,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

@@ -39,6 +39,7 @@ SECTIONS
{
_text = .;
KEEP(*(.intvecs))
*(.boot*)
*(.text*)
*(.rodata*)
*(.ARM.extab* .gnu.linkonce.armextab.*)

View File

@@ -43,23 +43,31 @@ extern "C"
*******************************************************************************/
#define IMG_BOOT_INFO "/sys/bootinfo.bin"
#define IMG_FACTORY "/sys/factimg.bin"
#define IMG_UPDATE "/sys/updtimg.bin"
#define IMG_UPDATE1 "/sys/updtimg1.bin"
#define IMG_UPDATE2 "/sys/updtimg2.bin"
#define IMG_PREFIX "/sys/updtimg"
#define IMG_SRVPACK "/sys/servicepack.ucf"
#define SRVPACK_SIGN "/sys/servicepack.sig"
#define CA_FILE "/cert/ca.pem"
#define CERT_FILE "/cert/cert.pem"
#define KEY_FILE "/cert/private.key"
/******************************************************************************
Image file sizes
Special file sizes
*******************************************************************************/
#define IMG_SIZE (232 * 1024) /* 16KB are reserved for the bootloader and at least 8KB for the heap*/
#define IMG_SIZE (192 * 1024) /* 16KB are reserved for the bootloader and at least 48KB for the heap*/
#define SRVPACK_SIZE (16 * 1024)
#define SIGN_SIZE (2 * 1024)
#define CA_KEY_SIZE (4 * 1024)
/******************************************************************************
Active Image
*******************************************************************************/
#define IMG_ACT_FACTORY 0
#define IMG_ACT_UPDATE 1
#define IMG_ACT_UPDATE1 1
#define IMG_ACT_UPDATE2 2
#define IMG_STATUS_CHECK 0
#define IMG_STATUS_READY 1
@@ -67,13 +75,13 @@ extern "C"
/******************************************************************************
Boot Info structure
*******************************************************************************/
typedef struct sBootInfo
typedef struct _sBootInfo_t
{
_u8 ActiveImg;
_u8 Status;
_u8 PrevImg;
_u8 : 8;
_u8 : 8;
}sBootInfo_t;
} sBootInfo_t;
/******************************************************************************

View File

@@ -26,7 +26,8 @@
#include <stdint.h>
#include <stdbool.h>
#include <std.h>
#include "std.h"
#include "py/mpconfig.h"
#include MICROPY_HAL_H
@@ -47,11 +48,12 @@
#include "flc.h"
#include "bootmgr.h"
#include "shamd5.h"
#include "hash.h"
#include "cryptohash.h"
#include "utils.h"
#include "cc3200_hal.h"
#include "debug.h"
#include "mperror.h"
#include "antenna.h"
//*****************************************************************************
@@ -62,11 +64,16 @@
#define BOOTMGR_HASH_SIZE 32
#define BOOTMGR_BUFF_SIZE 512
#define BOOTMGR_WAIT_SAFE_MODE_MS 1600
#define BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS 200
#define BOOTMGR_WAIT_SAFE_MODE_0_MS 500
#define BOOTMGR_SAFE_MODE_ENTER_MS 800
#define BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS 80
#define BOOTMGR_WAIT_SAFE_MODE_1_MS 3000
#define BOOTMGR_WAIT_SAFE_MODE_1_BLINK_MS 250
#define BOOTMGR_WAIT_SAFE_MODE_2_MS 3000
#define BOOTMGR_WAIT_SAFE_MODE_2_BLINK_MS 250
#define BOOTMGR_WAIT_SAFE_MODE_3_MS 1500
#define BOOTMGR_WAIT_SAFE_MODE_3_BLINK_MS 100
//*****************************************************************************
// Exported functions declarations
@@ -77,9 +84,11 @@ extern void bootmgr_run_app (_u32 base);
// Local functions declarations
//*****************************************************************************
static void bootmgr_board_init (void);
static bool bootmgr_verify (void);
static bool bootmgr_verify (_u8 *image);
static void bootmgr_load_and_execute (_u8 *image);
static bool safe_mode_boot (void);
static bool wait_while_blinking (uint32_t wait_time, uint32_t period, bool force_wait);
static bool safe_boot_request_start (uint32_t wait_time);
static void wait_for_safe_boot (sBootInfo_t *psBootInfo);
static void bootmgr_image_loader (sBootInfo_t *psBootInfo);
//*****************************************************************************
@@ -138,44 +147,52 @@ void SimpleLinkSockEventHandler(SlSockEvent_t *pSock)
//! Board Initialization & Configuration
//*****************************************************************************
static void bootmgr_board_init(void) {
// Set vector table base
// set the vector table base
MAP_IntVTableBaseSet((unsigned long)&g_pfnVectors[0]);
// Enable Processor Interrupts
// enable processor interrupts
MAP_IntMasterEnable();
MAP_IntEnable(FAULT_SYSTICK);
// Mandatory MCU Initialization
// mandatory MCU initialization
PRCMCC3200MCUInit();
// clear all the special bits, since we can't trust their content after reset
PRCMClearSpecialBit(PRCM_SAFE_BOOT_BIT);
PRCMClearSpecialBit(PRCM_WDT_RESET_BIT);
PRCMClearSpecialBit(PRCM_FIRST_BOOT_BIT);
// check the reset after clearing the special bits
mperror_bootloader_check_reset_cause();
// Enable the Data Hashing Engine
HASH_Init();
#if MICROPY_HW_ANTENNA_DIVERSITY
// configure the antenna selection pins
antenna_init0();
#endif
// Init the system led and the system switch
// enable the data hashing engine
CRYPTOHASH_Init();
// init the system led and the system switch
mperror_init0();
// clear the safe boot flag, since we can't trust its content after reset
PRCMClearSafeBootRequest();
}
//*****************************************************************************
//! Verifies the integrity of the new application binary
//*****************************************************************************
static bool bootmgr_verify (void) {
static bool bootmgr_verify (_u8 *image) {
SlFsFileInfo_t FsFileInfo;
_u32 reqlen, offset = 0;
_i32 fHandle;
// open the file for reading
if (0 == sl_FsOpen((_u8 *)IMG_UPDATE, FS_MODE_OPEN_READ, NULL, &fHandle)) {
if (0 == sl_FsOpen(image, FS_MODE_OPEN_READ, NULL, &fHandle)) {
// get the file size
sl_FsGetInfo((_u8 *)IMG_UPDATE, 0, &FsFileInfo);
sl_FsGetInfo(image, 0, &FsFileInfo);
if (FsFileInfo.FileLen > BOOTMGR_HASH_SIZE) {
FsFileInfo.FileLen -= BOOTMGR_HASH_SIZE;
HASH_SHAMD5Start(BOOTMGR_HASH_ALGO, FsFileInfo.FileLen);
CRYPTOHASH_SHAMD5Start(BOOTMGR_HASH_ALGO, FsFileInfo.FileLen);
do {
if ((FsFileInfo.FileLen - offset) > BOOTMGR_BUFF_SIZE) {
reqlen = BOOTMGR_BUFF_SIZE;
@@ -185,10 +202,10 @@ static bool bootmgr_verify (void) {
}
offset += sl_FsRead(fHandle, offset, bootmgr_file_buf, reqlen);
HASH_SHAMD5Update(bootmgr_file_buf, reqlen);
CRYPTOHASH_SHAMD5Update(bootmgr_file_buf, reqlen);
} while (offset < FsFileInfo.FileLen);
HASH_SHAMD5Read (bootmgr_file_buf);
CRYPTOHASH_SHAMD5Read (bootmgr_file_buf);
// convert the resulting hash to hex
for (_u32 i = 0; i < (BOOTMGR_HASH_SIZE / 2); i++) {
@@ -196,7 +213,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
@@ -235,47 +252,81 @@ static void bootmgr_load_and_execute (_u8 *image) {
}
//*****************************************************************************
//! Check for the safe mode pin
//! Wait while the safe mode pin is being held high and blink the system led
//! with the specified period
//*****************************************************************************
static bool safe_mode_boot (void) {
_u32 count = 0;
while (MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) &&
((BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * count++) < BOOTMGR_WAIT_SAFE_MODE_MS)) {
static bool wait_while_blinking (uint32_t wait_time, uint32_t period, bool force_wait) {
_u32 count;
for (count = 0; (force_wait || MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN)) &&
((period * count) < wait_time); count++) {
// toogle the led
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN));
UtilsDelay(UTILS_DELAY_US_TO_COUNT(BOOTMGR_WAIT_SAFE_MODE_TOOGLE_MS * 1000));
UtilsDelay(UTILS_DELAY_US_TO_COUNT(period * 1000));
}
return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false;
}
static bool safe_boot_request_start (uint32_t wait_time) {
if (MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN)) {
UtilsDelay(UTILS_DELAY_US_TO_COUNT(wait_time * 1000));
}
mperror_deinit_sfe_pin();
return MAP_GPIOPinRead(MICROPY_SAFE_BOOT_PORT, MICROPY_SAFE_BOOT_PORT_PIN) ? true : false;
}
//*****************************************************************************
//! Load the proper image based on information from boot info and executes it.
//! Check for the safe mode pin
//*****************************************************************************
static void wait_for_safe_boot (sBootInfo_t *psBootInfo) {
if (safe_boot_request_start(BOOTMGR_WAIT_SAFE_MODE_0_MS)) {
if (wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_1_MS, BOOTMGR_WAIT_SAFE_MODE_1_BLINK_MS, false)) {
// go back one step in time
psBootInfo->ActiveImg = psBootInfo->PrevImg;
if (wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_2_MS, BOOTMGR_WAIT_SAFE_MODE_2_BLINK_MS, false)) {
// go back directly to the factory image
psBootInfo->ActiveImg = IMG_ACT_FACTORY;
wait_while_blinking(BOOTMGR_WAIT_SAFE_MODE_3_MS, BOOTMGR_WAIT_SAFE_MODE_3_BLINK_MS, true);
}
}
// turn off the system led
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0);
// request a safe boot to the application
PRCMSetSpecialBit(PRCM_SAFE_BOOT_BIT);
}
// deinit the safe boot pin
mperror_deinit_sfe_pin();
}
//*****************************************************************************
//! Load the proper image based on the information from the boot info
//! and launch it.
//*****************************************************************************
static void bootmgr_image_loader(sBootInfo_t *psBootInfo) {
_i32 fhandle;
if (safe_mode_boot()) {
_u32 count = 0;
while ((BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS * count++) < BOOTMGR_SAFE_MODE_ENTER_MS) {
// toogle the led
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, ~MAP_GPIOPinRead(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN));
UtilsDelay(UTILS_DELAY_US_TO_COUNT(BOOTMGR_SAFE_MODE_ENTER_TOOGLE_MS * 1000));
}
psBootInfo->ActiveImg = IMG_ACT_FACTORY;
// turn the led off
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0);
// request a safe boot to the application
PRCMRequestSafeBoot();
_u8 *image;
// search for the active image
switch (psBootInfo->ActiveImg) {
case IMG_ACT_UPDATE1:
image = (unsigned char *)IMG_UPDATE1;
break;
case IMG_ACT_UPDATE2:
image = (unsigned char *)IMG_UPDATE2;
break;
default:
image = (unsigned char *)IMG_FACTORY;
break;
}
// do we have a new update image that needs to be verified?
else if ((psBootInfo->ActiveImg == IMG_ACT_UPDATE) && (psBootInfo->Status == IMG_STATUS_CHECK)) {
if (!bootmgr_verify()) {
// delete the corrupted file
sl_FsDel((_u8 *)IMG_UPDATE, 0);
// switch to the factory image
psBootInfo->ActiveImg = IMG_ACT_FACTORY;
// do we have a new image that needs to be verified?
if ((psBootInfo->ActiveImg != IMG_ACT_FACTORY) && (psBootInfo->Status == IMG_STATUS_CHECK)) {
if (!bootmgr_verify(image)) {
// verification failed, delete the broken file
sl_FsDel(image, 0);
// switch to the previous image
psBootInfo->ActiveImg = psBootInfo->PrevImg;
psBootInfo->PrevImg = IMG_ACT_FACTORY;
}
// in any case, set the status as "READY"
// in any case, change the status to "READY"
psBootInfo->Status = IMG_STATUS_READY;
// write the new boot info
if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_WRITE, NULL, &fhandle)) {
@@ -285,24 +336,34 @@ static void bootmgr_image_loader(sBootInfo_t *psBootInfo) {
}
}
// now boot the active image
if (IMG_ACT_UPDATE == psBootInfo->ActiveImg) {
bootmgr_load_and_execute((unsigned char *)IMG_UPDATE);
}
else {
bootmgr_load_and_execute((unsigned char *)IMG_FACTORY);
// this one might modify the boot info hence it MUST be called after
// bootmgr_verify! (so that the changes are not saved to flash)
wait_for_safe_boot(psBootInfo);
// select the active image again, since it might have changed
switch (psBootInfo->ActiveImg) {
case IMG_ACT_UPDATE1:
image = (unsigned char *)IMG_UPDATE1;
break;
case IMG_ACT_UPDATE2:
image = (unsigned char *)IMG_UPDATE2;
break;
default:
image = (unsigned char *)IMG_FACTORY;
break;
}
bootmgr_load_and_execute(image);
}
//*****************************************************************************
//! Main function
//*****************************************************************************
int main (void) {
sBootInfo_t sBootInfo = { .ActiveImg = IMG_ACT_FACTORY, .Status = IMG_STATUS_READY };
sBootInfo_t sBootInfo = { .ActiveImg = IMG_ACT_FACTORY, .Status = IMG_STATUS_READY, .PrevImg = IMG_ACT_FACTORY };
bool bootapp = false;
_i32 fhandle;
// Board Initialization
// board setup
bootmgr_board_init();
// start simplelink since we need it to access the sflash
@@ -315,17 +376,20 @@ int main (void) {
}
sl_FsClose(fhandle, 0, 0, 0);
}
// boot info file not present, it means that this is the first boot after being programmed
if (!bootapp) {
// create a new boot info file
_u32 BootInfoCreateFlag = _FS_FILE_OPEN_FLAG_COMMIT | _FS_FILE_PUBLIC_WRITE | _FS_FILE_PUBLIC_READ;
if (!sl_FsOpen ((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_CREATE((2 * sizeof(sBootInfo_t)),
BootInfoCreateFlag), NULL, &fhandle)) {
// Write the default boot info.
// write the default boot info.
if (sizeof(sBootInfo_t) == sl_FsWrite(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t))) {
bootapp = true;
}
sl_FsClose(fhandle, 0, 0, 0);
}
// signal the first boot to the application
PRCMSetSpecialBit(PRCM_FIRST_BOOT_BIT);
}
if (bootapp) {
@@ -336,14 +400,23 @@ int main (void) {
// stop simplelink
sl_Stop(SL_STOP_TIMEOUT);
// if we've reached this point, then it means a fatal error occurred and the application
// could not be loaded, so, loop forever and signal the crash to the user
// if we've reached this point, then it means that a fatal error has occurred and the
// application could not be loaded, so, loop forever and signal the crash to the user
while (true) {
// keep the bld on
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN);
__asm volatile(" dsb \n"
" isb \n"
" wfi \n");
__asm volatile(" dsb \n"
" isb \n"
" wfi \n");
}
}
//*****************************************************************************
//! 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

@@ -10,17 +10,19 @@
#include <stdbool.h>
#include "py/mpconfig.h"
#include "py/obj.h"
#include "diskio.h" /* FatFs lower layer API */
#include "sflash_diskio.h" /* Serial flash disk IO API */
#if MICROPY_HW_HAS_SDCARD
#include "sd_diskio.h" /* SDCARD disk IO API */
#endif
#include "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 "pybrtc.h"
#include "timeutils.h"
/* Definitions of physical drive number for each drive */
#define SFLASH 0 /* Map SFLASH drive to drive number 0 */
@@ -192,13 +194,8 @@ DWORD get_fattime (
void
)
{
mod_struct_time 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_struct_time_t tm;
timeutils_seconds_since_2000_to_struct_time(pybrtc_get_seconds(), &tm);
return ((tm.tm_year - 1980) << 25) | ((tm.tm_mon) << 21) |
((tm.tm_mday) << 16) | ((tm.tm_hour) << 11) |

View File

@@ -4,10 +4,12 @@
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/obj.h"
#include "simplelink.h"
#include "diskio.h"
#include "sflash_diskio.h"
#include "debug.h"
#include "modnetwork.h"
#include "modwlan.h"
#define SFLASH_TIMEOUT_MAX_MS 5500
@@ -58,7 +60,7 @@ DRESULT sflash_disk_init (void) {
print_block_name (i);
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
// Create the block file if it doesn't exist
if (sl_FsGetInfo(sflash_block_name, 0, &FsFileInfo) < 0) {
if (sl_FsGetInfo(sflash_block_name, 0, &FsFileInfo) != 0) {
if (!sl_FsOpen(sflash_block_name, FS_MODE_OPEN_CREATE(SFLASH_BLOCK_SIZE, 0), NULL, &fileHandle)) {
sl_FsClose(fileHandle, NULL, NULL, 0);
sl_LockObjUnlock (&wlan_LockObj);
@@ -72,6 +74,10 @@ DRESULT sflash_disk_init (void) {
sl_LockObjUnlock (&wlan_LockObj);
return RES_ERROR;
}
} else {
// file system exists, break here to speed up booting
sl_LockObjUnlock (&wlan_LockObj);
break;
}
sl_LockObjUnlock (&wlan_LockObj);
}

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);
*dest += 7;
memcpy(*dest, "/flash", 6);
*dest += 6;
}
#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
@@ -39,8 +39,9 @@
#include "pybrtc.h"
#include "ftp.h"
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
#include "modutime.h"
#include "modusocket.h"
#include "debug.h"
#include "serverstask.h"
#include "ff.h"
@@ -49,7 +50,7 @@
#include "diskio.h"
#include "sd_diskio.h"
#include "updater.h"
#include "timeutils.h"
/******************************************************************************
DEFINE PRIVATE CONSTANTS
@@ -67,7 +68,6 @@
#define FTP_UNIX_TIME_20150101 1420070400
#define FTP_UNIX_SECONDS_180_DAYS 15552000
#define FTP_DATA_TIMEOUT_MS 5000 // 5 seconds
#define FTP_CMD_TIMEOUT_MS 120000 // 2 minutes
#define FTP_SOCKETFIFO_ELEMENTS_MAX 4
#define FTP_CYCLE_TIME_MS (SERVERS_CYCLE_TIME_MS * 2)
@@ -137,17 +137,16 @@ typedef struct {
uint8_t e_open;
bool closechild;
bool enabled;
bool swupdating;
bool special_file;
} ftp_data_t;
typedef struct {
char * cmd;
}ftp_cmd_t;
} ftp_cmd_t;
typedef struct {
char * month;
}ftp_month_t;
} ftp_month_t;
typedef enum {
E_FTP_CMD_NOT_SUPPORTED = -1,
@@ -174,7 +173,7 @@ typedef enum {
E_FTP_CMD_NOOP,
E_FTP_CMD_QUIT,
E_FTP_NUM_FTP_CMDS
}ftp_cmd_index_t;
} ftp_cmd_index_t;
/******************************************************************************
DECLARE PRIVATE DATA
@@ -224,7 +223,6 @@ static ftp_result_t ftp_list_dir (char *list, uint32_t maxlistsize, uint32_t *li
static void ftp_open_child (char *pwd, char *dir);
static void ftp_close_child (char *pwd);
static void ftp_return_to_previous_path (char *pwd, char *dir);
static void ftp_reset (void);
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
@@ -244,7 +242,7 @@ void ftp_init (void) {
ftp_data.e_open = E_FTP_NOTHING_OPEN;
ftp_data.state = E_FTP_STE_DISABLED;
ftp_data.substate.data = E_FTP_STE_SUB_DISCONNECTED;
ftp_data.swupdating = false;
ftp_data.special_file = false;
}
void ftp_run (void) {
@@ -253,7 +251,7 @@ void ftp_run (void) {
ftp_wait_for_enabled();
break;
case E_FTP_STE_START:
if (ftp_create_listening_socket(&ftp_data.lc_sd, FTP_CMD_PORT, FTP_CMD_CLIENTS_MAX )) {
if (wlan_is_connected() && ftp_create_listening_socket(&ftp_data.lc_sd, FTP_CMD_PORT, FTP_CMD_CLIENTS_MAX)) {
ftp_data.state = E_FTP_STE_READY;
}
break;
@@ -301,19 +299,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:
@@ -324,7 +324,7 @@ void ftp_run (void) {
ftp_data.dtimeout = 0;
ftp_data.ctimeout = 0;
// its a software update
if (ftp_data.swupdating) {
if (ftp_data.special_file) {
if (updater_write(ftp_data.dBuffer, len)) {
break;
}
@@ -344,8 +344,8 @@ void ftp_run (void) {
}
}
else {
if (ftp_data.swupdating) {
ftp_data.swupdating = false;
if (ftp_data.special_file) {
ftp_data.special_file = false;
updater_finnish();
}
ftp_close_files();
@@ -406,6 +406,16 @@ void ftp_disable (void) {
ftp_data.state = E_FTP_STE_DISABLED;
}
void ftp_reset (void) {
// close all connections and start all over again
servers_close_socket(&ftp_data.lc_sd);
servers_close_socket(&ftp_data.ld_sd);
ftp_close_cmd_data();
ftp_data.state = E_FTP_STE_START;
ftp_data.substate.data = E_FTP_STE_SUB_DISCONNECTED;
SOCKETFIFO_Flush();
}
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
@@ -427,21 +437,27 @@ static bool ftp_create_listening_socket (_i16 *sd, _u16 port, _u8 backlog) {
_sd = *sd;
if (_sd > 0) {
// add the new socket to the network administration
modusocket_socket_add(_sd, false);
// Enable non-blocking mode
nonBlockingOption.NonblockingEnabled = 1;
ASSERT (sl_SetSockOpt(_sd, SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption)) == SL_SOC_OK);
ASSERT ((result = sl_SetSockOpt(_sd, SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption))) == SL_SOC_OK);
// 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);
ASSERT ((result |= sl_Bind(_sd, (const SlSockAddr_t *)&sServerAddress, sizeof(sServerAddress))) == SL_SOC_OK);
// Start listening
ASSERT ((result = sl_Listen (_sd, backlog)) == SL_SOC_OK);
ASSERT ((result |= sl_Listen (_sd, backlog)) == SL_SOC_OK);
return (result == SL_SOC_OK) ? true : false;
if (result == SL_SOC_OK) {
return true;
}
servers_close_socket(sd);
}
return false;
}
@@ -462,6 +478,9 @@ static ftp_result_t ftp_wait_for_connection (_i16 l_sd, _i16 *n_sd) {
return E_FTP_RESULT_FAILED;
}
// add the new socket to the network administration
modusocket_socket_add(_sd, false);
// client connected, so go on
return E_FTP_RESULT_OK;
}
@@ -558,8 +577,8 @@ static void ftp_send_from_fifo (void) {
// close the listening and the data sockets
servers_close_socket(&ftp_data.ld_sd);
servers_close_socket(&ftp_data.d_sd);
if (ftp_data.swupdating) {
ftp_data.swupdating = false;
if (ftp_data.special_file) {
ftp_data.special_file = false;
}
}
}
@@ -588,8 +607,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 +688,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 +696,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 +719,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);
}
@@ -734,15 +758,14 @@ static void ftp_process_cmd (void) {
ftp_get_param_and_open_child (&bufptr);
// first check if a software update is being requested
if (updater_check_path (ftp_path)) {
// start by erasing the previous status file
// must be done before starting the updater
f_unlink(ftp_path);
if (updater_start()) {
ftp_data.swupdating = true;
ftp_data.special_file = true;
ftp_data.state = E_FTP_STE_CONTINUE_FILE_RX;
ftp_send_reply(150, NULL);
}
else {
// to unlock the updater
updater_finnish();
ftp_data.state = E_FTP_STE_END_TRANSFER;
ftp_send_reply(550, NULL);
}
@@ -815,7 +838,7 @@ static void ftp_process_cmd (void) {
}
}
else if (result == E_FTP_RESULT_CONTINUE) {
if (ftp_data.ctimeout++ > (FTP_CMD_TIMEOUT_MS / FTP_CYCLE_TIME_MS)) {
if (ftp_data.ctimeout++ > (servers_get_timeout() / FTP_CYCLE_TIME_MS)) {
ftp_send_reply(221, NULL);
}
}
@@ -836,9 +859,9 @@ static void ftp_close_files (void) {
static void ftp_close_filesystem_on_error (void) {
ftp_close_files();
if (ftp_data.swupdating) {
if (ftp_data.special_file) {
updater_finnish ();
ftp_data.swupdating = false;
ftp_data.special_file = false;
}
}
@@ -874,37 +897,43 @@ static int ftp_print_eplf_item (char *dest, uint32_t destsize, FILINFO *fno) {
char *type = (fno->fattrib & AM_DIR) ? "d" : "-";
uint32_t tseconds;
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,
(fno->ftime >> 5) & 0x3f,
2 * (fno->ftime & 0x1f));
MAP_PRCMRTCGet(&tseconds, &mseconds);
tseconds = pybrtc_get_seconds();
if (FTP_UNIX_SECONDS_180_DAYS < tseconds - fseconds) {
return snprintf(dest, destsize, "%srw-rw-r-- 1 root root %9u %s %2u %5u %s\r\n",
type, (_u32)fno->fsize, ftp_month[mindex].month, day,
#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);
tseconds = pybrtc_get_seconds();
if (FTP_UNIX_SECONDS_180_DAYS < tseconds - (FTP_UNIX_TIME_20150101 - FTP_UNIX_TIME_20000101)) {
return snprintf(dest, destsize, "%srw-rw-r-- 1 root root %9u %s %2u %5u %s\r\n",
type, 0, ftp_month[(tm.tm_mon - 1)].month, tm.tm_mday, tm.tm_year, name);
@@ -956,10 +985,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 +1008,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 +1028,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;
}
@@ -1047,12 +1087,3 @@ static void ftp_return_to_previous_path (char *pwd, char *dir) {
}
}
static void ftp_reset (void) {
// close all connections and start all over again
servers_close_socket(&ftp_data.lc_sd);
servers_close_socket(&ftp_data.ld_sd);
ftp_close_cmd_data();
ftp_data.state = E_FTP_STE_START;
ftp_data.substate.data = E_FTP_STE_SUB_DISCONNECTED;
SOCKETFIFO_Flush();
}

View File

@@ -34,5 +34,6 @@ extern void ftp_init (void);
extern void ftp_run (void);
extern void ftp_enable (void);
extern void ftp_disable (void);
extern void ftp_reset (void);
#endif /* FTP_H_ */

View File

@@ -1,22 +1,53 @@
/*
* 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.
*/
#include <stdint.h>
#include <stdbool.h>
#include "std.h"
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/obj.h"
#include "simplelink.h"
#include "flc.h"
#include "updater.h"
#include "shamd5.h"
#include "modnetwork.h"
#include "modwlan.h"
#include "debug.h"
#include "osi.h"
/******************************************************************************
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 UPDATER_CA_PATH "/flash/cert/ca.pem"
#define UPDATER_CERT_PATH "/flash/cert/cert.pem"
#define UPDATER_KEY_PATH "/flash/cert/private.key"
/******************************************************************************
DEFINE TYPES
@@ -31,35 +62,64 @@ typedef struct {
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
static updater_data_t updater_data;
static updater_data_t updater_data = { .path = NULL, .fhandle = -1, .fsize = 0, .foffset = 0 };
static OsiLockObj_t updater_LockObj;
static sBootInfo_t sBootInfo;
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
__attribute__ ((section (".boot")))
void updater_pre_init (void) {
// create the updater lock
ASSERT(OSI_OK == sl_LockObjCreate(&updater_LockObj, "UpdaterLock"));
}
bool updater_check_path (void *path) {
// conert the path supplied to upper case
stoupper (path);
sl_LockObjLock (&updater_LockObj, SL_OS_WAIT_FOREVER);
if (!strcmp(UPDATER_IMG_PATH, path)) {
updater_data.path = IMG_UPDATE;
updater_data.fsize = IMG_SIZE;
return true;
}
else if (!strcmp(UPDATER_SRVPACK_PATH, path)) {
updater_data.path = IMG_UPDATE1;
// the launchxl doesn't have enough flash space for 2 user update images
#ifdef WIPY
// check which one should be the next active image
_i32 fhandle;
if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_READ, NULL, &fhandle)) {
ASSERT (sizeof(sBootInfo_t) == sl_FsRead(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t)));
sl_FsClose(fhandle, 0, 0, 0);
if ((sBootInfo.Status == IMG_STATUS_CHECK && sBootInfo.ActiveImg == IMG_ACT_UPDATE2) ||
sBootInfo.ActiveImg == IMG_ACT_UPDATE1) {
updater_data.path = IMG_UPDATE2;
}
}
#endif
} else if (!strcmp(UPDATER_SRVPACK_PATH, path)) {
updater_data.path = IMG_SRVPACK;
updater_data.fsize = SRVPACK_SIZE;
return true;
}
else if (!strcmp(UPDATER_SIGN_PATH, path)) {
} else if (!strcmp(UPDATER_SIGN_PATH, path)) {
updater_data.path = SRVPACK_SIGN;
updater_data.fsize = SIGN_SIZE;
return true;
} else if (!strcmp(UPDATER_CA_PATH, path)) {
updater_data.path = CA_FILE;
updater_data.fsize = CA_KEY_SIZE;
} else if (!strcmp(UPDATER_CERT_PATH, path)) {
updater_data.path = CERT_FILE;
updater_data.fsize = CA_KEY_SIZE;
} else if (!strcmp(UPDATER_KEY_PATH, path)) {
updater_data.path = KEY_FILE;
updater_data.fsize = CA_KEY_SIZE;
} else {
sl_LockObjUnlock (&updater_LockObj);
return false;
}
return false;
return true;
}
bool updater_start (void) {
_u32 AccessModeAndMaxSize = FS_MODE_OPEN_WRITE;
SlFsFileInfo_t FsFileInfo;
bool result = false;
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
if (0 != sl_FsGetInfo((_u8 *)updater_data.path, 0, &FsFileInfo)) {
// file doesn't exist, create it
@@ -67,49 +127,76 @@ bool updater_start (void) {
}
if (!sl_FsOpen((_u8 *)updater_data.path, AccessModeAndMaxSize, NULL, &updater_data.fhandle)) {
updater_data.foffset = 0;
return true;
result = true;
}
sl_LockObjUnlock (&wlan_LockObj);
return false;
return result;
}
bool updater_write (uint8_t *buf, uint32_t len) {
bool result = false;
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
if (len == sl_FsWrite(updater_data.fhandle, updater_data.foffset, buf, len)) {
updater_data.foffset += len;
return true;
result = true;
}
return false;
sl_LockObjUnlock (&wlan_LockObj);
return result;
}
void updater_finnish (void) {
sBootInfo_t sBootInfo;
_i32 fhandle;
if (updater_data.fhandle > 0) {
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
// close the file being updated
sl_FsClose(updater_data.fhandle, NULL, NULL, 0);
if (!strcmp (IMG_UPDATE, updater_data.path)) {
// open the boot info file for reading
#ifdef WIPY
// if we still have an image pending for verification, leave the boot info as it is
if (!strncmp(IMG_PREFIX, updater_data.path, strlen(IMG_PREFIX)) && sBootInfo.Status != IMG_STATUS_CHECK) {
#else
if (!strncmp(IMG_PREFIX, updater_data.path, strlen(IMG_PREFIX))) {
#endif
#ifdef DEBUG
if (!sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_READ, NULL, &fhandle)) {
ASSERT (sizeof(sBootInfo_t) == sl_FsRead(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t)));
sl_FsClose(fhandle, 0, 0, 0);
// open the file for writing
#endif
// open the boot info file for writing
ASSERT (sl_FsOpen((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_WRITE, NULL, &fhandle) == 0);
#ifdef DEBUG
}
else {
// the boot info file doesn't exist yet
_u32 BootInfoCreateFlag = _FS_FILE_OPEN_FLAG_COMMIT | _FS_FILE_PUBLIC_WRITE | _FS_FILE_PUBLIC_READ;
ASSERT (sl_FsOpen ((unsigned char *)IMG_BOOT_INFO, FS_MODE_OPEN_CREATE((2 * sizeof(sBootInfo_t)),
BootInfoCreateFlag), NULL, &fhandle) == 0);
}
#endif
// write the new boot info
sBootInfo.ActiveImg = IMG_ACT_UPDATE;
// save the new boot info
#ifdef WIPY
sBootInfo.PrevImg = sBootInfo.ActiveImg;
if (sBootInfo.ActiveImg == IMG_ACT_UPDATE1) {
sBootInfo.ActiveImg = IMG_ACT_UPDATE2;
} else {
sBootInfo.ActiveImg = IMG_ACT_UPDATE1;
}
// the launchxl doesn't have enough flash space for 2 user updates
#else
sBootInfo.PrevImg = IMG_ACT_FACTORY;
sBootInfo.ActiveImg = IMG_ACT_UPDATE1;
#endif
sBootInfo.Status = IMG_STATUS_CHECK;
ASSERT (sizeof(sBootInfo_t) == sl_FsWrite(fhandle, 0, (unsigned char *)&sBootInfo, sizeof(sBootInfo_t)));
sl_FsClose(fhandle, 0, 0, 0);
}
sl_LockObjUnlock (&wlan_LockObj);
updater_data.fhandle = -1;
}
updater_data.fhandle = -1;
sl_LockObjUnlock (&wlan_LockObj);
sl_LockObjUnlock (&updater_LockObj);
}

View File

@@ -1,11 +1,38 @@
/*
* 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 UPDATER_H_
#define UPDATER_H_
bool updater_check_path (void *path);
bool updater_start (void);
bool updater_write (uint8_t *buf, uint32_t len);
void updater_finnish (void);
bool updater_verify (uint8_t *rbuff, uint8_t *hasbuff);
extern void updater_pre_init (void);
extern bool updater_check_path (void *path);
extern bool updater_start (void);
extern bool updater_write (uint8_t *buf, uint32_t len);
extern void updater_finnish (void);
extern bool updater_verify (uint8_t *rbuff, uint8_t *hasbuff);
#endif /* UPDATER_H_ */

View File

@@ -45,6 +45,8 @@
#include "mpexception.h"
#include "telnet.h"
#include "pybuart.h"
#include "utils.h"
#include "irq.h"
#ifdef USE_FREERTOS
#include "FreeRTOS.h"
@@ -107,16 +109,23 @@ uint32_t HAL_GetTick(void) {
}
void HAL_Delay(uint32_t delay) {
#ifdef USE_FREERTOS
vTaskDelay (delay / portTICK_PERIOD_MS);
#else
uint32_t start = HAL_tickCount;
// Wraparound of tick is taken care of by 2's complement arithmetic.
while (HAL_tickCount - start < delay) {
// Enter sleep mode, waiting for (at least) the SysTick interrupt.
__WFI();
// only if we are not within interrupt context and interrupts are enabled
if ((HAL_NVIC_INT_CTRL_REG & HAL_VECTACTIVE_MASK) == 0 && query_irq() == IRQ_STATE_ENABLED) {
#ifdef USE_FREERTOS
vTaskDelay (delay / portTICK_PERIOD_MS);
#else
uint32_t start = HAL_tickCount;
// wraparound of tick is taken care of by 2's complement arithmetic.
while (HAL_tickCount - start < delay) {
// enter sleep mode, waiting for (at least) the SysTick interrupt.
__WFI();
}
#endif
} else {
for (int ms = 0; ms < delay; ms++) {
UtilsDelay(UTILS_DELAY_US_TO_COUNT(1000));
}
}
#endif
}
void mp_hal_set_interrupt_char (int c) {

View File

@@ -37,7 +37,7 @@
#define HAL_FCPU_MHZ 80U
#define HAL_FCPU_HZ (1000000U * HAL_FCPU_MHZ)
#define HAL_SYSTICK_PERIOD_US 1000U
#define UTILS_DELAY_US_TO_COUNT(us) (((us) * HAL_FCPU_MHZ) / 3)
#define UTILS_DELAY_US_TO_COUNT(us) (((us) * HAL_FCPU_MHZ) / 6)
#define HAL_NVIC_INT_CTRL_REG (*((volatile uint32_t *) 0xE000ED04 ) )
#define HAL_VECTACTIVE_MASK (0x1FUL)

View File

@@ -49,15 +49,6 @@
#include "inc/hw_ocp_shared.h"
#include "pin.h"
//*****************************************************************************
// Macros
//*****************************************************************************
#define PAD_MODE_MASK 0x0000000F
#define PAD_STRENGTH_MASK 0x000000E0
#define PAD_TYPE_MASK 0x00000310
#define PAD_CONFIG_BASE ((OCP_SHARED_BASE + \
OCP_SHARED_O_GPIO_PAD_CONFIG_0))
//*****************************************************************************
// PIN to PAD matrix
//*****************************************************************************

View File

@@ -143,6 +143,13 @@ extern "C"
#define PIN_TYPE_OD_PD 0x00000210
#define PIN_TYPE_ANALOG 0x10000000
//*****************************************************************************
// Macros for mode and type
//*****************************************************************************
#define PAD_MODE_MASK 0x0000000F
#define PAD_STRENGTH_MASK 0x000000E0
#define PAD_TYPE_MASK 0x00000310
#define PAD_CONFIG_BASE ((OCP_SHARED_BASE + OCP_SHARED_O_GPIO_PAD_CONFIG_0))
//*****************************************************************************
//

View File

@@ -129,11 +129,12 @@
//*****************************************************************************
//
// Bit: 31 is used to indicate use of RTC. If set as '1', RTC feature is used.
// Bit: 30 is used to indicate that a safe boot should be performed
// bit: 29 is used to indicate that the last reset was caused by the WDT
// Bits: 28 to 26 are unused
// Bit: 30 is used to indicate that a safe boot should be performed.
// bit: 29 is used to indicate that the last reset was caused by the WDT.
// bit: 28 is used to indicate that the board is booting for the first time after being programmed in factory.
// Bits: 27 and 26 are unused.
// Bits: 25 to 16 are used to save millisecond part of RTC reference.
// Bits: 15 to 0 are being used for HW Changes / ECO
// Bits: 15 to 0 are being used for HW Changes / ECO.
//
//*****************************************************************************
@@ -254,94 +255,49 @@ static const PRCM_PeriphRegs_t PRCM_PeriphRegsList[] =
//*****************************************************************************
//
//! Requests a safe boot
//! Set a special bit
//!
//! \return None.
//
//*****************************************************************************
void PRCMRequestSafeBoot(void)
void PRCMSetSpecialBit(unsigned char bit)
{
unsigned int uiRegValue;
uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) | (1 << 30);
uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) | (1 << bit);
PRCMHIBRegWrite(RTC_MSEC_U32_REG_ADDR, uiRegValue);
}
//*****************************************************************************
//
//! Clear the safe boot request
//! Clear a special bit
//!
//! \return None.
//
//*****************************************************************************
void PRCMClearSafeBootRequest(void)
void PRCMClearSpecialBit(unsigned char bit)
{
unsigned int uiRegValue;
uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (~(1 << 30));
uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (~(1 << bit));
PRCMHIBRegWrite(RTC_MSEC_U32_REG_ADDR, uiRegValue);
}
//*****************************************************************************
//
//! Read the safe boot request bit. This bit is cleared after reading.
//! Read a special bit
//!
//! \return Value of the safe boot bit
//! \return Value of the bit
//
//*****************************************************************************
tBoolean PRCMIsSafeBootRequested(void)
tBoolean PRCMGetSpecialBit(unsigned char bit)
{
tBoolean safeboot = (MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (1 << 30)) ? true : false;
PRCMClearSafeBootRequest();
return safeboot;
}
//*****************************************************************************
//
//! Signals that a WDT reset has occurred
//!
//! \return None.
//
//*****************************************************************************
void PRCMSignalWDTReset(void)
{
unsigned int uiRegValue;
uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) | (1 << 29);
PRCMHIBRegWrite(RTC_MSEC_U32_REG_ADDR, uiRegValue);
}
//*****************************************************************************
//
//! Clear the WDT reset signal
//!
//! \return None.
//
//*****************************************************************************
void PRCMClearWDTResetSignal(void)
{
unsigned int uiRegValue;
uiRegValue = MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (~(1 << 29));
PRCMHIBRegWrite(RTC_MSEC_U32_REG_ADDR, uiRegValue);
}
//*****************************************************************************
//
//! Read the WDT reset signal bit
//!
//! \return Value of the WDT reset signal bit
//
//*****************************************************************************
tBoolean PRCMWasResetBecauseOfWDT(void)
{
return (MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (1 << 29)) ? true : false;
tBoolean value = (MAP_PRCMHIBRegRead(RTC_MSEC_U32_REG_ADDR) & (1 << bit)) ? true : false;
// special bits must be cleared immediatelly after reading
PRCMClearSpecialBit(bit);
return value;
}
//*****************************************************************************

View File

@@ -192,17 +192,21 @@ unsigned char ulRstReg;
// PRCM_ADC should never be used in any user code.
#define PRCM_ADC 0x000000FF
//*****************************************************************************
// User bits in the PRCM persistent registers
//*****************************************************************************
#define PRCM_SAFE_BOOT_BIT 30
#define PRCM_WDT_RESET_BIT 29
#define PRCM_FIRST_BOOT_BIT 28
//*****************************************************************************
//
// API Function prototypes
//
//*****************************************************************************
extern void PRCMRequestSafeBoot(void);
extern void PRCMClearSafeBootRequest(void);
extern tBoolean PRCMIsSafeBootRequested(void);
extern void PRCMSignalWDTReset(void);
extern void PRCMClearWDTResetSignal(void);
extern tBoolean PRCMWasResetBecauseOfWDT(void);
extern void PRCMSetSpecialBit(unsigned char bit);
extern void PRCMClearSpecialBit(unsigned char bit);
extern tBoolean PRCMGetSpecialBit(unsigned char bit);
extern void PRCMSOCReset(void);
extern void PRCMMCUReset(tBoolean bIncludeSubsystem);
extern unsigned long PRCMSysResetCauseGet(void);

View File

@@ -34,6 +34,7 @@
#include "simplelink.h"
#include "pybwdt.h"
#include "debug.h"
#include "antenna.h"
#include "mperror.h"
/******************************************************************************
@@ -65,6 +66,11 @@ int main (void) {
// Initialize the clocks and the interrupt system
HAL_SystemInit();
#if MICROPY_HW_ANTENNA_DIVERSITY
// configure the antenna selection pins
antenna_init0();
#endif
// Init the watchdog
pybwdt_init0();

View File

@@ -34,7 +34,6 @@
#include "inc/hw_memmap.h"
#include "pybuart.h"
#include "osi.h"
#include "pybwdt.h"
#include "mperror.h"
@@ -49,8 +48,6 @@
//*****************************************************************************
void vApplicationIdleHook (void)
{
// kick the watchdog
pybwdt_kick();
// signal that we are alive and kicking
mperror_heartbeat_signal();
// gate the processor's clock to save power

97
cc3200/misc/antenna.c Normal file
View File

@@ -0,0 +1,97 @@
/*
* 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.
*/
#include <stdint.h>
#include "mpconfigboard.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "rom_map.h"
#include "pin.h"
#include "prcm.h"
#include "gpio.h"
#include "antenna.h"
#if MICROPY_HW_ANTENNA_DIVERSITY
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
#define REG_PAD_CONFIG_26 (0x4402E108)
#define REG_PAD_CONFIG_27 (0x4402E10C)
/******************************************************************************
DEFINE PRIVATE DATA
******************************************************************************/
static antenna_type_t antenna_type_selected = ANTENNA_TYPE_INTERNAL;
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
void antenna_init0(void) {
// enable the peripheral clock and set the gpio direction for
// both antenna 1 and antenna 2 pins
MAP_PRCMPeripheralClkEnable(PRCM_GPIOA3, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
MAP_GPIODirModeSet(GPIOA3_BASE, 0x0C, GPIO_DIR_MODE_OUT);
// configure antenna 1 pin type and strength
HWREG(REG_PAD_CONFIG_26) = ((HWREG(REG_PAD_CONFIG_26) & ~(PAD_STRENGTH_MASK | PAD_TYPE_MASK)) | (0x00000020 | 0x00000000));
// set the mode
HWREG(REG_PAD_CONFIG_26) = ((HWREG(REG_PAD_CONFIG_26) & ~PAD_MODE_MASK) | 0x00000000) & ~(3 << 10);
// set the direction
HWREG(REG_PAD_CONFIG_26) = ((HWREG(REG_PAD_CONFIG_26) & ~0xC00) | 0x00000800);
// configure antenna 2 pin type and strength
HWREG(REG_PAD_CONFIG_27) = ((HWREG(REG_PAD_CONFIG_27) & ~(PAD_STRENGTH_MASK | PAD_TYPE_MASK)) | (0x00000020 | 0x00000000));
// set the mode
HWREG(REG_PAD_CONFIG_27) = ((HWREG(REG_PAD_CONFIG_27) & ~PAD_MODE_MASK) | 0x00000000) & ~(3 << 10);
// set the direction
HWREG(REG_PAD_CONFIG_27) = ((HWREG(REG_PAD_CONFIG_27) & ~0xC00) | 0x00000800);
// select the currently active antenna
antenna_select(antenna_type_selected);
}
void antenna_select (antenna_type_t _antenna) {
if (_antenna == ANTENNA_TYPE_INTERNAL) {
MAP_GPIOPinWrite(GPIOA3_BASE, 0x0C, 0x04);
// also configure the pull-up and pull-down accordingly
HWREG(REG_PAD_CONFIG_26) = ((HWREG(REG_PAD_CONFIG_26) & ~PAD_TYPE_MASK)) | PIN_TYPE_STD_PU;
HWREG(REG_PAD_CONFIG_27) = ((HWREG(REG_PAD_CONFIG_27) & ~PAD_TYPE_MASK)) | PIN_TYPE_STD_PD;
} else {
MAP_GPIOPinWrite(GPIOA3_BASE, 0x0C, 0x08);
// also configure the pull-up and pull-down accordingly
HWREG(REG_PAD_CONFIG_26) = ((HWREG(REG_PAD_CONFIG_26) & ~PAD_TYPE_MASK)) | PIN_TYPE_STD_PD;
HWREG(REG_PAD_CONFIG_27) = ((HWREG(REG_PAD_CONFIG_27) & ~PAD_TYPE_MASK)) | PIN_TYPE_STD_PU;
}
antenna_type_selected = _antenna;
}
#endif

View File

@@ -3,7 +3,6 @@
*
* 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
@@ -25,31 +24,15 @@
* THE SOFTWARE.
*/
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/obj.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "rom_map.h"
#include "gpio.h"
#include "pin.h"
#include "pybpin.h"
#ifndef _ANTENNA_H_
#define _ANTENNA_H_
typedef enum {
ANTENNA_TYPE_INTERNAL = 0,
ANTENNA_TYPE_EXTERNAL
} antenna_type_t;
extern void antenna_init0 (void);
extern void antenna_select (antenna_type_t antenna_type);
// Returns the pin mode. This value returned by this macro should be one of:
// GPIO_DIR_MODE_IN or GPIO_DIR_MODE_OUT
uint32_t pin_get_mode (const pin_obj_t *self) {
return self->mode;
}
uint32_t pin_get_type (const pin_obj_t *self) {
return self->type;
}
uint32_t pin_get_strenght (const pin_obj_t *self) {
return self->strength;
}
#endif /* _ANTENNA_H_ */

View File

@@ -24,6 +24,8 @@
* THE SOFTWARE.
*/
#include "std.h"
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/obj.h"
@@ -41,7 +43,7 @@
DEFINE PUBLIC DATA
******************************************************************************/
const mp_arg_t mpcallback_init_args[] = {
{ MP_QSTR_intmode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_handler, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_priority, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
{ MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
@@ -71,7 +73,6 @@ mp_obj_t mpcallback_new (mp_obj_t parent, mp_obj_t handler, const mp_cb_methods_
mpcallback_obj_t *mpcallback_find (mp_obj_t parent) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(mpcallback_obj_list).len; i++) {
// search for the object and then remove it
mpcallback_obj_t *callback_obj = ((mpcallback_obj_t *)(MP_STATE_PORT(mpcallback_obj_list).items[i]));
if (callback_obj->parent == parent) {
return callback_obj;
@@ -125,10 +126,8 @@ uint mpcallback_translate_priority (uint priority) {
void mpcallback_handler (mp_obj_t self_in) {
mpcallback_obj_t *self = self_in;
if (self && self->handler != mp_const_none) {
// disable interrupts to avoid nesting
uint primsk = disable_irq();
// when executing code within a handler we must lock the GC to prevent
// any memory allocations. We must also catch any exceptions.
// any memory allocations.
gc_lock();
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
@@ -139,13 +138,13 @@ void mpcallback_handler (mp_obj_t self_in) {
// uncaught exception; disable the callback so that it doesn't run again
self->methods->disable (self->parent);
self->handler = mp_const_none;
// printing an exception here will cause a stack overflow that will end up in
// a hard fault, so is better to signal the uncaught (probably non-recoverable)
// exception by blinking the system led instead.
// signal the error using the heart beat led and print an
// exception message as well
mperror_signal_error();
printf("Uncaught exception in callback handler\n");
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
}
gc_unlock();
enable_irq(primsk);
}
}

View File

@@ -25,13 +25,14 @@
* THE SOFTWARE.
*/
#include <std.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/obj.h"
#include "py/runtime.h"
#include "hw_ints.h"
#include "hw_types.h"
#include "hw_gpio.h"
@@ -63,12 +64,17 @@
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
#ifndef BOOTLOADER
STATIC const mp_obj_base_t pyb_heartbeat_obj = {&pyb_heartbeat_type};
#endif
struct mperror_heart_beat {
uint32_t off_time;
uint32_t on_time;
bool beating;
bool enabled;
} mperror_heart_beat = {.off_time = 0, .on_time = 0, .beating = false, .enabled = false};
bool do_disable;
} mperror_heart_beat = {.off_time = 0, .on_time = 0, .beating = false, .enabled = false, .do_disable = false};
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
@@ -90,6 +96,7 @@ void mperror_init0 (void) {
// configure the system led
pin_config ((pin_obj_t *)&MICROPY_SYS_LED_GPIO, PIN_MODE_0, GPIO_DIR_MODE_OUT, PIN_TYPE_STD, PIN_STRENGTH_6MA);
#endif
mperror_heart_beat.enabled = true;
mperror_heartbeat_switch_off();
}
@@ -108,7 +115,7 @@ void mperror_bootloader_check_reset_cause (void) {
// since the reset cause will be changed, we must store the right reason
// so that the application knows it when booting for the next time
PRCMSignalWDTReset();
PRCMSetSpecialBit(PRCM_WDT_RESET_BIT);
MAP_PRCMHibernateWakeupSourceEnable(PRCM_HIB_SLOW_CLK_CTR);
// set the sleep interval to 10ms
@@ -131,23 +138,21 @@ void mperror_signal_error (void) {
}
}
void mperror_enable_heartbeat (void) {
mperror_heart_beat.enabled = true;
}
void mperror_heartbeat_switch_off (void) {
mperror_heart_beat.on_time = 0;
mperror_heart_beat.off_time = 0;
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0);
}
void mperror_disable_heartbeat (void) {
mperror_heart_beat.enabled = false;
mperror_heartbeat_switch_off();
if (mperror_heart_beat.enabled) {
mperror_heart_beat.on_time = 0;
mperror_heart_beat.off_time = 0;
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, 0);
}
}
void mperror_heartbeat_signal (void) {
if (mperror_heart_beat.enabled) {
if (mperror_heart_beat.do_disable) {
mperror_heart_beat.do_disable = false;
mperror_heartbeat_switch_off();
mperror_heart_beat.enabled = false;
}
else if (mperror_heart_beat.enabled) {
if (!mperror_heart_beat.beating) {
if ((mperror_heart_beat.on_time = HAL_GetTick()) - mperror_heart_beat.off_time > MPERROR_HEARTBEAT_OFF_MS) {
MAP_GPIOPinWrite(MICROPY_SYS_LED_PORT, MICROPY_SYS_LED_PORT_PIN, MICROPY_SYS_LED_PORT_PIN);
@@ -198,10 +203,21 @@ void nlr_jump_fail(void *val) {
/******************************************************************************/
// Micro Python bindings
/// \classmethod \constructor()
///
/// Return the heart beat object
STATIC mp_obj_t pyb_heartbeat_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 0, 0, false);
// return constant object
return (mp_obj_t)&pyb_heartbeat_obj;
}
/// \function enable()
/// Enables the heartbeat signal
STATIC mp_obj_t pyb_enable_heartbeat(mp_obj_t self) {
mperror_enable_heartbeat ();
mperror_heart_beat.enabled = true;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_enable_heartbeat_obj, pyb_enable_heartbeat);
@@ -209,7 +225,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_enable_heartbeat_obj, pyb_enable_heartbeat)
/// \function disable()
/// Disables the heartbeat signal
STATIC mp_obj_t pyb_disable_heartbeat(mp_obj_t self) {
mperror_disable_heartbeat ();
mperror_heart_beat.do_disable = true;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_disable_heartbeat_obj, pyb_disable_heartbeat);
@@ -220,11 +236,11 @@ STATIC const mp_map_elem_t pyb_heartbeat_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_heartbeat_locals_dict, pyb_heartbeat_locals_dict_table);
static const mp_obj_type_t pyb_heartbeat_type = {
const mp_obj_type_t pyb_heartbeat_type = {
{ &mp_type_type },
.name = MP_QSTR_HeartBeat,
.make_new = pyb_heartbeat_make_new,
.locals_dict = (mp_obj_t)&pyb_heartbeat_locals_dict,
};
const mp_obj_base_t pyb_heartbeat_obj = {&pyb_heartbeat_type};
#endif

View File

@@ -29,7 +29,7 @@
#define MPERROR_H_
#ifndef BOOTLOADER
extern const mp_obj_base_t pyb_heartbeat_obj;
extern const mp_obj_type_t pyb_heartbeat_type;
#endif
extern void NORETURN __fatal_error(const char *msg);
@@ -38,9 +38,7 @@ void mperror_init0 (void);
void mperror_bootloader_check_reset_cause (void);
void mperror_deinit_sfe_pin (void);
void mperror_signal_error (void);
void mperror_enable_heartbeat (void);
void mperror_heartbeat_switch_off (void);
void mperror_disable_heartbeat (void);
void mperror_heartbeat_signal (void);
#endif // MPERROR_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

@@ -28,7 +28,6 @@
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/obj.h"
#include "irq.h"
#include "mpsystick.h"
#include "systick.h"
#include "inc/hw_types.h"

View File

@@ -30,16 +30,17 @@
#include <string.h>
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/obj.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "pybpin.h"
#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) {
STATIC void pin_named_pins_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pin_named_pins_obj_t *self = self_in;
print(env, "<Pin.%s>", qstr_str(self->name));
mp_printf(print, "<Pin.%q>", self->name);
}
const mp_obj_type_t pin_cpu_pins_obj_type = {
@@ -58,16 +59,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

@@ -26,86 +26,75 @@
*/
#include <std.h>
#include <stdint.h>
#include <string.h>
#include "py/mpstate.h"
#include MICROPY_HAL_H
#include "modnetwork.h"
#include "mpexception.h"
#include "serverstask.h"
#include "simplelink.h"
/// \module network - network configuration
///
/// This module provides network drivers and routing configuration.
/// This module provides network drivers and server configuration.
void mod_network_init0(void) {
mp_obj_list_init(&MP_STATE_PORT(mod_network_nic_list), 0);
}
void mod_network_register_nic(mp_obj_t nic) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) {
if (MP_STATE_PORT(mod_network_nic_list).items[i] == nic) {
// nic already registered
return;
}
}
// nic not registered so add to list
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
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));
}
STATIC mp_obj_t network_route(void) {
return &MP_STATE_PORT(mod_network_nic_list);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_route_obj, network_route);
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
STATIC mp_obj_t network_server_start(void) {
servers_start();
return mp_const_none;
STATIC mp_obj_t network_server_running(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args > 0) {
// set
if (mp_obj_is_true(args[0])) {
servers_start();
} else {
servers_stop();
}
return mp_const_none;
} else {
// get
return MP_BOOL(servers_are_enabled());
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_server_start_obj, network_server_start);
STATIC mp_obj_t network_server_stop(void) {
servers_stop();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_server_stop_obj, network_server_stop);
STATIC mp_obj_t network_server_enabled(void) {
return MP_BOOL(servers_are_enabled());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_server_enabled_obj, network_server_enabled);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_server_running_obj, 0, 1, network_server_running);
STATIC mp_obj_t network_server_login(mp_obj_t user, mp_obj_t pass) {
const char *_user = mp_obj_str_get_str(user);
const char *_pass = mp_obj_str_get_str(pass);
if (strlen(user) > SERVERS_USER_PASS_LEN_MAX || strlen(pass) > SERVERS_USER_PASS_LEN_MAX) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
servers_set_login ((char *)_user, (char *)_pass);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(network_server_login_obj, network_server_login);
// timeout value given in seconds
STATIC mp_obj_t network_server_timeout(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args > 0) {
uint32_t _timeout = mp_obj_get_int(args[0]);
if (!servers_set_timeout(_timeout * 1000)) {
// timeout is too low
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
return mp_const_none;
} else {
// get
return mp_obj_new_int(servers_get_timeout() / 1000);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(network_server_timeout_obj, 0, 1, network_server_timeout);
#endif
STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&mod_network_nic_type_wlan },
{ MP_OBJ_NEW_QSTR(MP_QSTR_route), (mp_obj_t)&network_route_obj },
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
{ MP_OBJ_NEW_QSTR(MP_QSTR_start_server), (mp_obj_t)&network_server_start_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_stop_server), (mp_obj_t)&network_server_stop_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_server_enabled), (mp_obj_t)&network_server_enabled_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_server_running), (mp_obj_t)&network_server_running_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_server_login), (mp_obj_t)&network_server_login_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_server_timeout), (mp_obj_t)&network_server_timeout_obj },
#endif
};
@@ -116,65 +105,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,57 +25,50 @@
* THE SOFTWARE.
*/
#ifndef MODNETWORK_H_
#define MODNETWORK_H_
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
#define MOD_NETWORK_IPV4ADDR_BUF_SIZE (4)
// Forward declaration
struct _mod_network_socket_obj_t;
/******************************************************************************
DEFINE TYPES
******************************************************************************/
typedef struct _mod_network_nic_type_t {
mp_obj_type_t base;
// API for non-socket operations
int (*gethostbyname)(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *ip_out, uint8_t family);
// API for socket operations; return -1 on error
int (*socket)(struct _mod_network_socket_obj_t *s, int *_errno);
void (*close)(struct _mod_network_socket_obj_t *socket);
int (*bind)(struct _mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno);
int (*listen)(struct _mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno);
int (*accept)(struct _mod_network_socket_obj_t *s, struct _mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno);
int (*connect)(struct _mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno);
int (*send)(struct _mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno);
int (*recv)(struct _mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno);
int (*sendto)(struct _mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno);
int (*recvfrom)(struct _mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno);
int (*setsockopt)(struct _mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno);
int (*settimeout)(struct _mod_network_socket_obj_t *s, mp_uint_t timeout_ms, int *_errno);
int (*ioctl)(struct _mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno);
} mod_network_nic_type_t;
typedef struct _mod_network_socket_obj_t {
mp_obj_base_t base;
mp_obj_t nic;
mod_network_nic_type_t *nic_type;
typedef struct _mod_network_socket_base_t {
union {
struct {
// this order is important so that fileno gets > 0 once
// the socket descriptor is assigned after being created.
uint8_t domain;
int8_t fileno;
uint8_t type;
uint8_t proto;
int8_t fileno;
} u_param;
int16_t sd;
};
bool closed;
bool has_timeout;
bool cert_req;
} mod_network_socket_base_t;
typedef struct _mod_network_socket_obj_t {
mp_obj_base_t base;
mod_network_socket_base_t sock_base;
} mod_network_socket_obj_t;
/******************************************************************************
EXPORTED DATA
******************************************************************************/
extern const mod_network_nic_type_t mod_network_nic_type_wlan;
/******************************************************************************
DECLARE FUNCTIONS
******************************************************************************/
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);
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"
@@ -38,6 +37,7 @@
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_uart.h"
#include "rom_map.h"
#include "prcm.h"
#include "pyexec.h"
#include "pybuart.h"
@@ -45,6 +45,7 @@
#include "pybrtc.h"
#include "mpsystick.h"
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
#include "moduos.h"
#include "telnet.h"
@@ -63,9 +64,11 @@
#include "pybwdt.h"
#include "pybsleep.h"
#include "pybspi.h"
#include "pybtimer.h"
#include "utils.h"
#include "gccollect.h"
#include "mperror.h"
#include "genhdr/mpversion.h"
#ifdef DEBUG
@@ -79,17 +82,17 @@ extern OsiTaskHandle xSimpleLinkSpawnTaskHndl;
///
/// The `pyb` module contains specific functions related to the pyboard.
/// \function hard_reset()
/// Resets the pyboard in a manner similar to pushing the external RESET
/// button.
STATIC mp_obj_t pyb_hard_reset(void) {
/// \function reset()
/// Resets the pyboard in a manner similar to pushing the external
/// reset button.
STATIC mp_obj_t pyb_reset(void) {
// disable wlan
wlan_stop(SL_STOP_TIMEOUT_LONG);
// perform a SoC reset
PRCMSOCReset();
// reset the cpu and it's peripherals
MAP_PRCMMCUReset(true);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_hard_reset_obj, pyb_hard_reset);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_reset_obj, pyb_reset);
#ifdef DEBUG
/// \function info([dump_alloc_table])
@@ -123,10 +126,22 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj, 0, 1, pyb_info);
/// \function freq()
/// Returns the CPU frequency: (F_CPU).
STATIC mp_obj_t pyb_freq(void) {
return mp_obj_new_int(HAL_FCPU_HZ);
mp_obj_t tuple[1] = {
mp_obj_new_int(HAL_FCPU_HZ),
};
return mp_obj_new_tuple(1, tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_freq_obj, pyb_freq);
/// \function unique_id()
/// Returns a string of 6 bytes (48 bits), which is the unique ID for the MCU.
STATIC mp_obj_t pyb_unique_id(void) {
uint8_t mac[SL_BSSID_LENGTH];
wlan_get_mac (mac);
return mp_obj_new_bytes(mac, SL_BSSID_LENGTH);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_unique_id_obj, pyb_unique_id);
/// \function millis()
/// Returns the number of milliseconds since the board was last reset.
///
@@ -233,27 +248,17 @@ 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[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_reset), (mp_obj_t)&pyb_hard_reset_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_reset), (mp_obj_t)&pyb_reset_obj },
#ifdef DEBUG
{ MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_info_obj },
#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&pyb_freq_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_unique_id), (mp_obj_t)&pyb_unique_id_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_repl_info), (mp_obj_t)&pyb_set_repl_info_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_repl_uart), (mp_obj_t)&pyb_repl_uart_obj },
@@ -268,15 +273,13 @@ 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 },
#endif
#if MICROPY_HW_ENABLE_RTC
{ MP_OBJ_NEW_QSTR(MP_QSTR_RTC), (mp_obj_t)&pyb_rtc_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RTC), (mp_obj_t)&pyb_rtc_type },
#endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pin_type },
@@ -284,9 +287,10 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_i2c_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&pyb_spi_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WDT), (mp_obj_t)&pyb_wdt_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Timer), (mp_obj_t)&pyb_timer_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WDT), (mp_obj_t)&pyb_wdt_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Sleep), (mp_obj_t)&pyb_sleep_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HeartBeat), (mp_obj_t)&pyb_heartbeat_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HeartBeat), (mp_obj_t)&pyb_heartbeat_type },
#if MICROPY_HW_HAS_SDCARD
{ MP_OBJ_NEW_QSTR(MP_QSTR_SD), (mp_obj_t)&pyb_sd_type },

View File

@@ -0,0 +1,64 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Paul Sokolovsky
* Copyright (c) 2015 Daniel Campora
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/binary.h"
#include "extmod/modubinascii.h"
#include "modubinascii.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_dthe.h"
#include "hw_memmap.h"
#include "rom_map.h"
#include "prcm.h"
#include "crc.h"
#include "cryptohash.h"
#include "mpexception.h"
/******************************************************************************/
// Micro Python bindings
STATIC const mp_map_elem_t mp_module_binascii_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ubinascii) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_hexlify), (mp_obj_t)&mod_binascii_hexlify_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_unhexlify), (mp_obj_t)&mod_binascii_unhexlify_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_a2b_base64), (mp_obj_t)&mod_binascii_a2b_base64_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_b2a_base64), (mp_obj_t)&mod_binascii_b2a_base64_obj },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table);
const mp_obj_module_t mp_module_ubinascii = {
.base = { &mp_type_module },
.name = MP_QSTR_ubinascii,
.globals = (mp_obj_dict_t*)&mp_module_binascii_globals,
};

View File

@@ -0,0 +1,31 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2014 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.
*/
#ifndef MODUBINASCII_H_
#define MODUBINASCII_H_
#endif /* MODUBINASCII_H_ */

210
cc3200/mods/moduhashlib.c Normal file
View File

@@ -0,0 +1,210 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Paul Sokolovsky
* Copyright (c) 2015 Daniel Campora
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <assert.h>
#include <string.h>
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/nlr.h"
#include "py/runtime.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_shamd5.h"
#include "inc/hw_dthe.h"
#include "hw_memmap.h"
#include "rom_map.h"
#include "prcm.h"
#include "shamd5.h"
#include "cryptohash.h"
#include "mpexception.h"
/******************************************************************************
DEFINE PRIVATE TYPES
******************************************************************************/
typedef struct _mp_obj_hash_t {
mp_obj_base_t base;
uint8_t *buffer;
uint32_t b_size;
uint32_t c_size;
uint8_t algo;
uint8_t h_size;
bool fixedlen;
bool digested;
uint8_t hash[32];
} mp_obj_hash_t;
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC void hash_update_internal(mp_obj_t self_in, mp_obj_t data, bool digest);
STATIC mp_obj_t hash_read (mp_obj_t self_in);
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
STATIC void hash_update_internal(mp_obj_t self_in, mp_obj_t data, bool digest) {
mp_obj_hash_t *self = self_in;
mp_buffer_info_t bufinfo;
if (data) {
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
}
if (digest) {
CRYPTOHASH_SHAMD5Start (self->algo, self->b_size);
}
if (self->c_size < self->b_size || !data || !self->fixedlen) {
if (digest || self->fixedlen) {
// no data means we want to process our internal buffer
CRYPTOHASH_SHAMD5Update (data ? bufinfo.buf : self->buffer, data ? bufinfo.len : self->b_size);
self->c_size += data ? bufinfo.len : 0;
} else {
self->buffer = m_renew(byte, self->buffer, self->b_size, self->b_size + bufinfo.len);
mp_seq_copy((byte*)self->buffer + self->b_size, bufinfo.buf, bufinfo.len, byte);
self->b_size += bufinfo.len;
self->digested = false;
}
} else {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
}
STATIC mp_obj_t hash_read (mp_obj_t self_in) {
mp_obj_hash_t *self = self_in;
if (!self->fixedlen) {
if (!self->digested) {
hash_update_internal(self, MP_OBJ_NULL, true);
}
} else if (self->c_size < self->b_size) {
// it's a fixed len block which is still incomplete
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
if (!self->digested) {
CRYPTOHASH_SHAMD5Read ((uint8_t *)self->hash);
self->digested = true;
}
return mp_obj_new_bytes(self->hash, self->h_size);
}
/******************************************************************************/
// Micro Python bindings
/// \classmethod \constructor([data[, block_size]])
/// initial data must be given if block_size wants to be passed
STATIC mp_obj_t hash_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, 2, false);
mp_obj_hash_t *self = m_new0(mp_obj_hash_t, 1);
self->base.type = type_in;
if (self->base.type->name == MP_QSTR_sha1) {
self->algo = SHAMD5_ALGO_SHA1;
self->h_size = 20;
} else /* if (self->base.type->name == MP_QSTR_sha256) */ {
self->algo = SHAMD5_ALGO_SHA256;
self->h_size = 32;
} /* else {
self->algo = SHAMD5_ALGO_MD5;
self->h_size = 32;
} */
if (n_args) {
// CPython extension to avoid buffering the data before digesting it
// Note: care must be taken to provide all intermediate blocks as multiple
// of four bytes, otherwise the resulting hash will be incorrect.
// the final block can be of any length
if (n_args > 1) {
// block size given, we will feed the data directly into the hash engine
self->fixedlen = true;
self->b_size = mp_obj_get_int(args[1]);
hash_update_internal(self, args[0], true);
} else {
hash_update_internal(self, args[0], false);
}
}
return self;
}
STATIC mp_obj_t hash_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = self_in;
hash_update_internal(self, arg, false);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(hash_update_obj, hash_update);
STATIC mp_obj_t hash_digest(mp_obj_t self_in) {
return hash_read(self_in);
}
MP_DEFINE_CONST_FUN_OBJ_1(hash_digest_obj, hash_digest);
STATIC const mp_map_elem_t hash_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_update), (mp_obj_t) &hash_update_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_digest), (mp_obj_t) &hash_digest_obj },
};
STATIC MP_DEFINE_CONST_DICT(hash_locals_dict, hash_locals_dict_table);
//STATIC const mp_obj_type_t md5_type = {
// { &mp_type_type },
// .name = MP_QSTR_md5,
// .make_new = hash_make_new,
// .locals_dict = (mp_obj_t)&hash_locals_dict,
//};
STATIC const mp_obj_type_t sha1_type = {
{ &mp_type_type },
.name = MP_QSTR_sha1,
.make_new = hash_make_new,
.locals_dict = (mp_obj_t)&hash_locals_dict,
};
STATIC const mp_obj_type_t sha256_type = {
{ &mp_type_type },
.name = MP_QSTR_sha256,
.make_new = hash_make_new,
.locals_dict = (mp_obj_t)&hash_locals_dict,
};
STATIC const mp_map_elem_t mp_module_hashlib_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib) },
// { MP_OBJ_NEW_QSTR(MP_QSTR_md5), (mp_obj_t)&md5_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sha1), (mp_obj_t)&sha1_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sha256), (mp_obj_t)&sha256_type },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_hashlib_globals, mp_module_hashlib_globals_table);
const mp_obj_module_t mp_module_uhashlib = {
.base = { &mp_type_module },
.name = MP_QSTR_uhashlib,
.globals = (mp_obj_dict_t*)&mp_module_hashlib_globals,
};

View File

@@ -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,27 @@ 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 MICROPY_HW_HAS_SDCARD
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));
}
#endif
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 +180,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 +213,44 @@ 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 rename(old_path, new_path)
/// Rename a file
STATIC mp_obj_t os_rename(mp_obj_t path_in, mp_obj_t path_out) {
const char *old_path = mp_obj_str_get_str(path_in);
const char *new_path = mp_obj_str_get_str(path_out);
FRESULT res = f_rename(old_path, new_path);
switch (res) {
case FR_OK:
return mp_const_none;
default:
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename);
/// \function remove(path)
/// Remove a file.
/// 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 +270,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 +303,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 +331,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 +353,38 @@ STATIC mp_obj_t os_urandom(mp_obj_t num) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
#endif
/// \function mkfs('path')
/// Formats the selected drive, useful when the filesystem has been damaged beyond repair
STATIC mp_obj_t os_mkfs(mp_obj_t path_o) {
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_mkfs_obj, os_mkfs);
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_rename), (mp_obj_t)&os_rename_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&os_remove_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rmdir), (mp_obj_t)&os_remove_obj }, // rmdir aliases to remove
{ MP_OBJ_NEW_QSTR(MP_QSTR_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_mkfs), (mp_obj_t)&os_mkfs_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,69 +25,145 @@
* THE SOFTWARE.
*/
#include <std.h>
#include <stdint.h>
#include <string.h>
#include "simplelink.h"
#include "py/mpstate.h"
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/obj.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "netutils.h"
#include "modnetwork.h"
#include "modwlan.h"
#include "modusocket.h"
#include "mpexception.h"
/******************************************************************************
DEFINE PRIVATE CONSTANTS
******************************************************************************/
#define MOD_NETWORK_MAX_SOCKETS 10
/******************************************************************************
DEFINE PRIVATE TYPES
******************************************************************************/
typedef struct {
int16_t sd;
bool user;
} modusocket_sock_t;
/******************************************************************************
DEFINE PRIVATE DATA
******************************************************************************/
STATIC const mp_obj_type_t socket_type;
STATIC OsiLockObj_t modusocket_LockObj;
STATIC modusocket_sock_t modusocket_sockets[MOD_NETWORK_MAX_SOCKETS] = {{.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1},
{.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}, {.sd = -1}};
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
__attribute__ ((section (".boot")))
void modusocket_pre_init (void) {
// create the wlan lock
ASSERT(OSI_OK == sl_LockObjCreate(&modusocket_LockObj, "SockLock"));
sl_LockObjUnlock (&modusocket_LockObj);
}
void modusocket_socket_add (int16_t sd, bool user) {
sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER);
for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) {
if (modusocket_sockets[i].sd < 0) {
modusocket_sockets[i].sd = sd;
modusocket_sockets[i].user = user;
break;
}
}
sl_LockObjUnlock (&modusocket_LockObj);
}
void modusocket_socket_delete (int16_t sd) {
sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER);
for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) {
if (modusocket_sockets[i].sd == sd) {
modusocket_sockets[i].sd = -1;
break;
}
}
sl_LockObjUnlock (&modusocket_LockObj);
}
void modusocket_enter_sleep (void) {
fd_set socketset;
int16_t maxfd = 0;
for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) {
int16_t sd;
if ((sd = modusocket_sockets[i].sd) >= 0) {
FD_SET(sd, &socketset);
maxfd = (maxfd > sd) ? maxfd : sd;
}
}
// wait for any of the sockets to become ready...
sl_Select(maxfd + 1, &socketset, NULL, NULL, NULL);
}
void modusocket_close_all_user_sockets (void) {
sl_LockObjLock (&modusocket_LockObj, SL_OS_WAIT_FOREVER);
for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) {
if (modusocket_sockets[i].sd >= 0 && modusocket_sockets[i].user) {
sl_Close(modusocket_sockets[i].sd);
modusocket_sockets[i].sd = -1;
}
}
sl_LockObjUnlock (&modusocket_LockObj);
}
/******************************************************************************/
// socket class
STATIC const mp_obj_type_t socket_type;
// 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);
// create socket object (not bound to any NIC yet)
// create socket object
mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t);
s->base.type = (mp_obj_t)&socket_type;
s->nic = MP_OBJ_NULL;
s->nic_type = NULL;
s->u_param.domain = AF_INET;
s->u_param.type = SOCK_STREAM;
s->u_param.proto = IPPROTO_TCP;
s->u_param.fileno = -1;
if (n_args >= 1) {
s->u_param.domain = mp_obj_get_int(args[0]);
if (n_args >= 2) {
s->u_param.type = mp_obj_get_int(args[1]);
if (n_args >= 3) {
s->u_param.proto = mp_obj_get_int(args[2]);
if (n_args == 4) {
s->u_param.fileno = mp_obj_get_int(args[3]);
s->sock_base.u_param.domain = AF_INET;
s->sock_base.u_param.type = SOCK_STREAM;
s->sock_base.u_param.proto = IPPROTO_TCP;
s->sock_base.u_param.fileno = -1;
s->sock_base.has_timeout = false;
s->sock_base.cert_req = false;
if (n_args > 0) {
s->sock_base.u_param.domain = mp_obj_get_int(args[0]);
if (n_args > 1) {
s->sock_base.u_param.type = mp_obj_get_int(args[1]);
if (n_args > 2) {
s->sock_base.u_param.proto = mp_obj_get_int(args[2]);
if (n_args > 3) {
s->sock_base.u_param.fileno = mp_obj_get_int(args[3]);
}
}
}
}
// create the socket
int _errno;
if (wlan_socket_socket(s, &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
}
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;
if (self->nic != MP_OBJ_NULL) {
self->nic_type->close(self);
}
wlan_socket_close(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close);
@@ -98,17 +174,13 @@ 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;
if (self->nic_type->bind(self, ip, port, &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
if (wlan_socket_bind(self, ip, port, &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
@@ -117,16 +189,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog) {
mod_network_socket_obj_t *self = self_in;
if (self->nic == MP_OBJ_NULL) {
// not connected
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN)));
}
int _errno;
if (self->nic_type->listen(self, mp_obj_get_int(backlog), &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
if (wlan_socket_listen(self, mp_obj_get_int(backlog), &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen);
@@ -136,29 +202,25 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
mod_network_socket_obj_t *self = self_in;
// create new socket object
// starts with empty NIC so that finaliser doesn't run close() method if accept() fails
mod_network_socket_obj_t *socket2 = m_new_obj_with_finaliser(mod_network_socket_obj_t);
socket2->base.type = (mp_obj_t)&socket_type;
socket2->nic = MP_OBJ_NULL;
socket2->nic_type = NULL;
// the new socket inherits all properties from its parent
memcpy (socket2, self, sizeof(mod_network_socket_obj_t));
// accept incoming connection
// accept the incoming connection
uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
mp_uint_t port;
int _errno;
if (self->nic_type->accept(self, socket2, ip, &port, &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
if (wlan_socket_accept(self, socket2, ip, &port, &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
}
// new socket has valid state, so set the NIC to the same as parent
socket2->nic = self->nic;
socket2->nic_type = self->nic_type;
// add the socket to the list
modusocket_socket_add(socket2->sock_base.sd, true);
// 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;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
@@ -169,17 +231,16 @@ 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);
mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE);
// check if we need to select a NIC
socket_select_nic(self, ip);
// call the NIC to connect the socket
// connect the socket
int _errno;
if (self->nic_type->connect(self, ip, port, &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
if (wlan_socket_connect(self, ip, port, &_errno) != 0) {
if (!self->sock_base.cert_req && _errno == SL_ESECSNOVERIFY) {
return mp_const_none;
}
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
@@ -187,16 +248,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
// method socket.send(bytes)
STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
mod_network_socket_obj_t *self = self_in;
if (self->nic == MP_OBJ_NULL) {
// not connected
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF)));
}
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
int _errno;
mp_uint_t ret = self->nic_type->send(self, bufinfo.buf, bufinfo.len, &_errno);
if (ret == -1) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
mp_int_t ret = wlan_socket_send(self, bufinfo.buf, bufinfo.len, &_errno);
if (ret < 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
}
return mp_obj_new_int_from_uint(ret);
}
@@ -205,17 +262,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send);
// method socket.recv(bufsize)
STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
mod_network_socket_obj_t *self = self_in;
if (self->nic == MP_OBJ_NULL) {
// not connected
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN)));
}
mp_int_t len = mp_obj_get_int(len_in);
vstr_t vstr;
vstr_init_len(&vstr, len);
int _errno;
mp_uint_t ret = self->nic_type->recv(self, (byte*)vstr.buf, len, &_errno);
if (ret == -1) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
mp_int_t ret = wlan_socket_recv(self, (byte*)vstr.buf, len, &_errno);
if (ret < 0) {
if (_errno == EAGAIN && self->sock_base.has_timeout) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TimeoutError, "timed out"));
}
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
}
if (ret == 0) {
return mp_const_empty_bytes;
@@ -236,18 +292,14 @@ 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);
mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE);
// check if we need to select a NIC
socket_select_nic(self, ip);
// call the NIC to sendto
// call the nic to sendto
int _errno;
mp_int_t ret = self->nic_type->sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno);
if (ret == -1) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
mp_int_t ret = wlan_socket_sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno);
if (ret < 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
}
return mp_obj_new_int(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto);
@@ -255,18 +307,17 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(socket_sendto_obj, socket_sendto);
// method socket.recvfrom(bufsize)
STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
mod_network_socket_obj_t *self = self_in;
if (self->nic == MP_OBJ_NULL) {
// not connected
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN)));
}
vstr_t vstr;
vstr_init_len(&vstr, mp_obj_get_int(len_in));
byte ip[4];
mp_uint_t port;
int _errno;
mp_int_t ret = self->nic_type->recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno);
if (ret == -1) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
mp_int_t ret = wlan_socket_recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno);
if (ret < 0) {
if (_errno == EAGAIN && self->sock_base.has_timeout) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_TimeoutError, "timed out"));
}
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
}
mp_obj_t tuple[2];
if (ret == 0) {
@@ -276,7 +327,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 +343,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 {
@@ -303,10 +354,9 @@ STATIC mp_obj_t socket_setsockopt(mp_uint_t n_args, const mp_obj_t *args) {
}
int _errno;
if (self->nic_type->setsockopt(self, level, opt, optval, optlen, &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
if (wlan_socket_setsockopt(self, level, opt, optval, optlen, &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);
@@ -317,19 +367,15 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_s
// otherwise, timeout is in seconds
STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) {
mod_network_socket_obj_t *self = self_in;
if (self->nic == MP_OBJ_NULL) {
// not connected
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOTCONN)));
}
mp_uint_t timeout;
if (timeout_in == mp_const_none) {
timeout = -1;
} else {
timeout = 1000 * mp_obj_get_int(timeout_in);
timeout = mp_obj_get_int(timeout_in);
}
int _errno;
if (self->nic_type->settimeout(self, timeout, &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
if (wlan_socket_settimeout(self, timeout, &_errno) != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno)));
}
return mp_const_none;
}
@@ -346,29 +392,68 @@ STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) {
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
STATIC const mp_map_elem_t socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&socket_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&socket_bind_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&socket_listen_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&socket_accept_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&socket_connect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&socket_sendto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&socket_recvfrom_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&socket_setsockopt_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_settimeout), (mp_obj_t)&socket_settimeout_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_setblocking), (mp_obj_t)&socket_setblocking_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&socket_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&socket_bind_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&socket_listen_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&socket_accept_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&socket_connect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendall), (mp_obj_t)&socket_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&socket_sendto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&socket_recvfrom_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&socket_setsockopt_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_settimeout), (mp_obj_t)&socket_settimeout_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_setblocking), (mp_obj_t)&socket_setblocking_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_makefile), (mp_obj_t)&mp_identity_obj },
// stream methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
};
STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
STATIC mp_uint_t socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
mod_network_socket_obj_t *self = self_in;
return self->nic_type->ioctl(self, request, arg, errcode);
mp_int_t ret = wlan_socket_recv(self, buf, size, errcode);
if (ret < 0) {
// we need to ignore the socket closed error here because a readall() or read() without params
// only returns when the socket is closed by the other end
if (*errcode != SL_ESECCLOSED) {
ret = MP_STREAM_ERROR;
// needed to convert simplelink's negative error codes to POSIX
(*errcode) *= -1;
} else {
ret = 0;
}
}
return ret;
}
STATIC const mp_stream_p_t socket_stream_p = {
STATIC mp_uint_t socket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
mod_network_socket_obj_t *self = self_in;
mp_int_t ret = wlan_socket_send(self, buf, size, errcode);
if (ret < 0) {
ret = MP_STREAM_ERROR;
// needed to convert simplelink's negative error codes to POSIX
(*errcode) *= -1;
}
return ret;
}
STATIC mp_uint_t socket_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
mod_network_socket_obj_t *self = self_in;
return wlan_socket_ioctl(self, request, arg, errcode);
}
const mp_stream_p_t socket_stream_p = {
.read = socket_read,
.write = socket_write,
.ioctl = socket_ioctl,
.is_text = false,
};
@@ -391,28 +476,19 @@ STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
const char *host = mp_obj_str_get_data(host_in, &hlen);
mp_int_t port = mp_obj_get_int(port_in);
// find a NIC that can do a name lookup
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];
mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic);
if (nic_type->gethostbyname != NULL) {
// Only IPv4 is supported
uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
int32_t result = nic_type->gethostbyname(nic, host, hlen, out_ip, AF_INET);
if (result != 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(result)));
}
mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET);
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);
return mp_obj_new_list(1, (mp_obj_t*)&tuple);
}
// ipv4 only
uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
int32_t result = wlan_gethostbyname(host, hlen, out_ip, AF_INET);
if (result < 0) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-result)));
}
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET);
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] = netutils_format_inet_addr(out_ip, port, NETUTILS_LITTLE);
return mp_obj_new_list(1, (mp_obj_t*)&tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_usocket_getaddrinfo_obj, mod_usocket_getaddrinfo);
@@ -422,6 +498,10 @@ STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&socket_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&mod_usocket_getaddrinfo_obj },
// class exceptions
{ MP_OBJ_NEW_QSTR(MP_QSTR_error), (mp_obj_t)&mp_type_OSError },
{ MP_OBJ_NEW_QSTR(MP_QSTR_timeout), (mp_obj_t)&mp_type_TimeoutError },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(AF_INET) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET6), MP_OBJ_NEW_SMALL_INT(AF_INET6) },
@@ -430,6 +510,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

@@ -3,7 +3,7 @@
*
* 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
@@ -24,19 +24,16 @@
* THE SOFTWARE.
*/
typedef unsigned int size_t;
#ifndef MODUSOCKET_H_
#define MODUSOCKET_H_
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);
extern const mp_obj_dict_t socket_locals_dict;
extern const mp_stream_p_t socket_stream_p;
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);
extern void modusocket_pre_init (void);
extern void modusocket_socket_add (int16_t sd, bool user);
extern void modusocket_socket_delete (int16_t sd);
extern void modusocket_enter_sleep (void);
extern void modusocket_close_all_user_sockets (void);
int printf(const char *fmt, ...);
int snprintf(char *str, size_t size, const char *fmt, ...);
#endif /* MODUSOCKET_H_ */

149
cc3200/mods/modussl.c Normal file
View File

@@ -0,0 +1,149 @@
/*
* 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.
*/
#include <stdint.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 "modnetwork.h"
#include "modusocket.h"
#include "mpexception.h"
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
#define SSL_CERT_NONE (0)
#define SSL_CERT_OPTIONAL (1)
#define SSL_CERT_REQUIRED (2)
/******************************************************************************
DEFINE TYPES
******************************************************************************/
typedef struct _mp_obj_ssl_socket_t {
mp_obj_base_t base;
mod_network_socket_base_t sock_base;
mp_obj_t o_sock;
} mp_obj_ssl_socket_t;
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC const mp_obj_type_t ssl_socket_type;
/******************************************************************************/
// Micro Python bindings; SSL class
// ssl socket inherits from normal socket, so we take its
// locals and stream methods
STATIC const mp_obj_type_t ssl_socket_type = {
{ &mp_type_type },
.name = MP_QSTR_ussl,
.getiter = NULL,
.iternext = NULL,
.stream_p = &socket_stream_p,
.locals_dict = (mp_obj_t)&socket_locals_dict,
};
STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
STATIC const mp_arg_t allowed_args[] = {
{ MP_QSTR_sock, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_keyfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_certfile, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_false} },
{ MP_QSTR_cert_reqs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SSL_CERT_NONE} },
{ MP_QSTR_ca_certs, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
};
// parse arguments
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// chech if ca validation is required
if (args[4].u_int != SSL_CERT_NONE && args[5].u_obj == mp_const_none) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
// server side param is irrelevant for us (at least for the moment)
// retrieve the file paths (with an 6 byte offset because to strip the '/flash' prefix)
const char *keyfile = (args[1].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[1].u_obj)[6]);
const char *certfile = (args[2].u_obj == mp_const_none) ? NULL : &(mp_obj_str_get_str(args[2].u_obj)[6]);
const char *cafile = (args[5].u_obj == mp_const_none || args[4].u_int != SSL_CERT_REQUIRED) ?
NULL : &(mp_obj_str_get_str(args[5].u_obj)[6]);
_i16 sd = ((mod_network_socket_obj_t *)args[0].u_obj)->sock_base.sd;
_i16 _errno;
if (keyfile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_PRIVATE_KEY_FILE_NAME, keyfile, strlen(keyfile))) < 0) {
goto socket_error;
}
if (certfile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CERTIFICATE_FILE_NAME, certfile, strlen(certfile))) < 0) {
goto socket_error;
}
if (cafile && (_errno = sl_SetSockOpt(sd, SL_SOL_SOCKET, SL_SO_SECURE_FILES_CA_FILE_NAME, cafile, strlen(cafile))) < 0) {
goto socket_error;
}
// create the ssl socket
mp_obj_ssl_socket_t *ssl_sock = m_new_obj(mp_obj_ssl_socket_t);
// ssl socket inherits all properties from the original socket
memcpy (&ssl_sock->sock_base, &((mod_network_socket_obj_t *)args[0].u_obj)->sock_base, sizeof(mod_network_socket_base_t));
ssl_sock->base.type = &ssl_socket_type;
ssl_sock->sock_base.cert_req = (args[4].u_int == SSL_CERT_REQUIRED) ? true : false;
ssl_sock->o_sock = args[0].u_obj;
return ssl_sock;
socket_error:
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
STATIC const mp_map_elem_t mp_module_ussl_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ussl) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_wrap_socket), (mp_obj_t)&mod_ssl_wrap_socket_obj },
// class exceptions
{ MP_OBJ_NEW_QSTR(MP_QSTR_SSLError), (mp_obj_t)&mp_type_OSError },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_CERT_NONE), MP_OBJ_NEW_SMALL_INT(SSL_CERT_NONE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CERT_OPTIONAL), MP_OBJ_NEW_SMALL_INT(SSL_CERT_OPTIONAL) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CERT_REQUIRED), MP_OBJ_NEW_SMALL_INT(SSL_CERT_REQUIRED) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_ussl_globals, mp_module_ussl_globals_table);
const mp_obj_module_t mp_module_ussl = {
.base = { &mp_type_module },
.name = MP_QSTR_ussl,
.globals = (mp_obj_dict_t*)&mp_module_ussl_globals,
};

View File

@@ -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,30 +60,30 @@ 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),
mp_obj_new_int(tm.tm_mon),
mp_obj_new_int(tm.tm_mday),
mp_obj_new_int(tm.tm_wday),
mp_obj_new_int(tm.tm_hour),
mp_obj_new_int(tm.tm_min),
mp_obj_new_int(tm.tm_sec),
mp_obj_new_int(mseconds)
mp_obj_new_int(tm.tm_wday),
mp_obj_new_int(tm.tm_yday)
};
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),
@@ -220,7 +105,6 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
/// 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;
@@ -231,72 +115,20 @@ 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]);
// 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));
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(milliseconds)
/// Sleep for the given number of milliseconds.
STATIC mp_obj_t time_sleep(mp_obj_t milliseconds_o) {
HAL_Delay(mp_obj_get_int(milliseconds_o));
/// \function sleep(seconds)
/// Sleep for the given number of seconds.
STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
int32_t sleep_s = mp_obj_get_int(seconds_o);
if (sleep_s > 0) {
HAL_Delay(sleep_s * 1000);
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep);
@@ -304,12 +136,7 @@ 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) {
uint32_t seconds;
uint16_t mseconds;
// get the seconds and the milliseconds from the RTC
MAP_PRCMRTCGet(&seconds, &mseconds);
return mp_obj_new_int(seconds);
return mp_obj_new_int(pybrtc_get_seconds());
}
MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time);

File diff suppressed because it is too large Load Diff

View File

@@ -43,7 +43,7 @@ typedef enum {
MODWLAN_ERROR_INVALID_PARAMS = -1,
MODWLAN_ERROR_TIMEOUT = -2,
MODWLAN_ERROR_UNKNOWN = -3,
}modwlan_Status_t;
} modwlan_Status_t;
/******************************************************************************
DECLARE PUBLIC DATA
@@ -53,13 +53,31 @@ extern _SlLockObj_t wlan_LockObj;
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
******************************************************************************/
extern void wlan_init0 (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_pre_init (void);
extern void wlan_sl_enable (int8_t mode, const char *ssid, uint8_t ssid_len, uint8_t sec,
const char *key, uint8_t key_len, uint8_t channel, bool append_mac);
extern void wlan_first_start (void);
extern void wlan_update(void);
extern void wlan_stop (uint32_t timeout);
extern void wlan_start (void);
extern void wlan_get_mac (uint8_t *macAddress);
extern void wlan_get_ip (uint32_t *ip);
extern bool wlan_is_connected (void);
extern void wlan_set_current_time (uint32_t seconds_since_2000);
extern int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family);
extern int wlan_socket_socket(mod_network_socket_obj_t *s, int *_errno);
extern void wlan_socket_close(mod_network_socket_obj_t *s);
extern int wlan_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno);
extern int wlan_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno);
extern int wlan_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno);
extern int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno);
extern int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno);
extern int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno);
extern int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno);
extern int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno);
extern int wlan_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno);
extern int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int *_errno);
extern int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno);
#endif /* MODWLAN_H_ */

View File

@@ -57,10 +57,8 @@
///
/// Usage:
///
/// adc = pyb.ADC(channel) # create an adc object on the given channel (0 to 3)
/// this automatically configures the pin associated to
/// that analog channel.
/// adc.read() # read channel value
/// adc = pyb.ADC('GP5') # create an adc object on the given pin (GP2, GP3, GP4 o GP5)
/// adc.read() # read channel value
///
/// The sample rate is fixed to 62.5KHz and the resolution to 12 bits.
@@ -75,14 +73,23 @@
******************************************************************************/
typedef struct {
mp_obj_base_t base;
pin_obj_t *pin;
byte channel;
byte num;
byte id;
} pyb_adc_obj_t;
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC pyb_adc_obj_t pyb_adc_obj[PYB_ADC_NUM_CHANNELS] = { {.pin = &pin_GP2, .channel = ADC_CH_0, .id = 1}, {.pin = &pin_GP3, .channel = ADC_CH_1, .id = 2},
{.pin = &pin_GP4, .channel = ADC_CH_2, .id = 2}, {.pin = &pin_GP5, .channel = ADC_CH_3, .id = 4} };
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
STATIC void pybadc_init (pyb_adc_obj_t *self) {
// configure the pin in analog mode
pin_config (self->pin, PIN_MODE_0, GPIO_DIR_MODE_IN, PYBPIN_ANALOG_TYPE, PIN_STRENGTH_2MA);
// enable the ADC channel
MAP_ADCChannelEnable(ADC_BASE, self->channel);
// enable and configure the timer
@@ -92,68 +99,34 @@ STATIC void pybadc_init (pyb_adc_obj_t *self) {
MAP_ADCEnable(ADC_BASE);
}
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
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, "<ADC1 channel=%u on %q>", self->id, self->pin->name);
}
/// \classmethod \constructor(channel)
/// Create an ADC object associated with the given channel.
/// \classmethod \constructor(pin)
/// Create an ADC object associated with the given pin.
/// This allows you to then read analog values on that pin.
STATIC mp_obj_t adc_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
// check number of arguments
mp_arg_check_num(n_args, n_kw, 1, 1, false);
// the first argument is the channel number
uint num = mp_obj_get_int(args[0]);
const pin_obj_t *pin;
uint channel;
switch (num) {
case 0:
channel = ADC_CH_0;
pin = &pin_GPIO2;
break;
case 1:
channel = ADC_CH_1;
pin = &pin_GPIO3;
break;
case 2:
channel = ADC_CH_2;
pin = &pin_GPIO4;
break;
case 3:
channel = ADC_CH_3;
pin = &pin_GPIO5;
break;
default:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
break;
// the argument passed is the pin
const pin_obj_t *pin = (pin_obj_t *)pin_find(args[0]);
for (int32_t idx = 0; idx < PYB_ADC_NUM_CHANNELS; idx++) {
if (pin == pyb_adc_obj[idx].pin) {
pyb_adc_obj_t *self = &pyb_adc_obj[idx];
self->base.type = &pyb_adc_type;
pybadc_init (self);
// register it with the sleep module
pybsleep_add ((const mp_obj_t)self, (WakeUpCB_t)pybadc_init);
return self;
}
}
// disable the callback before re-configuring
pyb_adc_obj_t *self = &pyb_adc_obj[channel];
self->base.type = &pyb_adc_type;
self->channel = channel;
self->num = num;
// configure the pin in analog mode
pin_config ((pin_obj_t *)pin, PIN_MODE_0, GPIO_DIR_MODE_IN, PYBPIN_ANALOG_TYPE, PIN_STRENGTH_2MA);
// initialize it
pybadc_init (self);
// register it with the sleep module
pybsleep_add ((const mp_obj_t)self, (WakeUpCB_t)pybadc_init);
return self;
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
/// \method read()
@@ -172,19 +145,19 @@ STATIC mp_obj_t adc_read(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_read_obj, adc_read);
/// \method enable()
/// \method init()
/// Enable the adc channel
STATIC mp_obj_t adc_enable(mp_obj_t self_in) {
STATIC mp_obj_t adc_init(mp_obj_t self_in) {
pyb_adc_obj_t *self = self_in;
pybadc_init(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_enable_obj, adc_enable);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_init_obj, adc_init);
/// \method disable()
/// \method deinit()
/// Disable the adc channel
STATIC mp_obj_t adc_disable(mp_obj_t self_in) {
STATIC mp_obj_t adc_deinit(mp_obj_t self_in) {
pyb_adc_obj_t *self = self_in;
MAP_ADCChannelDisable(ADC_BASE, self->channel);
@@ -192,12 +165,12 @@ STATIC mp_obj_t adc_disable(mp_obj_t self_in) {
pybsleep_remove ((const mp_obj_t)self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_disable_obj, adc_disable);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_deinit_obj, adc_deinit);
STATIC const mp_map_elem_t adc_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&adc_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&adc_enable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&adc_disable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&adc_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&adc_deinit_obj },
};
STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table);

View File

@@ -56,10 +56,10 @@
///
/// from pyb import I2C
///
/// i2c = I2C() # create
/// i2c = I2C(50000) # create and init with a 50KHz baudrate
/// i2c.init(100000) # init with a 100KHz baudrate
/// i2c.deinit() # turn off the peripheral
/// i2c = I2C(1) # create
/// i2c = I2C(1, I2C.MASTER, baudrate=50000) # create and init with a 50KHz baudrate
/// i2c.init(I2C.MASTER, baudrate=100000) # init with a 100KHz baudrate
/// i2c.deinit() # turn off the peripheral
///
/// Printing the i2c object gives you information about its configuration.
///
@@ -76,7 +76,6 @@
///
/// A master must specify the recipient's address:
///
/// i2c.init(100000)
/// i2c.send('123', 0x42) # send 3 bytes to slave with address 0x42
/// i2c.send(b'456', addr=0x42) # keyword for address
///
@@ -98,6 +97,8 @@ typedef struct _pyb_i2c_obj_t {
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
#define PYBI2C_MASTER (0)
#define PYBI2C_MIN_BAUD_RATE_HZ (50000)
#define PYBI2C_MAX_BAUD_RATE_HZ (400000)
@@ -251,16 +252,40 @@ STATIC bool pyb_i2c_scan_device(byte devAddr) {
/******************************************************************************/
/* Micro Python bindings */
/******************************************************************************/
/// \method init(100000)
///
/// Initialise the I2C bus as a master with the given baudrate.
///
STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self_in, mp_obj_t baudrate) {
STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_i2c_obj_t *self = self_in;
if (self->baudrate > 0) {
mp_printf(print, "<I2C1, I2C.MASTER, baudrate=%u>)", self->baudrate);
}
else {
mp_print_str(print, "<I2C1>");
}
}
/// \method init(mode, *, baudrate=100000)
///
/// Initialise the I2C bus with the given parameters:
///
/// - `mode` must be either `I2C.MASTER` or `I2C.SLAVE`
/// - `baudrate` is the SCL clock rate (only sensible for a master)
STATIC const mp_arg_t pyb_i2c_init_args[] = {
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} },
};
#define PYB_I2C_INIT_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_init_args)
STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t vals[PYB_I2C_INIT_NUM_ARGS];
mp_arg_parse_all(n_args, args, kw_args, PYB_I2C_INIT_NUM_ARGS, pyb_i2c_init_args, vals);
// verify that mode is master
if (vals[0].u_int != PYBI2C_MASTER) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
// make sure the baudrate is between the valid range
self->baudrate = MIN(MAX(mp_obj_get_int(baudrate), PYBI2C_MIN_BAUD_RATE_HZ), PYBI2C_MAX_BAUD_RATE_HZ);
self->baudrate = MIN(MAX(vals[1].u_int, PYBI2C_MIN_BAUD_RATE_HZ), PYBI2C_MAX_BAUD_RATE_HZ);
// init the I2C bus
i2c_init(self);
@@ -273,7 +298,7 @@ STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self_in, mp_obj_t baudrate) {
/// \classmethod \constructor(bus, ...)
///
/// Construct an I2C object on the given bus. `bus` can only be 0.
/// Construct an I2C object on the given bus. `bus` can only be 1.
/// With no additional parameters, the I2C object is created but not
/// initialised (it has the settings from the last initialisation of
/// the bus, if any). If extra arguments are given, the bus is initialised.
@@ -286,28 +311,20 @@ STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n
pyb_i2c_obj_t *self = &pyb_i2c_obj;
self->base.type = &pyb_i2c_type;
if (n_args > 0) {
if (n_args > 1 || n_kw > 0) {
// start the peripheral
pyb_i2c_init_helper(self, *args);
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
pyb_i2c_init_helper(self, n_args - 1, args + 1, &kw_args);
}
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) {
pyb_i2c_obj_t *self = self_in;
if (self->baudrate > 0) {
print(env, "<I2C0, I2C.MASTER, baudrate=%u>)", self->baudrate);
}
else {
print(env, "<I2C0>");
}
STATIC mp_obj_t pyb_i2c_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
return pyb_i2c_init_helper(args[0], n_args - 1, args + 1, kw_args);
}
STATIC mp_obj_t pyb_i2c_init(mp_obj_t self_in, mp_obj_t baudrate) {
return pyb_i2c_init_helper(self_in, baudrate);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_init_obj, pyb_i2c_init);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_init_obj, 1, pyb_i2c_init);
/// \method deinit()
/// Turn off the I2C bus.
@@ -361,8 +378,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_scan_obj, pyb_i2c_scan);
/// - `addr` is the address to send to (only required in master mode)
/// Return value: `None`.
STATIC const mp_arg_t pyb_i2c_send_args[] = {
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_addr, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
#define PYB_I2C_SEND_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_send_args)
@@ -396,8 +414,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_send_obj, 1, pyb_i2c_send);
/// Return value: if `recv` is an integer then a new buffer of the bytes received,
/// otherwise the same buffer that was passed in to `recv`.
STATIC const mp_arg_t pyb_i2c_recv_args[] = {
{ MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_addr, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
#define PYB_I2C_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_recv_args)
@@ -437,9 +456,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_recv_obj, 1, pyb_i2c_recv);
/// Returns the read data.
/// This is only valid in master mode.
STATIC const mp_arg_t pyb_i2c_mem_read_args[] = {
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
{ MP_QSTR_addr_size, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
};
#define PYB_I2C_MEM_READ_NUM_ARGS MP_ARRAY_SIZE(pyb_i2c_mem_read_args)
@@ -529,6 +549,10 @@ STATIC const mp_map_elem_t pyb_i2c_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_i2c_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_read), (mp_obj_t)&pyb_i2c_mem_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_write), (mp_obj_t)&pyb_i2c_mem_write_obj },
// class constants
/// \constant MASTER - for initialising the bus to master mode
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(PYBI2C_MASTER) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);

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,10 +69,10 @@
/// Example callback:
///
/// def pincb(pin):
/// print(pin.pin())
/// print(pin.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)
/// extint.callback (mode=pyb.Pin.INT_RISING, handler=pincb)
/// # the callback can be triggered manually
/// extint.callback()()
/// # to disable the callback
@@ -114,15 +92,17 @@
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC void pin_obj_configure (const pin_obj_t *self);
STATIC void pin_get_hibernate_pin_and_idx (const pin_obj_t *self, uint *wake_pin, uint *idx);
STATIC void pin_extint_enable (mp_obj_t self_in);
STATIC void pin_extint_disable (mp_obj_t self_in);
STATIC void pin_verify_af (uint af);
STATIC void pin_extint_register(pin_obj_t *self, uint32_t intmode, uint32_t priority);
STATIC void GPIOA0IntHandler (void);
STATIC void GPIOA1IntHandler (void);
STATIC void GPIOA2IntHandler (void);
STATIC void GPIOA3IntHandler (void);
STATIC void EXTI_Handler(uint port);
STATIC void pin_obj_configure (const pin_obj_t *self);
STATIC void pin_get_hibernate_pin_and_idx (const pin_obj_t *self, uint *wake_pin, uint *idx);
STATIC void pin_extint_enable (mp_obj_t self_in);
STATIC void pin_extint_disable (mp_obj_t self_in);
/******************************************************************************
DEFINE CONSTANTS
@@ -155,48 +135,32 @@ STATIC pybpin_wake_pin_t pybpin_wake_pin[PYBPIN_NUM_WAKE_PINS] =
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
void pin_init0(void) {
// assign GPIO10 and GPIO11 to the GPIO peripheral (the default is I2C), so that the I2C bus can
// assign GP10 and GP11 to the GPIO peripheral (the default is I2C), so that the I2C bus can
// be assigned safely to any other pins (as recomended by the SDK release notes). Make them
// inputs with pull-downs enabled to ensure they are not floating during LDPS and hibernate.
pin_config ((pin_obj_t *)&pin_GPIO10, PIN_MODE_0, GPIO_DIR_MODE_IN, PIN_TYPE_STD_PD, PIN_STRENGTH_2MA);
pin_config ((pin_obj_t *)&pin_GPIO11, PIN_MODE_0, GPIO_DIR_MODE_IN, PIN_TYPE_STD_PD, PIN_STRENGTH_2MA);
pin_config ((pin_obj_t *)&pin_GP10, PIN_MODE_0, GPIO_DIR_MODE_IN, PIN_TYPE_STD_PD, PIN_STRENGTH_2MA);
pin_config ((pin_obj_t *)&pin_GP11, PIN_MODE_0, GPIO_DIR_MODE_IN, PIN_TYPE_STD_PD, PIN_STRENGTH_2MA);
}
// C API used to convert a user-supplied pin name into an ordinal pin number.
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));
}
void pin_verify_af (uint af) {
if (af > PIN_MODE_15) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
}
void pin_config (pin_obj_t *self, uint af, uint mode, uint type, uint strength) {
// configure the pin in analog mode
self->af = af, self->mode = mode, self->type = type, self->strength = strength;
@@ -207,37 +171,6 @@ void pin_config (pin_obj_t *self, uint af, uint mode, uint type, uint strength)
pybsleep_add ((const mp_obj_t)self, (WakeUpCB_t)pin_obj_configure);
}
void pin_extint_register(pin_obj_t *self, uint32_t intmode, uint32_t priority) {
void *handler;
uint32_t intnum;
// configure the interrupt type
MAP_GPIOIntTypeSet(self->port, self->bit, intmode);
switch (self->port) {
case GPIOA0_BASE:
handler = GPIOA0IntHandler;
intnum = INT_GPIOA0;
break;
case GPIOA1_BASE:
handler = GPIOA1IntHandler;
intnum = INT_GPIOA1;
break;
case GPIOA2_BASE:
handler = GPIOA2IntHandler;
intnum = INT_GPIOA2;
break;
case GPIOA3_BASE:
default:
handler = GPIOA3IntHandler;
intnum = INT_GPIOA3;
break;
}
MAP_GPIOIntRegister(self->port, handler);
// set the interrupt to the lowest priority, to make sure that
// no other ISRs will be preemted by this one
MAP_IntPrioritySet(intnum, priority);
}
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
@@ -277,27 +210,27 @@ STATIC void pin_obj_configure (const pin_obj_t *self) {
STATIC void pin_get_hibernate_pin_and_idx (const pin_obj_t *self, uint *hib_pin, uint *idx) {
// pin_num is actually : (package_pin - 1)
switch (self->pin_num) {
case 56: // GPIO2
case 56: // GP2
*hib_pin = PRCM_HIB_GPIO2;
*idx = 0;
break;
case 58: // GPIO4
case 58: // GP4
*hib_pin = PRCM_HIB_GPIO4;
*idx = 1;
break;
case 3: // GPIO13
case 3: // GP13
*hib_pin = PRCM_HIB_GPIO13;
*idx = 2;
break;
case 7: // GPIO17
case 7: // GP17
*hib_pin = PRCM_HIB_GPIO17;
*idx = 3;
break;
case 1: // GPIO11
case 1: // GP11
*hib_pin = PRCM_HIB_GPIO11;
*idx = 4;
break;
case 16: // GPIO24
case 16: // GP24
*hib_pin = PRCM_HIB_GPIO24;
*idx = 5;
break;
@@ -358,6 +291,77 @@ STATIC void pin_extint_disable (mp_obj_t self_in) {
MAP_GPIOIntDisable(self->port, self->bit);
}
STATIC void pin_verify_af (uint af) {
if (af > PIN_MODE_15) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
}
STATIC void pin_extint_register(pin_obj_t *self, uint32_t intmode, uint32_t priority) {
void *handler;
uint32_t intnum;
// configure the interrupt type
MAP_GPIOIntTypeSet(self->port, self->bit, intmode);
switch (self->port) {
case GPIOA0_BASE:
handler = GPIOA0IntHandler;
intnum = INT_GPIOA0;
break;
case GPIOA1_BASE:
handler = GPIOA1IntHandler;
intnum = INT_GPIOA1;
break;
case GPIOA2_BASE:
handler = GPIOA2IntHandler;
intnum = INT_GPIOA2;
break;
case GPIOA3_BASE:
default:
handler = GPIOA3IntHandler;
intnum = INT_GPIOA3;
break;
}
MAP_GPIOIntRegister(self->port, handler);
// set the interrupt to the lowest priority, to make sure that
// no other ISRs will be preemted by this one
MAP_IntPrioritySet(intnum, priority);
}
STATIC void GPIOA0IntHandler (void) {
EXTI_Handler(GPIOA0_BASE);
}
STATIC void GPIOA1IntHandler (void) {
EXTI_Handler(GPIOA1_BASE);
}
STATIC void GPIOA2IntHandler (void) {
EXTI_Handler(GPIOA2_BASE);
}
STATIC void GPIOA3IntHandler (void) {
EXTI_Handler(GPIOA3_BASE);
}
// common interrupt handler
STATIC void EXTI_Handler(uint port) {
uint32_t bits = MAP_GPIOIntStatus(port, true);
MAP_GPIOIntClear(port, bits);
// might be that we have more than one Pin interrupt pending
// therefore we must loop through all of the 8 possible bits
for (int i = 0; i < 8; i++) {
uint32_t bit = (1 << i);
if (bit & bits) {
pin_obj_t *self = (pin_obj_t *)pin_find_pin_by_port_bit(&pin_cpu_pins_locals_dict, port, bit);
mp_obj_t _callback = mpcallback_find(self);
mpcallback_handler(_callback);
}
}
}
/******************************************************************************/
// Micro Python bindings
@@ -365,7 +369,7 @@ STATIC void pin_extint_disable (mp_obj_t self_in) {
/// Initialise the pin:
///
/// - `af` can be in range 0-15, please check the CC3200 datasheet
/// for the details on the AFs availables on each pin (af=0, keeps it as a gpio pin).
/// for the details on the AFs availables on each pin (af=0 keeps it as a gpio pin).
/// - `mode` can be one of:
/// - `Pin.IN` - configure the pin for input;
/// - `Pin.OUT` - configure the pin for output;
@@ -376,7 +380,6 @@ STATIC void pin_extint_disable (mp_obj_t self_in) {
/// - `Pin.OD` - standard without pull up or pull down;
/// - `Pin.OD_PU` - open drain with pull-up resistor;
/// - `Pin.OD_PD` - open drain with pull-down resistor.
/// - `Pin.ANALOG` - configured in analog (adc) mode
/// - `strength` can be one of:
/// - `Pin.S2MA` - 2ma drive strength;
/// - `Pin.S4MA` - 4ma drive strength;
@@ -387,7 +390,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)
@@ -399,55 +402,59 @@ STATIC mp_obj_t pin_obj_init_helper(pin_obj_t *self, mp_uint_t n_args, const mp_
// get the af
uint af = args[0].u_int;
if (af < PIN_MODE_0 || af > PIN_MODE_15) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
goto invalid_args;
}
// get the io mode
uint mode = args[1].u_int;
// checking the mode only makes sense if af == GPIO
if (af == PIN_MODE_0) {
if (mode != GPIO_DIR_MODE_IN && mode != GPIO_DIR_MODE_OUT) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
goto invalid_args;
}
}
// get the type
uint type = args[2].u_int;
if (type != PIN_TYPE_STD && type != PIN_TYPE_STD_PU && type != PIN_TYPE_STD_PD &&
type != PIN_TYPE_OD && type != PIN_TYPE_OD_PU && type != PIN_TYPE_OD_PD) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
goto invalid_args;
}
// get the strenght
uint strength = args[3].u_int;
if (strength != PIN_STRENGTH_2MA && strength != PIN_STRENGTH_4MA && strength != PIN_STRENGTH_6MA) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
goto invalid_args;
}
// configure the pin as requested
pin_config (self, af, mode, type, strength);
return mp_const_none;
invalid_args:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
/// \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 +472,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 +483,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, ...)
@@ -555,68 +562,36 @@ 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.
/// Returns the qstr name of the pin
STATIC mp_obj_t pin_name(mp_obj_t self_in) {
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);
/// \method port()
/// Get the pin port.
STATIC mp_obj_t pin_port(mp_obj_t self_in) {
/// \method info()
/// Returns a named tupple with the current configuration of the gpio pin
STATIC mp_obj_t pin_info(mp_obj_t self_in) {
STATIC const qstr pin_info_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_int(self->port);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_port_obj, pin_port);
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 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);
return mp_obj_new_attrtuple(pin_info_fields, 5, pin_config);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_pin_obj, pin_pin);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_info_obj, pin_info);
/// \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);
/// \method callback(method, intmode, priority, pwrmode)
/// \method callback(method, mode, priority, pwrmode)
/// Creates a callback object associated to a pin
/// min num of arguments is 1 (intmode)
/// min num of arguments is 1 (mode)
STATIC mp_obj_t pin_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_arg_val_t args[mpcallback_INIT_NUM_ARGS];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mpcallback_INIT_NUM_ARGS, mpcallback_init_args, args);
@@ -631,7 +606,7 @@ STATIC mp_obj_t pin_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map
uint intmode = args[0].u_int;
if (intmode != GPIO_FALLING_EDGE && intmode != GPIO_RISING_EDGE && intmode != GPIO_BOTH_EDGES &&
intmode != GPIO_LOW_LEVEL && intmode != GPIO_HIGH_LEVEL) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
goto invalid_args;
}
uint pwrmode = args[4].u_int;
@@ -751,12 +726,7 @@ STATIC const mp_map_elem_t pin_locals_dict_table[] = {
{ 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_info), (mp_obj_t)&pin_info_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pin_callback_obj },
// class attributes
@@ -792,7 +762,6 @@ STATIC const mp_map_elem_t pin_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_INT_RISING_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_BOTH_EDGES) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_INT_LOW_LEVEL), MP_OBJ_NEW_SMALL_INT(GPIO_LOW_LEVEL) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_INT_HIGH_LEVEL), MP_OBJ_NEW_SMALL_INT(GPIO_HIGH_LEVEL) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_S2MA), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_2MA) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_S4MA), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_4MA) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_S6MA), MP_OBJ_NEW_SMALL_INT(PIN_STRENGTH_6MA) },
@@ -814,29 +783,3 @@ STATIC const mp_cb_methods_t pin_cb_methods = {
.disable = pin_extint_disable,
};
STATIC void GPIOA0IntHandler (void) {
EXTI_Handler(GPIOA0_BASE);
}
STATIC void GPIOA1IntHandler (void) {
EXTI_Handler(GPIOA1_BASE);
}
STATIC void GPIOA2IntHandler (void) {
EXTI_Handler(GPIOA2_BASE);
}
STATIC void GPIOA3IntHandler (void) {
EXTI_Handler(GPIOA3_BASE);
}
// common interrupt handler
STATIC void EXTI_Handler(uint port) {
uint32_t bit = MAP_GPIOIntStatus(port, true);
MAP_GPIOIntClear(port, bit);
pin_obj_t *self = (pin_obj_t *)pin_find_pin_by_port_bit(&pin_cpu_pins_locals_dict, port, bit);
mp_obj_t _callback = mpcallback_find(self);
mpcallback_handler(_callback);
}

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;
@@ -62,14 +67,9 @@ extern const mp_obj_type_t pin_cpu_pins_obj_type;
extern const mp_obj_dict_t pin_cpu_pins_locals_dict;
void pin_init0(void);
void pin_verify_af (uint af);
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

@@ -25,13 +25,12 @@
* THE SOFTWARE.
*/
#include <stdio.h>
#include <std.h>
#include "py/mpconfig.h"
#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,10 @@
#include "pybrtc.h"
#include "pybsleep.h"
#include "mpcallback.h"
#include "timeutils.h"
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
/// \moduleref pyb
/// \class RTC - real time clock
@@ -71,6 +74,7 @@ typedef struct {
******************************************************************************/
STATIC pybrtc_data_t pybrtc_data;
STATIC const mp_cb_methods_t pybrtc_cb_methods;
STATIC const mp_obj_base_t pyb_rtc_obj = {&pyb_rtc_type};
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
@@ -82,7 +86,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();
@@ -92,6 +96,26 @@ void pybrtc_init(void) {
}
}
uint32_t pybrtc_get_seconds (void) {
uint32_t seconds;
uint16_t mseconds;
MAP_PRCMRTCGet(&seconds, &mseconds);
return seconds;
}
void pyb_rtc_callback_disable (mp_obj_t self_in) {
// check the wake from param
if (pybrtc_data.prwmode & PYB_PWR_MODE_ACTIVE) {
// disable the slow clock interrupt
MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
}
// 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();
}
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
@@ -108,19 +132,19 @@ STATIC void pyb_rtc_callback_enable (mp_obj_t self_in) {
pybsleep_configure_timer_wakeup (pybrtc_data.prwmode);
}
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
MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
}
// disable wake from ldps and hibernate
pybsleep_configure_timer_wakeup (PYB_PWR_MODE_ACTIVE);
}
/******************************************************************************/
// Micro Python bindings
/// \classmethod \constructor()
/// Create an RTC object.
STATIC mp_obj_t pyb_rtc_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 0, 0, false);
// return constant object
return (mp_obj_t)&pyb_rtc_obj;
}
/// \method datetime([datetimetuple])
/// Get or set the date and time of the RTC.
///
@@ -135,7 +159,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 +167,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),
@@ -164,16 +188,18 @@ mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
tm.tm_year = mp_obj_get_int(items[0]);
tm.tm_mon = mp_obj_get_int(items[1]);
tm.tm_mday = mp_obj_get_int(items[2]);
// Skip the weekday
// skip the weekday
tm.tm_hour = mp_obj_get_int(items[4]);
tm.tm_min = mp_obj_get_int(items[5]);
tm.tm_sec = mp_obj_get_int(items[6]);
mseconds = mp_obj_get_int(items[7]);
seconds = 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);
// set WLAN time and date, this is needed to verify certificates
wlan_set_current_time(seconds);
return mp_const_none;
}
}
@@ -190,7 +216,7 @@ STATIC mp_obj_t pyb_rtc_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp
// check if any parameters were passed
mp_obj_t _callback = mpcallback_find((mp_obj_t)&pyb_rtc_obj);
if (kw_args->used > 0 || !_callback) {
uint32_t f_mseconds = args[3].u_int;
uint32_t f_mseconds = MAX(1, args[3].u_int);
uint32_t seconds;
uint16_t mseconds;
// get the seconds and the milliseconds from the RTC
@@ -208,7 +234,7 @@ STATIC mp_obj_t pyb_rtc_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp
// set the match value
MAP_PRCMRTCMatchSet(seconds, mseconds);
// save the match data for later
// save the power mode data for later
pybrtc_data.prwmode = args[4].u_int;
// create the callback
@@ -217,7 +243,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)
@@ -233,9 +259,10 @@ STATIC const mp_map_elem_t pyb_rtc_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
STATIC const mp_obj_type_t pyb_rtc_type = {
const mp_obj_type_t pyb_rtc_type = {
{ &mp_type_type },
.name = MP_QSTR_RTC,
.make_new = pyb_rtc_make_new,
.locals_dict = (mp_obj_t)&pyb_rtc_locals_dict,
};
@@ -244,5 +271,3 @@ STATIC const mp_cb_methods_t pybrtc_cb_methods = {
.enable = pyb_rtc_callback_enable,
.disable = pyb_rtc_callback_disable,
};
const mp_obj_base_t pyb_rtc_obj = {&pyb_rtc_type};

View File

@@ -31,8 +31,10 @@
#define RTC_U16MS_CYCLES(msec) ((msec * 1024) / 1000)
#define RTC_CYCLES_U16MS(cycles) ((cycles * 1000) / 1024)
extern const mp_obj_base_t pyb_rtc_obj;
extern const mp_obj_type_t pyb_rtc_type;
void pybrtc_init(void);
extern void pybrtc_init(void);
extern void pyb_rtc_callback_disable (mp_obj_t self_in);
extern uint32_t pybrtc_get_seconds (void);
#endif // PYBRTC_H_

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>
@@ -46,6 +45,7 @@
#include "pybsleep.h"
#include "pybpin.h"
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
#include "osi.h"
#include "debug.h"
@@ -53,6 +53,8 @@
#include "mpcallback.h"
#include "mperror.h"
#include "sleeprestore.h"
#include "serverstask.h"
#include "antenna.h"
/******************************************************************************
DECLARE PRIVATE CONSTANTS
@@ -124,6 +126,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_wake_reason_t pybsleep_wake_reason = PYB_SLP_WAKED_PWRON;
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
@@ -134,7 +137,7 @@ STATIC NORETURN void pybsleep_suspend_enter (void);
void pybsleep_suspend_exit (void);
STATIC void pybsleep_obj_wakeup (void);
STATIC void PRCMInterruptHandler (void);
STATIC void pybsleep_iopark (void);
STATIC void pybsleep_iopark (bool hibernate);
STATIC bool setup_timer_lpds_wake (void);
STATIC bool setup_timer_hibernate_wake (void);
@@ -175,11 +178,22 @@ void pybsleep_init0 (void) {
pybsleep_reset_cause = PYB_SLP_WDT_RESET;
break;
case PRCM_HIB_EXIT:
if (PRCMWasResetBecauseOfWDT()) {
if (PRCMGetSpecialBit(PRCM_WDT_RESET_BIT)) {
pybsleep_reset_cause = PYB_SLP_WDT_RESET;
}
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:
@@ -326,7 +340,7 @@ STATIC NORETURN void pybsleep_suspend_enter (void) {
mperror_heartbeat_switch_off();
// park the gpio pins
pybsleep_iopark();
pybsleep_iopark(false);
// store the cpu registers
sleep_store();
@@ -384,6 +398,11 @@ void pybsleep_suspend_exit (void) {
// ungate the clock to the shared spi bus
MAP_PRCMPeripheralClkEnable(PRCM_SSPI, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
#if MICROPY_HW_ANTENNA_DIVERSITY
// re-configure the antenna selection pins
antenna_init0();
#endif
// reinitialize simplelink's interface
sl_IfOpen (NULL, 0);
@@ -411,15 +430,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
// disable the timer as 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;
@@ -434,31 +456,29 @@ STATIC void pybsleep_obj_wakeup (void) {
}
}
STATIC void pybsleep_iopark (void) {
STATIC void pybsleep_iopark (bool hibernate) {
mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)&pin_cpu_pins_locals_dict);
for (uint i = 0; i < named_map->used; i++) {
pin_obj_t * pin = (pin_obj_t *)named_map->table[i].value;
// skip the sflash pins since these are shared with the network processor
switch (pin->pin_num) {
case PIN_11:
case PIN_12:
case PIN_13:
case PIN_14:
#ifdef DEBUG
// also skip the JTAG pins
// skip the JTAG pins
case PIN_16:
case PIN_17:
case PIN_19:
case PIN_20:
#endif
break;
#endif
default:
// enable a weak pull-down if the pin is unused
if (!pin->isused) {
MAP_PinConfigSet(pin->pin_num, pin->strength, PIN_TYPE_STD_PD);
}
// make it an input
MAP_PinDirModeSet(pin->pin_num, PIN_DIR_MODE_IN);
if (hibernate) {
// make it an input
MAP_PinDirModeSet(pin->pin_num, PIN_DIR_MODE_IN);
}
break;
}
}
@@ -473,9 +493,25 @@ STATIC void pybsleep_iopark (void) {
HWREG(0x4402E0F4) &= ~(0x3 << 8);
HWREG(0x4402E0F4) |= (0x1 << 8);
// park the antenna selection pins
HWREG(0x4402E108) = 0x00000E61;
HWREG(0x4402E10C) = 0x00000E61;
// if the board has antenna diversity, only park the antenna
// selection pins when going into hibernation
#if MICROPY_HW_ANTENNA_DIVERSITY
if (hibernate) {
#endif
// park the antenna selection pins
// (tri-stated with pull down enabled)
HWREG(0x4402E108) = 0x00000E61;
HWREG(0x4402E10C) = 0x00000E61;
#if MICROPY_HW_ANTENNA_DIVERSITY
} else {
// park the antenna selection pins
// (tri-stated without changing the pull up/down resistors)
HWREG(0x4402E108) &= ~0x000000FF;
HWREG(0x4402E108) |= 0x00000C61;
HWREG(0x4402E10C) &= ~0x000000FF;
HWREG(0x4402E10C) |= 0x00000C61;
}
#endif
}
STATIC bool setup_timer_lpds_wake (void) {
@@ -579,6 +615,7 @@ STATIC mp_obj_t pyb_sleep_suspend (mp_obj_t self_in) {
// do we need network wake-up?
if (pybsleep_data.wlan_lpds_wake_cb) {
MAP_PRCMLPDSWakeupSourceEnable (PRCM_LPDS_HOST_IRQ);
server_sleep_sockets();
}
else {
MAP_PRCMLPDSWakeupSourceDisable (PRCM_LPDS_HOST_IRQ);
@@ -615,7 +652,7 @@ STATIC mp_obj_t pyb_sleep_hibernate (mp_obj_t self_in) {
wlan_stop(SL_STOP_TIMEOUT);
pybsleep_flash_powerdown();
// must be done just before entering hibernate mode
pybsleep_iopark();
pybsleep_iopark(true);
MAP_PRCMHibernateEnter();
return mp_const_none;
}
@@ -631,7 +668,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 +684,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 +698,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

@@ -54,9 +54,9 @@
/// parameters to init the SPI bus:
///
/// from pyb import SPI
/// spi = SPI(2000000, bits=8, submode=0, cs=SPI.ACTIVE_LOW)
/// spi = SPI(1, SPI.MASTER, baudrate=2000000, bits=8, polarity=0, phase=0, nss=SPI.ACTIVE_LOW)
///
/// Only required parameter is the baudrate, in Hz. Submode may be 0-3.
/// Only required parameter is the baudrate, in Hz. polarity and phase may be 0 or 1.
/// Bit accepts 8, 16, 32. Chip select values are ACTIVE_LOW and ACTIVE_HIGH
///
/// Additional method for SPI:
@@ -77,6 +77,8 @@ typedef struct _pyb_spi_obj_t {
vstr_t rx_vstr;
uint tx_index;
uint rx_index;
byte polarity;
byte phase;
byte submode;
byte wlen;
} pyb_spi_obj_t;
@@ -85,7 +87,6 @@ typedef struct _pyb_spi_obj_t {
DEFINE CONSTANTS
******************************************************************************/
#define PYBSPI_DEF_BAUDRATE 1000000 // 1MHz
#define PYBSPI_CS_NONE 0xFF // spi cs is controlled by the user
/******************************************************************************
DECLARE PRIVATE DATA
@@ -163,31 +164,35 @@ 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>",
self->baudrate, self->config, self->submode, (self->wlen * 8));
}
else {
print(env, "<SPI0>");
mp_printf(print, "<SPI1, SPI.MASTER, baudrate=%u, bits=%u, polarity=%u, phase=%u, nss=%q>",
self->baudrate, (self->wlen * 8), self->polarity, self->phase,
(self->config & SPI_CS_ACTIVELOW) ? MP_QSTR_ACTIVE_LOW : MP_QSTR_ACTIVE_HIGH);
} else {
mp_print_str(print, "<SPI1>");
}
}
/// \method init(2000000, *, bits=8, submode=0, cs=SPI.ACTIVELOW)
/// \method init(mode, *, baudrate=1000000, bits=8, polarity=0, phase=0, nss=SPI.ACTIVE_LOW)
///
/// Initialise the SPI bus with the given parameters:
///
/// - `mode` must be MASTER.
/// - `baudrate` is the SCK clock rate.
/// - `bits` is the transfer width size (8, 16, 32).
/// - `submode` is the spi mode (0, 1, 2, 3).
/// - `cs` can be ACTIVELOW, ACTIVEHIGH, or NONE
/// - `polarity` (0, 1).
/// - `phase` (0, 1).
/// - `nss` can be ACTIVE_LOW or ACTIVE_HIGH.
static const mp_arg_t pybspi_init_args[] = {
{ MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYBSPI_DEF_BAUDRATE} },
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
{ MP_QSTR_submode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_cs, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_CS_ACTIVELOW} },
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_nss, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = SPI_CS_ACTIVELOW} },
};
STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
@@ -195,13 +200,13 @@ STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, mp_uint_t n_args, const
mp_arg_val_t args[MP_ARRAY_SIZE(pybspi_init_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(pybspi_init_args), pybspi_init_args, args);
uint submode = args[2].u_int;
uint cs = args[3].u_int;
uint bits;
// verify that mode is master
if (args[0].u_int != SPI_MODE_MASTER) {
goto invalid_args;
}
// save the word length for later use
self->wlen = args[1].u_int / 8;
switch (args[1].u_int) {
uint bits;
switch (args[2].u_int) {
case 8:
bits = SPI_WL_8;
break;
@@ -212,22 +217,28 @@ STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, mp_uint_t n_args, const
bits = SPI_WL_32;
break;
default:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
goto invalid_args;
break;
}
if (submode < SPI_SUB_MODE_0 || submode > SPI_SUB_MODE_3) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
uint polarity = args[3].u_int;
uint phase = args[4].u_int;
if (polarity > 1 || phase > 1) {
goto invalid_args;
}
if (cs != SPI_CS_ACTIVELOW && cs != SPI_CS_ACTIVEHIGH) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
uint nss = args[5].u_int;
if (nss != SPI_CS_ACTIVELOW && nss != SPI_CS_ACTIVEHIGH) {
goto invalid_args;
}
// build the configuration
self->baudrate = args[0].u_int;
self->config = bits | cs | SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF;
self->submode = submode;
self->baudrate = args[1].u_int;
self->wlen = args[2].u_int >> 3;
self->config = bits | nss | SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF;
self->polarity = polarity;
self->phase = phase;
self->submode = (polarity << 1) | phase;
// init the bus
pybspi_init((const pyb_spi_obj_t *)self);
@@ -236,16 +247,18 @@ STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, mp_uint_t n_args, const
pybsleep_add((const mp_obj_t)self, (WakeUpCB_t)pybspi_init);
return mp_const_none;
invalid_args:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
/// \classmethod \constructor(bus, ...)
///
/// Construct an SPI object with the given baudrate.
/// With no parameters, the SPI object is created but not
/// Construct an SPI object with the given baudrate. Bus can only be 1.
/// With no extra parameters, the SPI object is created but not
/// initialised (it has the settings from the last initialisation of
/// the bus, if any). If extra arguments are given, the bus is initialised.
/// See `init` for parameters of initialisation.
///
STATIC mp_obj_t pyb_spi_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
@@ -253,11 +266,11 @@ STATIC mp_obj_t pyb_spi_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n
pyb_spi_obj_t *self = &pyb_spi_obj;
self->base.type = &pyb_spi_type;
if (n_args > 0 || n_kw > 0) {
if (n_args > 1 || n_kw > 0) {
// start the peripheral
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
pyb_spi_init_helper(self, n_args, args, &kw_args);
pyb_spi_init_helper(self, n_args - 1, args + 1, &kw_args);
}
return self;
@@ -282,39 +295,59 @@ STATIC mp_obj_t pyb_spi_deinit(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_spi_deinit_obj, pyb_spi_deinit);
/// \method send(send)
/// \method send(send, *, timeout=5000)
/// Send data on the bus:
///
/// - `send` is the data to send (a byte to send, or a buffer object).
/// - `timeout` is the timeout in milliseconds to wait for the send.
///
STATIC mp_obj_t pyb_spi_send (mp_obj_t self_in, mp_obj_t send_o) {
pyb_spi_obj_t *self = self_in;
STATIC mp_obj_t pyb_spi_send (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
// parse args
pyb_spi_obj_t *self = pos_args[0];
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// get the buffer to send from
mp_buffer_info_t bufinfo;
uint8_t data[1];
pyb_buf_get_for_send(send_o, &bufinfo, data);
pyb_buf_get_for_send(args[0].u_obj, &bufinfo, data);
// just send
pybspi_transfer(self, (const char *)bufinfo.buf, NULL, bufinfo.len);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_spi_send_obj, pyb_spi_send);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_send_obj, 1, pyb_spi_send);
/// \method recv(recv)
/// \method recv(recv, *, timeout=5000)
///
/// Receive data on the bus:
///
/// - `recv` can be an integer, which is the number of bytes to receive,
/// or a mutable buffer, which will be filled with received bytes.
/// - `timeout` is the timeout in milliseconds to wait for the receive.
///
/// Return: if `recv` is an integer then a new buffer of the bytes received,
/// otherwise the same buffer that was passed in to `recv`.
STATIC mp_obj_t pyb_spi_recv(mp_obj_t self_in, mp_obj_t recv_o) {
pyb_spi_obj_t *self = self_in;
STATIC mp_obj_t pyb_spi_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
// parse args
pyb_spi_obj_t *self = pos_args[0];
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// get the buffer to receive into
vstr_t vstr;
mp_obj_t o_ret = pyb_buf_get_for_recv(recv_o, &vstr);
mp_obj_t o_ret = pyb_buf_get_for_recv(args[0].u_obj, &vstr);
// just receive
pybspi_transfer(self, NULL, vstr.buf, vstr.len);
@@ -326,9 +359,9 @@ STATIC mp_obj_t pyb_spi_recv(mp_obj_t self_in, mp_obj_t recv_o) {
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_spi_recv_obj, pyb_spi_recv);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_recv_obj, 1, pyb_spi_recv);
/// \method send_recv(send, recv)
/// \method send_recv(send, recv=None, *, timeout=5000)
///
/// Send and receive data on the bus at the same time:
///
@@ -336,10 +369,20 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_spi_recv_obj, pyb_spi_recv);
/// - `recv` is a mutable buffer which will be filled with received bytes.
/// It can be the same as `send`, or omitted. If omitted, a new buffer will
/// be created.
/// - `timeout` is the timeout in milliseconds to wait for the transaction to complete.
///
/// Return: the buffer with the received bytes.
STATIC mp_obj_t pyb_spi_send_recv (mp_uint_t n_args, const mp_obj_t *args) {
pyb_spi_obj_t *self = args[0];
STATIC mp_obj_t pyb_spi_send_recv (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_send, MP_ARG_REQUIRED | MP_ARG_OBJ, },
{ MP_QSTR_recv, MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
// parse args
pyb_spi_obj_t *self = pos_args[0];
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// get buffers to send from/receive to
mp_buffer_info_t bufinfo_send;
@@ -348,35 +391,34 @@ STATIC mp_obj_t pyb_spi_send_recv (mp_uint_t n_args, const mp_obj_t *args) {
vstr_t vstr_recv;
mp_obj_t o_ret;
if (args[1] == args[2]) {
if (args[0].u_obj == args[1].u_obj) {
// same object for sending and receiving, it must be a r/w buffer
mp_get_buffer_raise(args[1], &bufinfo_send, MP_BUFFER_RW);
mp_get_buffer_raise(args[0].u_obj, &bufinfo_send, MP_BUFFER_RW);
bufinfo_recv = bufinfo_send;
o_ret = args[1];
o_ret = args[0].u_obj;
} else {
// get the buffer to send from
pyb_buf_get_for_send(args[1], &bufinfo_send, data_send);
pyb_buf_get_for_send(args[0].u_obj, &bufinfo_send, data_send);
// get the buffer to receive into
if (n_args == 2) {
if (args[1].u_obj == mp_const_none) {
// only the send was argument given, so create a fresh buffer of the send length
vstr_init_len(&vstr_recv, bufinfo_send.len);
bufinfo_recv.len = vstr_recv.len;
bufinfo_recv.buf = vstr_recv.buf;
o_ret = MP_OBJ_NULL;
}
else {
} else {
// recv argument given
mp_get_buffer_raise(args[2], &bufinfo_recv, MP_BUFFER_WRITE);
mp_get_buffer_raise(args[1].u_obj, &bufinfo_recv, MP_BUFFER_WRITE);
if (bufinfo_recv.len != bufinfo_send.len) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
o_ret = args[2];
o_ret = args[1].u_obj;
}
}
// send and receive
pybspi_transfer(self, (const char *)bufinfo_send.buf, vstr_recv.buf, bufinfo_send.len);
pybspi_transfer(self, (const char *)bufinfo_send.buf, bufinfo_recv.buf, bufinfo_send.len);
// return the received data
if (o_ret != MP_OBJ_NULL) {
@@ -385,7 +427,7 @@ STATIC mp_obj_t pyb_spi_send_recv (mp_uint_t n_args, const mp_obj_t *args) {
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr_recv);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_spi_send_recv_obj, 2, 3, pyb_spi_send_recv);
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_send_recv_obj, 1, pyb_spi_send_recv);
STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
// instance methods
@@ -396,6 +438,7 @@ STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_send_recv), (mp_obj_t)&pyb_spi_send_recv_obj },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(SPI_MODE_MASTER) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ACTIVE_LOW), MP_OBJ_NEW_SMALL_INT(SPI_CS_ACTIVELOW) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ACTIVE_HIGH), MP_OBJ_NEW_SMALL_INT(SPI_CS_ACTIVEHIGH) },
};

880
cc3200/mods/pybtimer.c Normal file
View File

@@ -0,0 +1,880 @@
/*
* This file is part of the Micro Python project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2015 Daniel Campora
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/obj.h"
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/gc.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_timer.h"
#include "rom_map.h"
#include "interrupt.h"
#include "prcm.h"
#include "timer.h"
#include "pybtimer.h"
#include "pybsleep.h"
#include "mpcallback.h"
#include "mpexception.h"
/// \moduleref pyb
/// \class Timer - generate periodic events, count events, and create PWM signals.
///
/// Each timer consists of a counter that counts up at a certain rate. The rate
/// at which it counts is the peripheral clock frequency (in Hz) divided by the
/// timer prescaler. When the counter reaches the timer period it triggers an
/// event, and the counter resets back to zero. By using the callback method,
/// the timer event can call a Python function.
///
/// Example usage to toggle an LED at a fixed frequency:
///
/// tim = pyb.Timer(4) # create a timer object using timer 4
/// tim.init(mode=Timer.PERIODIC) # initialize it in periodic mode
/// tim_ch = tim.channel(Timer.A, freq=2) # configure channel A at a frequency of 2Hz
/// tim_ch.callback(handler=lambda t:led.toggle()) # toggle a LED on every cycle of the timer
///
/// Further examples:
///
/// tim1 = pyb.Timer(2, mode=Timer.EVENT_COUNT) # initialize it capture mode
/// tim2 = pyb.Timer(1, mode=Timer.PWM) # initialize it in PWM mode
/// tim_ch = tim1.channel(Timer.A, freq=1, polarity=Timer.POSITIVE) # start the event counter with a frequency of 1Hz and triggered by positive edges
/// tim_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=50) # start the PWM on channel B with a 50% duty cycle
/// tim_ch.time() # get the current time in usec (can also be set)
/// tim_ch.freq(20) # set the frequency (can also get)
/// tim_ch.duty_cycle(30) # set the duty cycle to 30% (can also get)
/// tim_ch.duty_cycle(30, Timer.NEGATIVE) # set the duty cycle to 30% and change the polarity to negative
/// tim_ch.event_count() # get the number of captured events
/// tim_ch.event_time() # get the the time of the last captured event
/// tim_ch.period(2000000) # change the period to 2 seconds
///
/******************************************************************************
DECLARE PRIVATE CONSTANTS
******************************************************************************/
#define PYBTIMER_NUM_TIMERS (4)
#define PYBTIMER_POLARITY_POS (0x01)
#define PYBTIMER_POLARITY_NEG (0x02)
#define PYBTIMER_SRC_FREQ_HZ HAL_FCPU_HZ
/******************************************************************************
DEFINE PRIVATE TYPES
******************************************************************************/
typedef struct _pyb_timer_obj_t {
mp_obj_base_t base;
uint32_t timer;
uint32_t config;
uint16_t intflags;
uint8_t peripheral;
uint8_t id;
} pyb_timer_obj_t;
typedef struct _pyb_timer_channel_obj_t {
mp_obj_base_t base;
struct _pyb_timer_obj_t *timer;
uint32_t frequency;
uint32_t period;
uint16_t channel;
uint8_t polarity;
uint8_t duty_cycle;
} pyb_timer_channel_obj_t;
/******************************************************************************
DEFINE PRIVATE DATA
******************************************************************************/
STATIC const mp_cb_methods_t pyb_timer_channel_cb_methods;
STATIC pyb_timer_obj_t pyb_timer_obj[PYBTIMER_NUM_TIMERS] = {{.timer = TIMERA0_BASE, .peripheral = PRCM_TIMERA0},
{.timer = TIMERA1_BASE, .peripheral = PRCM_TIMERA1},
{.timer = TIMERA2_BASE, .peripheral = PRCM_TIMERA2},
{.timer = TIMERA3_BASE, .peripheral = PRCM_TIMERA3}};
STATIC const mp_obj_type_t pyb_timer_channel_type;
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
STATIC mp_obj_t pyb_timer_channel_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
STATIC void timer_disable (pyb_timer_obj_t *tim);
STATIC void TIMER0AIntHandler(void);
STATIC void TIMER0BIntHandler(void);
STATIC void TIMER1AIntHandler(void);
STATIC void TIMER1BIntHandler(void);
STATIC void TIMER2AIntHandler(void);
STATIC void TIMER2BIntHandler(void);
STATIC void TIMER3AIntHandler(void);
STATIC void TIMER3BIntHandler(void);
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
void timer_init0 (void) {
mp_obj_list_init(&MP_STATE_PORT(pyb_timer_channel_obj_list), 0);
}
void timer_disable_all (void) {
pyb_timer_obj_t timer = {
.timer = TIMERA0_BASE,
.intflags = TIMER_CAPB_EVENT | TIMER_CAPB_MATCH |
TIMER_TIMB_TIMEOUT | TIMER_CAPA_EVENT |
TIMER_CAPA_MATCH | TIMER_TIMA_TIMEOUT,
.peripheral = PRCM_TIMERA0
};
for (uint32_t i = 0; i < PYBTIMER_NUM_TIMERS; i++) {
// in case it's not clocked
MAP_PRCMPeripheralClkEnable(timer.peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
timer_disable(&timer);
// timer base offset according to hw_memmap.h
timer.timer += 0x1000;
// peripheral offset according to prcm.h
timer.peripheral++;
}
}
void pyb_timer_channel_callback_enable (mp_obj_t self_in) {
pyb_timer_channel_obj_t *self = self_in;
MAP_TimerIntClear(self->timer->timer, self->timer->intflags & self->channel);
MAP_TimerIntEnable(self->timer->timer, self->timer->intflags & self->channel);
}
void pyb_timer_channel_callback_disable (mp_obj_t self_in) {
pyb_timer_channel_obj_t *self = self_in;
MAP_TimerIntDisable(self->timer->timer, self->timer->intflags & self->channel);
}
pyb_timer_channel_obj_t *pyb_timer_channel_find (uint32_t timer, uint16_t channel_n) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(pyb_timer_channel_obj_list).len; i++) {
pyb_timer_channel_obj_t *ch = ((pyb_timer_channel_obj_t *)(MP_STATE_PORT(pyb_timer_channel_obj_list).items[i]));
// any 32-bit timer must be matched by any of its 16-bit versions
if (ch->timer->timer == timer && ((ch->channel & TIMER_A) == channel_n || (ch->channel & TIMER_B) == channel_n)) {
return ch;
}
}
return MP_OBJ_NULL;
}
void pyb_timer_channel_remove (pyb_timer_channel_obj_t *ch) {
pyb_timer_channel_obj_t *channel;
if ((channel = pyb_timer_channel_find(ch->timer->timer, ch->channel))) {
mp_obj_list_remove(&MP_STATE_PORT(pyb_timer_channel_obj_list), channel);
}
}
void pyb_timer_channel_add (pyb_timer_channel_obj_t *ch) {
// remove it in case it already exists
pyb_timer_channel_remove(ch);
mp_obj_list_append(&MP_STATE_PORT(pyb_timer_channel_obj_list), ch);
}
STATIC void timer_disable (pyb_timer_obj_t *tim) {
// disable all timers and it's interrupts
MAP_TimerDisable(tim->timer, TIMER_A | TIMER_B);
MAP_TimerIntDisable(tim->timer, tim->intflags);
MAP_TimerIntClear(tim->timer, tim->intflags);
MAP_PRCMPeripheralClkDisable(tim->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
memset(&pyb_timer_obj[tim->id], 0, sizeof(pyb_timer_obj_t));
}
// computes prescaler period and match value so timer triggers at freq-Hz
STATIC uint32_t compute_prescaler_period_and_match_value(pyb_timer_channel_obj_t *ch, uint32_t *period_out, uint32_t *match_out) {
uint32_t maxcount = (ch->channel == (TIMER_A | TIMER_B)) ? 0xFFFFFFFF : 0xFFFF;
uint32_t prescaler;
uint32_t period_c = (ch->frequency > 0) ? PYBTIMER_SRC_FREQ_HZ / ch->frequency : ((PYBTIMER_SRC_FREQ_HZ / 1000000) * ch->period);
period_c = MAX(1, period_c) - 1;
if (period_c == 0) {
goto error;
}
prescaler = period_c >> 16;
*period_out = period_c;
if (prescaler > 0xFF && maxcount == 0xFFFF) {
goto error;
}
// check limit values for the duty cycle
if (ch->duty_cycle == 0) {
*match_out = period_c - 1;
}
else {
*match_out = period_c - ((period_c * ch->duty_cycle) / 100);
}
if ((ch->timer->config & 0x0F) == TIMER_CFG_A_PWM && (*match_out > 0xFFFF)) {
goto error;
}
return prescaler;
error:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
STATIC void timer_init (pyb_timer_obj_t *tim) {
MAP_PRCMPeripheralClkEnable(tim->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
MAP_PRCMPeripheralReset(tim->peripheral);
MAP_TimerConfigure(tim->timer, tim->config);
}
STATIC void timer_channel_init (pyb_timer_channel_obj_t *ch) {
// calculate the period, the prescaler and the match value
uint32_t period_c;
uint32_t match;
uint32_t prescaler = compute_prescaler_period_and_match_value(ch, &period_c, &match);
// set the prescaler
MAP_TimerPrescaleSet(ch->timer->timer, ch->channel, (prescaler < 0xFF) ? prescaler : 0);
// set the load value
MAP_TimerLoadSet(ch->timer->timer, ch->channel, period_c);
// configure the pwm if we are in such mode
if ((ch->timer->config & 0x0F) == TIMER_CFG_A_PWM) {
// invert the timer output if required
MAP_TimerControlLevel(ch->timer->timer, ch->channel, (ch->polarity == PYBTIMER_POLARITY_NEG) ? true : false);
// set the match value (which is simply the duty cycle translated to ticks)
MAP_TimerMatchSet(ch->timer->timer, ch->channel, match);
}
// configure the event edge type if we are in such mode
else if ((ch->timer->config & 0x0F) == TIMER_CFG_A_CAP_COUNT || (ch->timer->config & 0x0F) == TIMER_CFG_A_CAP_TIME) {
uint32_t polarity = TIMER_EVENT_BOTH_EDGES;
if (ch->polarity == PYBTIMER_POLARITY_POS) {
polarity = TIMER_EVENT_POS_EDGE;
}
else if (ch->polarity == PYBTIMER_POLARITY_NEG) {
polarity = TIMER_EVENT_NEG_EDGE;
}
MAP_TimerControlEvent(ch->timer->timer, ch->channel, polarity);
}
#ifdef DEBUG
// stall the timer when the processor is halted while debugging
MAP_TimerControlStall(ch->timer->timer, ch->channel, true);
#endif
// now enable the timer channel
MAP_TimerEnable(ch->timer->timer, ch->channel);
}
/******************************************************************************/
/* Micro Python bindings */
STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_timer_obj_t *tim = self_in;
uint32_t mode = tim->config & 0xFF;
// timer mode
qstr mode_qst = MP_QSTR_PWM;
switch(mode) {
case TIMER_CFG_A_ONE_SHOT:
mode_qst = MP_QSTR_ONE_SHOT;
break;
case TIMER_CFG_A_PERIODIC:
mode_qst = MP_QSTR_PERIODIC;
break;
case TIMER_CFG_A_CAP_COUNT:
mode_qst = MP_QSTR_EDGE_COUNT;
break;
case TIMER_CFG_A_CAP_TIME:
mode_qst = MP_QSTR_EDGE_TIME;
break;
default:
break;
}
mp_printf(print, "<Timer%u, mode=Timer.%q>", (tim->id + 1), mode_qst);
}
/// \method init(mode, *, width)
/// Initialise the timer. Initialisation must give the desired mode
/// and an optional timer width
///
/// tim.init(mode=Timer.ONE_SHOT, width=32) # one shot mode
/// tim.init(mode=Timer.PERIODIC) # configure in free running periodic mode
/// split into two 16-bit independent timers
///
/// Keyword arguments:
///
/// - `width` - specifies the width of the timer. Default is 32 bit mode. When in 16 bit mode
/// the timer is splitted into 2 independent channels.
///
STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, },
{ MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16} },
};
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// check the mode
uint32_t _mode = args[0].u_int;
if (_mode != TIMER_CFG_A_ONE_SHOT && _mode != TIMER_CFG_A_PERIODIC && _mode != TIMER_CFG_A_CAP_COUNT &&
_mode != TIMER_CFG_A_CAP_TIME && _mode != TIMER_CFG_A_PWM) {
goto error;
}
// check the width
if (args[1].u_int != 16 && args[1].u_int != 32) {
goto error;
}
bool is16bit = (args[1].u_int == 16);
if (!is16bit && (_mode != TIMER_CFG_A_ONE_SHOT && _mode != TIMER_CFG_A_PERIODIC)) {
// 32-bit mode is only available when in free running modes
goto error;
}
tim->config = is16bit ? ((_mode | (_mode << 8)) | TIMER_CFG_SPLIT_PAIR) : _mode;
timer_init(tim);
// register it with the sleep module
pybsleep_add ((const mp_obj_t)tim, (WakeUpCB_t)timer_init);
return mp_const_none;
error:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
/// \classmethod \constructor(id, ...)
/// Construct a new timer object of the given id. If additional
/// arguments are given, then the timer is initialised by `init(...)`.
/// `id` can be 1 to 4
STATIC mp_obj_t pyb_timer_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
// check arguments
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// create a new Timer object
int32_t timer_idx = mp_obj_get_int(args[0]) - 1;
if (timer_idx < 0 || timer_idx > (PYBTIMER_NUM_TIMERS - 1)) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
}
pyb_timer_obj_t *tim = &pyb_timer_obj[timer_idx];
tim->base.type = &pyb_timer_type;
tim->id = timer_idx;
if (n_args > 1 || n_kw > 0) {
// start the peripheral
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
pyb_timer_init_helper(tim, n_args - 1, args + 1, &kw_args);
}
return (mp_obj_t)tim;
}
// \method init()
/// initializes the timer
STATIC mp_obj_t pyb_timer_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
return pyb_timer_init_helper(args[0], n_args - 1, args + 1, kw_args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_init_obj, 1, pyb_timer_init);
// \method deinit()
/// disables the timer
STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in) {
pyb_timer_obj_t *self = self_in;
timer_disable(self);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit);
/// \method channel(channel, *, freq, period, polarity, duty_cycle)
/// Initialise the timer channel. Initialization requires at least a frequency param. With no
/// extra params given besides the channel id, the channel is returned with the previous configuration
/// os 'None', if it hasn't been initialized before.
///
/// tim1.channel(Timer.A, freq=1000) # set channel A frequency to 1KHz
/// tim2.channel(Timer.AB, freq=10) # both channels (because it's a 32 bit timer) combined to create a 10Hz timer
///
/// when initialiazing the channel of a 32-bit timer, channel ID MUST be = Timer.AB
///
/// Keyword arguments:
///
/// - `freq` - specifies the frequency in Hz.
/// - `period` - specifies the period in microseconds.
/// - `polarity` - in PWM specifies the polarity of the pulse. In capture mode specifies the edge to capture.
/// in order to capture on both negative and positive edges, make it = Timer.POSITIVE | Timer.NEGATIVE.
/// - `duty_cycle` - sets the duty cycle value
///
STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYBTIMER_POLARITY_POS} },
{ MP_QSTR_duty_cycle, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
};
pyb_timer_obj_t *tim = pos_args[0];
mp_int_t channel_n = mp_obj_get_int(pos_args[1]);
// verify that the timer has been already initialized
if (!tim->config) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
if (channel_n != TIMER_A && channel_n != TIMER_B && channel_n != (TIMER_A | TIMER_B)) {
// invalid channel
goto error;
}
if (channel_n == (TIMER_A | TIMER_B) && (tim->config & TIMER_CFG_SPLIT_PAIR)) {
// 32-bit channel selected when the timer is in 16-bit mode
goto error;
}
// if only the channel number is given return the previously
// allocated channel (or None if no previous channel)
if (n_args == 2 && kw_args->used == 0) {
pyb_timer_channel_obj_t *ch;
if ((ch = pyb_timer_channel_find(tim->timer, channel_n))) {
return ch;
}
return mp_const_none;
}
// parse the arguments
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// throw an exception if both frequency and period are given
if (args[0].u_int != 0 && args[1].u_int != 0) {
goto error;
}
// check that at least one of them has a valid value
if (args[0].u_int <= 0 && args[1].u_int <= 0) {
goto error;
}
// check that the polarity is not 'both' in pwm mode
if ((tim->config & TIMER_A) == TIMER_CFG_A_PWM && args[2].u_int == (PYBTIMER_POLARITY_POS | PYBTIMER_POLARITY_NEG)) {
goto error;
}
// allocate a new timer channel
pyb_timer_channel_obj_t *ch = m_new_obj(pyb_timer_channel_obj_t);
ch->base.type = &pyb_timer_channel_type;
ch->timer = tim;
ch->channel = channel_n;
// get the frequency the polarity and the duty cycle
ch->frequency = args[0].u_int;
ch->period = args[1].u_int;
ch->polarity = args[2].u_int;
ch->duty_cycle = MIN(100, MAX(0, args[3].u_int));
timer_channel_init(ch);
// register it with the sleep module
pybsleep_add ((const mp_obj_t)ch, (WakeUpCB_t)timer_channel_init);
// add the timer to the list
pyb_timer_channel_add(ch);
return ch;
error:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_obj, 2, pyb_timer_channel);
STATIC const mp_map_elem_t pyb_timer_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_timer_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_timer_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_channel), (mp_obj_t)&pyb_timer_channel_obj },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_A), MP_OBJ_NEW_SMALL_INT(TIMER_A) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_B), MP_OBJ_NEW_SMALL_INT(TIMER_B) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ONE_SHOT), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_ONE_SHOT) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PERIODIC), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_PERIODIC) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_EDGE_COUNT), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_CAP_COUNT) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_EDGE_TIME), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_CAP_TIME) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PWM), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_PWM) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_POSITIVE), MP_OBJ_NEW_SMALL_INT(PYBTIMER_POLARITY_POS) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_NEGATIVE), MP_OBJ_NEW_SMALL_INT(PYBTIMER_POLARITY_NEG) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table);
const mp_obj_type_t pyb_timer_type = {
{ &mp_type_type },
.name = MP_QSTR_Timer,
.print = pyb_timer_print,
.make_new = pyb_timer_make_new,
.locals_dict = (mp_obj_t)&pyb_timer_locals_dict,
};
STATIC const mp_cb_methods_t pyb_timer_channel_cb_methods = {
.init = pyb_timer_channel_callback,
.enable = pyb_timer_channel_callback_enable,
.disable = pyb_timer_channel_callback_disable,
};
STATIC void TIMERGenericIntHandler(uint32_t timer, uint16_t channel) {
pyb_timer_channel_obj_t *self;
uint32_t status;
if ((self = pyb_timer_channel_find(timer, channel))) {
status = MAP_TimerIntStatus(self->timer->timer, true) & self->channel;
MAP_TimerIntClear(self->timer->timer, status);
mp_obj_t _callback = mpcallback_find(self);
mpcallback_handler(_callback);
}
}
STATIC void TIMER0AIntHandler(void) {
TIMERGenericIntHandler(TIMERA0_BASE, TIMER_A);
}
STATIC void TIMER0BIntHandler(void) {
TIMERGenericIntHandler(TIMERA0_BASE, TIMER_B);
}
STATIC void TIMER1AIntHandler(void) {
TIMERGenericIntHandler(TIMERA1_BASE, TIMER_A);
}
STATIC void TIMER1BIntHandler(void) {
TIMERGenericIntHandler(TIMERA1_BASE, TIMER_B);
}
STATIC void TIMER2AIntHandler(void) {
TIMERGenericIntHandler(TIMERA2_BASE, TIMER_A);
}
STATIC void TIMER2BIntHandler(void) {
TIMERGenericIntHandler(TIMERA2_BASE, TIMER_B);
}
STATIC void TIMER3AIntHandler(void) {
TIMERGenericIntHandler(TIMERA3_BASE, TIMER_A);
}
STATIC void TIMER3BIntHandler(void) {
TIMERGenericIntHandler(TIMERA3_BASE, TIMER_B);
}
STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_timer_channel_obj_t *ch = self_in;
char *ch_id = "AB";
// timer channel
if (ch->channel == TIMER_A) {
ch_id = "A";
}
else if (ch->channel == TIMER_B) {
ch_id = "B";
}
mp_printf(print, "<%q %s, timer=%u, %q=%u", MP_QSTR_TimerChannel,
ch_id, (ch->timer->id + 1), MP_QSTR_freq, ch->frequency);
uint32_t mode = ch->timer->config & 0xFF;
if (mode == TIMER_CFG_A_CAP_COUNT || mode == TIMER_CFG_A_CAP_TIME || mode == TIMER_CFG_A_PWM) {
mp_printf(print, ", %q=Timer.", MP_QSTR_polarity);
switch (ch->polarity) {
case PYBTIMER_POLARITY_POS:
mp_printf(print, "POSITIVE");
break;
case PYBTIMER_POLARITY_NEG:
mp_printf(print, "NEGATIVE");
break;
default:
mp_printf(print, "BOTH");
break;
}
if (mode == TIMER_CFG_A_PWM) {
mp_printf(print, ", %q=%u", MP_QSTR_duty_cycle, ch->duty_cycle);
}
}
mp_printf(print, ">");
}
/// \method freq([value])
/// get or set the frequency of the timer channel
STATIC mp_obj_t pyb_timer_channel_freq(mp_uint_t n_args, const mp_obj_t *args) {
pyb_timer_channel_obj_t *ch = args[0];
if (n_args == 1) {
// get
return mp_obj_new_int(ch->frequency);
} else {
// set
int32_t _frequency = mp_obj_get_int(args[1]);
if (_frequency <= 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
ch->frequency = _frequency;
ch->period = 1000000 / _frequency;
timer_channel_init(ch);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_freq_obj, 1, 2, pyb_timer_channel_freq);
/// \method period([value])
/// get or set the period of the timer channel in microseconds
STATIC mp_obj_t pyb_timer_channel_period(mp_uint_t n_args, const mp_obj_t *args) {
pyb_timer_channel_obj_t *ch = args[0];
if (n_args == 1) {
// get
return mp_obj_new_int(ch->period);
} else {
// set
int32_t _period = mp_obj_get_int(args[1]);
if (_period <= 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
ch->period = _period;
ch->frequency = 1000000 / _period;
timer_channel_init(ch);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_period_obj, 1, 2, pyb_timer_channel_period);
/// \method time([value])
/// get or set the value of the timer channel in microseconds
STATIC mp_obj_t pyb_timer_channel_time(mp_uint_t n_args, const mp_obj_t *args) {
pyb_timer_channel_obj_t *ch = args[0];
uint32_t value;
// calculate the period, the prescaler and the match value
uint32_t period_c;
uint32_t match;
(void)compute_prescaler_period_and_match_value(ch, &period_c, &match);
if (n_args == 1) {
// get
value = (ch->channel == TIMER_B) ? HWREG(ch->timer->timer + TIMER_O_TBV) : HWREG(ch->timer->timer + TIMER_O_TAV);
// return the current timer value in microseconds
// substract value to period since we are always operating in count-down mode
uint32_t time_t = (1000 * (period_c - value)) / period_c;
return mp_obj_new_int((time_t * 1000) / ch->frequency);
}
else {
// set
value = (mp_obj_get_int(args[1]) * ((ch->frequency * period_c) / 1000)) / 1000;
if ((value > 0xFFFF) && (ch->timer->config & TIMER_CFG_SPLIT_PAIR)) {
// this exceeds the maximum value of a 16-bit timer
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
// write period minus value since we are always operating in count-down mode
TimerValueSet (ch->timer->timer, ch->channel, (period_c - value));
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_time_obj, 1, 2, pyb_timer_channel_time);
/// \method event_count()
/// get the number of events triggered by the configured edge
STATIC mp_obj_t pyb_timer_channel_event_count(mp_obj_t self_in) {
pyb_timer_channel_obj_t *ch = self_in;
return mp_obj_new_int(MAP_TimerValueGet(ch->timer->timer, ch->channel == (TIMER_A | TIMER_B) ? TIMER_A : ch->channel));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_channel_event_count_obj, pyb_timer_channel_event_count);
/// \method event_time()
/// get the time at which the last event was triggered
STATIC mp_obj_t pyb_timer_channel_event_time(mp_obj_t self_in) {
pyb_timer_channel_obj_t *ch = self_in;
// calculate the period, the prescaler and the match value
uint32_t period_c;
uint32_t match;
(void)compute_prescaler_period_and_match_value(ch, &period_c, &match);
uint32_t value = MAP_TimerValueGet(ch->timer->timer, ch->channel == (TIMER_A | TIMER_B) ? TIMER_A : ch->channel);
// substract value to period since we are always operating in count-down mode
uint32_t time_t = (1000 * (period_c - value)) / period_c;
return mp_obj_new_int((time_t * 1000) / ch->frequency);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_channel_event_time_obj, pyb_timer_channel_event_time);
/// \method duty_cycle()
/// get or set the duty cycle when in PWM mode
STATIC mp_obj_t pyb_timer_channel_duty_cycle(mp_uint_t n_args, const mp_obj_t *args) {
pyb_timer_channel_obj_t *ch = args[0];
if (n_args == 1) {
// get
return mp_obj_new_int(ch->duty_cycle);
}
else {
// duty cycle must be converted from percentage to ticks
// calculate the period, the prescaler and the match value
uint32_t period_c;
uint32_t match;
ch->duty_cycle = MIN(100, MAX(0, mp_obj_get_int(args[1])));
compute_prescaler_period_and_match_value(ch, &period_c, &match);
if (n_args == 3) {
// set the new polarity if requested
ch->polarity = mp_obj_get_int(args[2]);
MAP_TimerControlLevel(ch->timer->timer, ch->channel, (ch->polarity == PYBTIMER_POLARITY_NEG) ? true : false);
}
MAP_TimerMatchSet(ch->timer->timer, ch->channel, match);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_duty_cycle_obj, 1, 3, pyb_timer_channel_duty_cycle);
/// \method callback(handler, priority, value)
/// create a callback object associated with the timer channel
STATIC mp_obj_t pyb_timer_channel_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
mp_arg_val_t args[mpcallback_INIT_NUM_ARGS];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mpcallback_INIT_NUM_ARGS, mpcallback_init_args, args);
pyb_timer_channel_obj_t *ch = pos_args[0];
mp_obj_t _callback = mpcallback_find(ch);
if (kw_args->used > 0 || !_callback) {
// convert the priority to the correct value
uint priority = mpcallback_translate_priority (args[2].u_int);
// validate the power mode
uint pwrmode = args[4].u_int;
if (pwrmode != PYB_PWR_MODE_ACTIVE) {
goto invalid_args;
}
uint32_t _config = (ch->channel == TIMER_B) ? ((ch->timer->config & TIMER_B) >> 8) : (ch->timer->config & TIMER_A);
// validate and set the value if we are in edge count mode
if (_config == TIMER_CFG_A_CAP_COUNT) {
uint32_t c_value = args[3].u_int;
if (!c_value || c_value > 0xFFFF) {
// zero or exceeds the maximum value of a 16-bit timer
goto invalid_args;
}
MAP_TimerMatchSet(ch->timer->timer, ch->channel, c_value);
}
// disable the callback first
pyb_timer_channel_callback_disable(ch);
uint8_t shift = (ch->channel == TIMER_B) ? 8 : 0;
switch (_config) {
case TIMER_CFG_A_ONE_SHOT:
case TIMER_CFG_A_PERIODIC:
ch->timer->intflags |= TIMER_TIMA_TIMEOUT << shift;
break;
case TIMER_CFG_A_CAP_COUNT:
ch->timer->intflags |= TIMER_CAPA_MATCH << shift;
// set the match value and make 1 the minimum
MAP_TimerMatchSet(ch->timer->timer, ch->channel, MAX(1, args[3].u_int));
break;
case TIMER_CFG_A_CAP_TIME:
ch->timer->intflags |= TIMER_CAPA_EVENT << shift;
break;
case TIMER_CFG_A_PWM:
// special case for the PWM match interrupt
ch->timer->intflags |= ((ch->channel & TIMER_A) == TIMER_A) ? TIMER_TIMA_MATCH : TIMER_TIMB_MATCH;
break;
default:
break;
}
// special case for a 32-bit timer
if (ch->channel == (TIMER_A | TIMER_B)) {
ch->timer->intflags |= (ch->timer->intflags << 8);
}
void (*pfnHandler)(void);
uint32_t intregister;
switch (ch->timer->timer) {
case TIMERA0_BASE:
if (ch->channel == TIMER_B) {
pfnHandler = &TIMER0BIntHandler;
intregister = INT_TIMERA0B;
} else {
pfnHandler = &TIMER0AIntHandler;
intregister = INT_TIMERA0A;
}
break;
case TIMERA1_BASE:
if (ch->channel == TIMER_B) {
pfnHandler = &TIMER1BIntHandler;
intregister = INT_TIMERA1B;
} else {
pfnHandler = &TIMER1AIntHandler;
intregister = INT_TIMERA1A;
}
break;
case TIMERA2_BASE:
if (ch->channel == TIMER_B) {
pfnHandler = &TIMER2BIntHandler;
intregister = INT_TIMERA2B;
} else {
pfnHandler = &TIMER2AIntHandler;
intregister = INT_TIMERA2A;
}
break;
default:
if (ch->channel == TIMER_B) {
pfnHandler = &TIMER3BIntHandler;
intregister = INT_TIMERA3B;
} else {
pfnHandler = &TIMER3AIntHandler;
intregister = INT_TIMERA3A;
}
break;
}
// register the interrupt and configure the priority
MAP_IntPrioritySet(intregister, priority);
MAP_TimerIntRegister(ch->timer->timer, ch->channel, pfnHandler);
// create the callback
_callback = mpcallback_new (ch, args[1].u_obj, &pyb_timer_channel_cb_methods);
// reload the timer
uint32_t period_c;
uint32_t match;
compute_prescaler_period_and_match_value(ch, &period_c, &match);
MAP_TimerLoadSet(ch->timer->timer, ch->channel, period_c);
// enable the callback before returning
pyb_timer_channel_callback_enable(ch);
}
return _callback;
invalid_args:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_callback_obj, 1, pyb_timer_channel_callback);
STATIC const mp_map_elem_t pyb_timer_channel_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&pyb_timer_channel_freq_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_period), (mp_obj_t)&pyb_timer_channel_period_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&pyb_timer_channel_time_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_event_count), (mp_obj_t)&pyb_timer_channel_event_count_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_event_time), (mp_obj_t)&pyb_timer_channel_event_time_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_duty_cycle), (mp_obj_t)&pyb_timer_channel_duty_cycle_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pyb_timer_channel_callback_obj },
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table);
STATIC const mp_obj_type_t pyb_timer_channel_type = {
{ &mp_type_type },
.name = MP_QSTR_TimerChannel,
.print = pyb_timer_channel_print,
.locals_dict = (mp_obj_t)&pyb_timer_channel_locals_dict,
};

View File

@@ -25,17 +25,14 @@
* 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.
/******************************************************************************
DECLARE EXPORTED DATA
******************************************************************************/
extern const mp_obj_type_t pyb_timer_type;
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
******************************************************************************/
void timer_init0 (void);
void timer_disable_all (void);
//*****************************************************************************
// Define types
//*****************************************************************************
enum {
PORT_A0 = GPIOA0_BASE,
PORT_A1 = GPIOA1_BASE,
PORT_A2 = GPIOA2_BASE,
PORT_A3 = GPIOA3_BASE
};

View File

@@ -51,6 +51,7 @@
#include "mpexception.h"
#include "py/mpstate.h"
#include "osi.h"
#include "utils.h"
/// \moduleref pyb
/// \class UART - duplex serial communication bus
@@ -62,7 +63,7 @@
///
/// from pyb import UART
///
/// uart = UART(0, 9600) # init with given baudrate
/// uart = UART(1, 9600) # init with given baudrate
/// uart.init(9600, bits=8, stop=1, parity=None) # init with given parameters
///
/// Bits can be 5, 6, 7, 8, parity can be None, 0 (even), 1 (odd). Stop can be 1 or 2.
@@ -88,8 +89,8 @@
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
#define PYBUART_TX_WAIT_MS 1
#define PYBUART_TX_MAX_TIMEOUT_MS 5
#define PYBUART_TX_WAIT_US (50)
#define PYBUART_TX_MAX_TIMEOUT_MS (5)
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
@@ -101,6 +102,7 @@ STATIC void UART0IntHandler(void);
STATIC void UART1IntHandler(void);
STATIC void uart_callback_enable (mp_obj_t self_in);
STATIC void uart_callback_disable (mp_obj_t self_in);
STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in);
/******************************************************************************
DEFINE PRIVATE TYPES
@@ -124,7 +126,8 @@ struct _pyb_uart_obj_t {
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
STATIC pyb_uart_obj_t pyb_uart_obj[PYB_NUM_UARTS];
STATIC pyb_uart_obj_t pyb_uart_obj[PYB_NUM_UARTS] = {{.reg = UARTA0_BASE, .baudrate = 0, .peripheral = PRCM_UARTA0},
{.reg = UARTA1_BASE, .baudrate = 0, .peripheral = PRCM_UARTA1}};
STATIC const mp_cb_methods_t uart_cb_methods;
/******************************************************************************
@@ -153,10 +156,10 @@ bool uart_tx_char(pyb_uart_obj_t *self, int c) {
uint32_t timeout = 0;
while (!MAP_UARTCharPutNonBlocking(self->reg, c)) {
if (timeout++ > (PYBUART_TX_MAX_TIMEOUT_MS / PYBUART_TX_WAIT_MS)) {
if (timeout++ > ((PYBUART_TX_MAX_TIMEOUT_MS * 1000) / PYBUART_TX_WAIT_US)) {
return false;
}
HAL_Delay (PYBUART_TX_WAIT_MS);
UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBUART_TX_WAIT_US));
}
return true;
}
@@ -208,20 +211,19 @@ mp_obj_t uart_callback_new (pyb_uart_obj_t *self, mp_obj_t handler, uint rxbuffe
return _callback;
}
void uart_disable_all (void) {
for (int i = 0; i < PYB_NUM_UARTS; i++) {
// in case it's not clocked
MAP_PRCMPeripheralClkEnable(pyb_uart_obj[i].peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
pyb_uart_deinit(&pyb_uart_obj[i]);
}
}
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
// assumes init parameters have been set up correctly
STATIC void uart_init (pyb_uart_obj_t *self) {
if (self->uart_id == PYB_UART_0) {
self->reg = UARTA0_BASE;
self->peripheral = PRCM_UARTA0;
}
else {
self->reg = UARTA1_BASE;
self->peripheral = PRCM_UARTA1;
}
// Enable the peripheral clock
MAP_PRCMPeripheralClkEnable(self->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
@@ -312,37 +314,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 + 1), 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 + 1));
}
}
@@ -351,11 +353,11 @@ STATIC void pyb_uart_print(void (*print)(void *env, const char *fmt, ...), void
/// Initialise the UART bus with the given parameters:
///
/// - `baudrate` is the clock rate.
/// - `bits` is the number of bits per byte, 7, 8 or 9.
/// - `bits` is the number of bits per byte, 5, 6, 7, 8
/// - `parity` is the parity, `None`, 0 (even) or 1 (odd).
/// - `stop` is the number of stop bits, 1 or 2.
/// - `flowcontrol` is the flow control mode, `None`, `UART.FLOW_TX`,
/// `UART.FLOW_RX', 'UART.FLOW_TXRX`.
/// - `flow` is the flow control mode, `None`, `UART.RTS`,
/// `UART.CTS', or `UART.CTS | UART.RTS`
/// - `timeout` is the timeout (in milliseconds) when waiting for the first character.
/// - `timeout_char` is the timeout (in milliseconds) between characters.
STATIC const mp_arg_t pyb_uart_init_args[] = {
@@ -402,7 +404,7 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con
self->config = UART_CONFIG_WLEN_8;
break;
default:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
goto error;
break;
}
// Parity
@@ -414,6 +416,10 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con
// Stop bits
self->config |= (args[3].u_int == 1 ? UART_CONFIG_STOP_ONE : UART_CONFIG_STOP_TWO);
// Flow control
if (args[4].u_int != UART_FLOWCONTROL_NONE || args[4].u_int != UART_FLOWCONTROL_TX ||
args[4].u_int != UART_FLOWCONTROL_RX || args[4].u_int != (UART_FLOWCONTROL_TX | UART_FLOWCONTROL_RX)) {
goto error;
}
self->flowcontrol = args[4].u_int;
}
else {
@@ -427,11 +433,14 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con
pybsleep_add ((const mp_obj_t)self, (WakeUpCB_t)uart_init);
return mp_const_none;
error:
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
/// \classmethod \constructor(bus, ...)
///
/// Construct a UART object on the given bus id. `bus id` can be 0 or 1
/// Construct a UART object on the given bus id. `bus id` can be 1 or 2
/// With no additional parameters, the UART object is created but not
/// initialised (it has the settings from the last initialisation of
/// the bus, if any).
@@ -447,7 +456,7 @@ STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
mp_arg_check_num(n_args, n_kw, 1, MP_ARRAY_SIZE(pyb_uart_init_args), true);
// work out the uart id
pyb_uart_id_t uart_id = mp_obj_get_int(args[0]);
int32_t uart_id = mp_obj_get_int(args[0]) - 1;
if (uart_id < PYB_UART_0 || uart_id > PYB_UART_1) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
@@ -457,6 +466,7 @@ STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
pyb_uart_obj_t *self = &pyb_uart_obj[uart_id];
self->base.type = &pyb_uart_type;
self->uart_id = uart_id;
if (n_args > 1 || n_kw > 0) {
// start the peripheral
mp_map_t kw_args;
@@ -474,7 +484,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init);
/// \method deinit()
/// Turn off the UART bus.
mp_obj_t pyb_uart_deinit(mp_obj_t self_in) {
STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
// unregister it with the sleep module
@@ -516,7 +526,7 @@ STATIC mp_obj_t pyb_uart_callback (mp_uint_t n_args, const mp_obj_t *pos_args, m
uint priority = mpcallback_translate_priority (args[2].u_int);
// check the power mode
if (PYB_PWR_MODE_ACTIVE != args[3].u_int) {
if (PYB_PWR_MODE_ACTIVE != args[4].u_int) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
@@ -538,7 +548,7 @@ STATIC mp_obj_t pyb_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) {
// send the character
if (!uart_tx_char(self, data)) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ETIMEDOUT)));
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
return mp_const_none;
@@ -559,6 +569,18 @@ STATIC mp_obj_t pyb_uart_readchar(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar);
/// \method sendbreak()
STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
// send a break signal for at least 2 complete frames
MAP_UARTBreakCtl(self->reg, true);
UtilsDelay(UTILS_DELAY_US_TO_COUNT((22 * 1000000) / self->baudrate));
MAP_UARTBreakCtl(self->reg, false);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_sendbreak_obj, pyb_uart_sendbreak);
STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_uart_init_obj },
@@ -579,12 +601,11 @@ STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_writechar), (mp_obj_t)&pyb_uart_writechar_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readchar), (mp_obj_t)&pyb_uart_readchar_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendbreak), (mp_obj_t)&pyb_uart_sendbreak_obj },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_FLOW_NONE), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_NONE) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_FLOW_TX), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_TX) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_FLOW_RX), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_RX) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_FLOW_TXRX), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_TX | UART_FLOWCONTROL_RX) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CTS), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_TX) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RTS), MP_OBJ_NEW_SMALL_INT(UART_FLOWCONTROL_RX) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table);
@@ -622,7 +643,7 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t
// write the data
if (!uart_tx_strn(self, buf, size)) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ETIMEDOUT)));
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
return size;
}

View File

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

View File

@@ -54,14 +54,16 @@
******************************************************************************/
typedef struct {
bool servers;
bool servers_sleeping;
bool simplelink;
bool running;
}pybwdt_data_t;
} pybwdt_data_t;
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
static pybwdt_data_t pybwdt_data;
STATIC pybwdt_data_t pybwdt_data = {.servers = false, .servers_sleeping = false, .simplelink = false, .running = false};
STATIC const mp_obj_base_t pyb_wdt_obj = {&pyb_wdt_type};
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
@@ -69,22 +71,16 @@ static pybwdt_data_t pybwdt_data;
// must be called in main.c just after initializing the hal
__attribute__ ((section (".boot")))
void pybwdt_init0 (void) {
pybwdt_data.running = false;
}
void pybwdt_kick (void) {
// check that the servers and simplelink are running fine
if (pybwdt_data.servers && pybwdt_data.simplelink && pybwdt_data.running) {
pybwdt_data.servers = false;
pybwdt_data.simplelink = false;
MAP_WatchdogIntClear(WDT_BASE);
}
}
void pybwdt_srv_alive (void) {
pybwdt_data.servers = true;
}
void pybwdt_srv_sleeping (bool state) {
pybwdt_data.servers_sleeping = state;
}
void pybwdt_sl_alive (void) {
pybwdt_data.simplelink = true;
}
@@ -92,58 +88,66 @@ void pybwdt_sl_alive (void) {
/******************************************************************************/
// Micro Python bindings
/// \function wdt_enable('msec')
/// Enabled the watchdog timer with msec timeout value
STATIC mp_obj_t pyb_enable_wdt(mp_obj_t self, mp_obj_t msec_in) {
mp_int_t msec = mp_obj_get_int(msec_in);
/// \function constructor('msec')
/// Enables the watchdog timer with msec timeout value
STATIC mp_obj_t pyb_wdt_make_new (mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
// check the arguments
mp_arg_check_num(n_args, n_kw, 0, 1, false);
if (msec < PYBWDT_MIN_TIMEOUT_MS) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
if (pybwdt_data.running) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
if (n_args > 0) {
mp_int_t msec = mp_obj_get_int(args[0]);
if (msec < PYBWDT_MIN_TIMEOUT_MS) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
}
if (pybwdt_data.running) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
}
// Enable the WDT peripheral clock
MAP_PRCMPeripheralClkEnable(PRCM_WDT, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
// Unlock to be able to configure the registers
MAP_WatchdogUnlock(WDT_BASE);
#ifdef DEBUG
// make the WDT stall when the debugger stops on a breakpoint
MAP_WatchdogStallEnable (WDT_BASE);
#endif
// set the watchdog timer reload value
// the WDT trigger a system reset after the second timeout
// so, divide by 2 the timeout value received
MAP_WatchdogReloadSet(WDT_BASE, PYBWDT_MILLISECONDS_TO_TICKS(msec / 2));
// start the timer. Once it's started, it cannot be disabled.
MAP_WatchdogEnable(WDT_BASE);
pybwdt_data.running = true;
}
// Enable the WDT peripheral clock
MAP_PRCMPeripheralClkEnable(PRCM_WDT, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
// Unlock to be able to configure the registers
MAP_WatchdogUnlock(WDT_BASE);
// make the WDT stall when the debugger stops on a breakpoint
MAP_WatchdogStallEnable (WDT_BASE);
// set the watchdog timer reload value
// the WDT trigger a system reset after the second timeout
// so, divide by the 2 timeout value received
MAP_WatchdogReloadSet(WDT_BASE, PYBWDT_MILLISECONDS_TO_TICKS(msec / 2));
// start the timer. Once wdt is started, it cannot be disabled.
MAP_WatchdogEnable(WDT_BASE);
pybwdt_data.running = true;
return mp_const_none;
return (mp_obj_t)&pyb_wdt_obj;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_enable_wdt_obj, pyb_enable_wdt);
/// \function wdt_kick()
/// Kicks the watchdog timer
STATIC mp_obj_t pyb_kick_wdt(mp_obj_t self) {
pybwdt_kick ();
if ((pybwdt_data.servers || pybwdt_data.servers_sleeping) && pybwdt_data.simplelink && pybwdt_data.running) {
pybwdt_data.servers = false;
pybwdt_data.simplelink = false;
MAP_WatchdogIntClear(WDT_BASE);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_kick_wdt_obj, pyb_kick_wdt);
STATIC const mp_map_elem_t pybwdt_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&pyb_enable_wdt_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_kick), (mp_obj_t)&pyb_kick_wdt_obj },
};
STATIC MP_DEFINE_CONST_DICT(pybwdt_locals_dict, pybwdt_locals_dict_table);
static const mp_obj_type_t pybwdt_type = {
const mp_obj_type_t pyb_wdt_type = {
{ &mp_type_type },
.name = MP_QSTR_WDT,
.make_new = pyb_wdt_make_new,
.locals_dict = (mp_obj_t)&pybwdt_locals_dict,
};
const mp_obj_base_t pyb_wdt_obj = {&pybwdt_type};

View File

@@ -29,11 +29,11 @@
#include "py/obj.h"
extern const mp_obj_base_t pyb_wdt_obj;
extern const mp_obj_type_t pyb_wdt_type;
void pybwdt_init0 (void);
void pybwdt_kick (void);
void pybwdt_srv_alive (void);
void pybwdt_srv_sleeping (bool state);
void pybwdt_sl_alive (void);
#endif /* PYBWDT_H_ */

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,8 @@
#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 (1)
#define MICROPY_QSTR_BYTES_IN_HASH (1)
/* Enable FatFS LFNs
0: Disable LFN feature.
@@ -54,22 +57,28 @@
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 (1)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
#define MICROPY_PY_BUILTINS_FROZENSET (1)
#define MICROPY_PY_BUILTINS_EXECFILE (1)
#define MICROPY_PY_BUILTINS_TIMEOUTERROR (1)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (0)
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
#define MICROPY_PY_SYS_MAXSIZE (1)
#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_UCTYPES (1)
#define MICROPY_PY_UBINASCII (0)
#define MICROPY_PY_UCTYPES (0)
#define MICROPY_PY_UZLIB (0)
#define MICROPY_PY_UJSON (1)
#define MICROPY_PY_URE (1)
@@ -98,17 +107,33 @@ extern const struct _mp_obj_module_t mp_module_utime;
extern const struct _mp_obj_module_t mp_module_uselect;
extern const struct _mp_obj_module_t mp_module_usocket;
extern const struct _mp_obj_module_t mp_module_network;
extern const struct _mp_obj_module_t mp_module_uhashlib;
extern const struct _mp_obj_module_t mp_module_ubinascii;
extern const struct _mp_obj_module_t mp_module_ussl;
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_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_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 }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&mp_module_uos }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&mp_module_utime }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_uselect), (mp_obj_t)&mp_module_uselect }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_network), (mp_obj_t)&mp_module_network }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_uhashlib), (mp_obj_t)&mp_module_uhashlib }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_ubinascii), (mp_obj_t)&mp_module_ubinascii }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_ussl), (mp_obj_t)&mp_module_ussl }, \
#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&mp_module_ustruct }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_re), (mp_obj_t)&mp_module_ure }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_heapq), (mp_obj_t)&mp_module_uheapq }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&mp_module_uos }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&mp_module_utime }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_select), (mp_obj_t)&mp_module_uselect }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&mp_module_usocket }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_hashlib), (mp_obj_t)&mp_module_uhashlib }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_binascii), (mp_obj_t)&mp_module_ubinascii }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_ssl), (mp_obj_t)&mp_module_ussl }, \
// extra constants
#define MICROPY_PORT_CONSTANTS \
@@ -120,14 +145,15 @@ extern const struct _mp_obj_module_t mp_module_network;
const char *readline_hist[8]; \
mp_obj_t mp_const_user_interrupt; \
mp_obj_t pyb_config_main; \
mp_obj_list_t mod_network_nic_list; \
mp_obj_list_t pybsleep_obj_list; \
mp_obj_list_t mpcallback_obj_list; \
mp_obj_list_t pyb_timer_channel_obj_list; \
// 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 +164,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 +189,14 @@ 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_PORT_WLAN_URN (0)
#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
@@ -51,6 +50,7 @@
#include "mperror.h"
#include "simplelink.h"
#include "modnetwork.h"
#include "modusocket.h"
#include "modwlan.h"
#include "serverstask.h"
#include "telnet.h"
@@ -64,7 +64,10 @@
#include "pybsd.h"
#include "pins.h"
#include "pybsleep.h"
#include "pybtimer.h"
#include "mpcallback.h"
#include "cryptohash.h"
#include "updater.h"
/******************************************************************************
DECLARE PRIVATE CONSTANTS
@@ -102,11 +105,14 @@ void TASK_Micropython (void *pvParameters) {
// initialize the garbage collector with the top of our stack
uint32_t sp = gc_helper_get_sp();
gc_collect_init (sp);
bool safeboot = false;
FRESULT res;
bool safeboot = false;
mptask_pre_init();
#ifndef DEBUG
safeboot = PRCMGetSpecialBit(PRCM_SAFE_BOOT_BIT);
#endif
soft_reset:
// GC init
@@ -125,20 +131,18 @@ soft_reset:
mperror_init0();
uart_init0();
pin_init0();
timer_init0();
readline_init0();
mod_network_init0();
wlan_init0();
#if MICROPY_HW_ENABLE_RNG
rng_init0();
#endif
// 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 *)&MICROPY_STDIO_UART_TX_PIN, MICROPY_STDIO_UART_TX_PIN_AF, 0, PIN_TYPE_STD_PU, PIN_STRENGTH_2MA);
pin_config ((pin_obj_t *)&MICROPY_STDIO_UART_RX_PIN, MICROPY_STDIO_UART_RX_PIN_AF, 0, PIN_TYPE_STD_PU, PIN_STRENGTH_2MA);
// instantiate the stdio uart
mp_obj_t args[2] = {
mp_obj_new_int(MICROPY_STDIO_UART),
@@ -147,6 +151,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) {
@@ -158,9 +165,6 @@ soft_reset:
else {
// only if not comming out of hibernate or a soft reset
mptask_enter_ap_mode();
#ifndef DEBUG
safeboot = PRCMIsSafeBootRequested();
#endif
}
// enable telnet and ftp
@@ -170,26 +174,22 @@ 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";
res = f_stat(boot_py, NULL);
if (res == FR_OK) {
int ret = pyexec_file(boot_py);
if (ret & PYEXEC_FORCED_EXIT) {
goto soft_reset_exit;
}
if (!ret) {
// flash the system led
mperror_signal_error();
}
// run boot.py
int ret = pyexec_file("boot.py");
if (ret & PYEXEC_FORCED_EXIT) {
goto soft_reset_exit;
}
if (!ret) {
// flash the system led
mperror_signal_error();
}
}
@@ -204,20 +204,17 @@ 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));
}
res = f_stat(main_py, NULL);
if (res == FR_OK) {
int ret = pyexec_file(main_py);
if (ret & PYEXEC_FORCED_EXIT) {
goto soft_reset_exit;
}
if (!ret) {
// flash the system led
mperror_signal_error();
}
int ret = pyexec_file(main_py);
if (ret & PYEXEC_FORCED_EXIT) {
goto soft_reset_exit;
}
if (!ret) {
// flash the system led
mperror_signal_error();
}
}
}
@@ -240,15 +237,26 @@ soft_reset_exit:
// soft reset
pybsleep_signal_soft_reset();
mp_printf(&mp_plat_print, "PYB: soft reboot\n");
printf("WiPy: soft reset\n");
// disable all peripherals that could trigger a callback
pyb_rtc_callback_disable(NULL);
timer_disable_all();
uart_disable_all();
// flush the serial flash buffer
sflash_disk_flush();
// clean-up the user socket space
modusocket_close_all_user_sockets();
#if MICROPY_HW_HAS_SDCARD
pybsd_deinit();
#endif
// wait for pending transactions to complete
HAL_Delay(20);
goto soft_reset;
}
@@ -270,10 +278,21 @@ STATIC void mptask_pre_init (void) {
// this one allocates memory for the nvic vault
pybsleep_pre_init();
// this one allocates memory for the WLAN semaphore
wlan_pre_init();
// this one allocates memory for the updater semaphore
updater_pre_init();
// this one allocates memory for the Socket semaphore
modusocket_pre_init();
#if MICROPY_HW_HAS_SDCARD
pybsd_init0();
#endif
CRYPTOHASH_Init();
#ifdef DEBUG
ASSERT (OSI_OK == osi_TaskCreate(TASK_Servers,
(const signed char *)"Servers",
@@ -286,38 +305,54 @@ 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.
// try to mount the flash
FRESULT res = f_mount(sflash_fatfs, "/SFLASH", 1);
// Create it if needed, and mount in on /flash.
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);
// create /flash/sys, /flash/lib and /flash/cert if they don't exist
if (FR_OK != f_chdir ("/flash/sys")) {
f_mkdir("/flash/sys");
}
if (FR_OK != f_chdir ("/flash/lib")) {
f_mkdir("/flash/lib");
}
if (FR_OK != f_chdir ("/flash/cert")) {
f_mkdir("/flash/cert");
}
f_chdir ("/flash");
// make sure we have a /flash/boot.py. Create it if needed.
res = f_stat("/flash/boot.py", &fno);
if (res == FR_OK) {
if (fno.fattrib & AM_DIR) {
// exists as a directory
@@ -329,7 +364,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 +373,18 @@ 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);
// append the mac only if it's not the first boot
bool append_mac = !PRCMGetSpecialBit(PRCM_FIRST_BOOT_BIT);
// enable simplelink in ap mode (use the MAC address to make the ssid unique)
wlan_sl_enable (ROLE_AP, MICROPY_PORT_WLAN_AP_SSID, strlen(MICROPY_PORT_WLAN_AP_SSID), MICROPY_PORT_WLAN_AP_SECURITY,
MICROPY_PORT_WLAN_AP_KEY, strlen(MICROPY_PORT_WLAN_AP_KEY), MICROPY_PORT_WLAN_AP_CHANNEL, append_mac);
}
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)
@@ -21,6 +48,7 @@ Q(readline)
Q(input)
Q(os)
Q(freq)
Q(unique_id)
Q(repl_info)
Q(disable_irq)
Q(enable_irq)
@@ -31,36 +59,50 @@ Q(elapsed_micros)
Q(udelay)
Q(flush)
Q(FileIO)
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(struct)
Q(binascii)
Q(re)
Q(json)
Q(heapq)
Q(hashlib)
// 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)
Q(mkdir)
Q(rename)
Q(remove)
Q(rmdir)
Q(unlink)
Q(sep)
Q(stat)
Q(urandom)
Q(mkfs)
// for file class
Q(seek)
@@ -68,23 +110,18 @@ Q(tell)
// for Pin class
Q(Pin)
Q(cpu)
Q(init)
Q(value)
Q(low)
Q(high)
Q(toggle)
Q(info)
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)
@@ -113,21 +150,23 @@ Q(deinit)
Q(all)
Q(writechar)
Q(readchar)
Q(sendbreak)
Q(readinto)
Q(read_buf_len)
Q(timeout)
Q(timeout_char)
Q(repl_uart)
Q(flow)
Q(FLOW_NONE)
Q(FLOW_TX)
Q(FLOW_RX)
Q(FLOW_TXRX)
Q(RTS)
Q(CTS)
// for I2C class
Q(I2C)
Q(mode)
Q(baudrate)
Q(addr)
Q(data)
Q(timeout)
Q(memaddr)
Q(addr_size)
Q(init)
@@ -138,15 +177,20 @@ Q(send)
Q(recv)
Q(mem_read)
Q(mem_write)
Q(MASTER)
// for ADC class
Q(ADC)
Q(read)
Q(init)
Q(deinit)
#if MICROPY_HW_HAS_SDCARD
// for SD class
Q(SD)
Q(enable)
Q(disable)
#endif
// for RTC class
Q(RTC)
@@ -174,6 +218,7 @@ Q(getaddrinfo)
Q(family)
Q(type)
Q(send)
Q(sendall)
Q(sendto)
Q(recv)
Q(recvfrom)
@@ -184,26 +229,44 @@ Q(settimeout)
Q(setblocking)
Q(setsockopt)
Q(close)
Q(makefile)
Q(protocol)
Q(error)
Q(timeout)
Q(AF_INET)
Q(AF_INET6)
Q(SOCK_STREAM)
Q(SOCK_DGRAM)
Q(SOCK_RAW)
Q(IPPROTO_SEC)
Q(IPPROTO_TCP)
Q(IPPROTO_UDP)
Q(IPPROTO_RAW)
// for ssl class
Q(ssl)
Q(ussl)
Q(wrap_socket)
Q(sock)
Q(keyfile)
Q(certfile)
Q(server_side)
Q(cert_reqs)
Q(ca_certs)
Q(SSLError)
Q(CERT_NONE)
Q(CERT_OPTIONAL)
Q(CERT_REQUIRED)
// for network class
Q(network)
Q(route)
Q(start_server)
Q(stop_server)
Q(server_enabled)
Q(server_running)
Q(server_login)
Q(server_timeout)
// for WLAN class
Q(WLAN)
Q(iwconfig)
Q(key)
Q(security)
Q(ssid)
@@ -213,21 +276,31 @@ Q(connect)
Q(isconnected)
Q(disconnect)
Q(channel)
Q(rssi)
Q(ifconfig)
Q(info)
Q(connections)
#if MICROPY_PORT_WLAN_URN
Q(urn)
#endif
Q(mode)
Q(ip)
Q(subnet)
Q(gateway)
Q(dns)
Q(mac)
Q(antenna)
Q(STA)
Q(AP)
Q(P2P)
Q(OPEN)
Q(WEP)
Q(WPA_WPA2)
Q(WPA_ENT)
Q(WPS_PBC)
Q(WPS_PIN)
Q(WPA)
Q(WPA2)
Q(INTERNAL)
Q(EXTERNAL)
// for WDT class
Q(WDT)
Q(enable)
Q(kick)
// for HeartBeat class
@@ -241,7 +314,7 @@ Q(enable)
Q(disable)
Q(callback)
Q(handler)
Q(intmode)
Q(mode)
Q(value)
Q(priority)
Q(wakes)
@@ -256,7 +329,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)
@@ -267,15 +340,59 @@ Q(RTC_WAKE)
// for SPI class
Q(SPI)
Q(mode)
Q(baudrate)
Q(bits)
Q(submode)
Q(cs)
Q(polarity)
Q(phase)
Q(nss)
Q(init)
Q(deinit)
Q(send)
Q(recv)
Q(send_recv)
Q(timeout)
Q(MASTER)
Q(ACTIVE_LOW)
Q(ACTIVE_HIGH)
// for Timer class
Q(Timer)
Q(TimerChannel)
Q(init)
Q(deinit)
Q(freq)
Q(period)
Q(mode)
Q(width)
Q(channel)
Q(polarity)
Q(duty_cycle)
Q(time)
Q(event_count)
Q(event_time)
Q(A)
Q(B)
Q(ONE_SHOT)
Q(PERIODIC)
Q(EDGE_COUNT)
Q(EDGE_TIME)
Q(PWM)
Q(POSITIVE)
Q(NEGATIVE)
// for uhashlib module
Q(uhashlib)
Q(update)
Q(digest)
//Q(md5)
Q(sha1)
Q(sha256)
// for ubinascii module
Q(ubinascii)
Q(hexlify)
Q(unhexlify)
Q(a2b_base64)
Q(b2a_base64)

View File

@@ -25,41 +25,46 @@
*/
#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"
#include "modusocket.h"
/******************************************************************************
DECLARE PRIVATE DEFINITIONS
******************************************************************************/
#define SERVERS_DEF_USER "micro"
#define SERVERS_DEF_PASS "python"
#define SERVERS_DEF_USER "micro"
#define SERVERS_DEF_PASS "python"
#define SERVERS_DEF_TIMEOUT_MS 300000 // 5 minutes
#define SERVERS_MIN_TIMEOUT_MS 5000 // 5 seconds
/******************************************************************************
DEFINE PRIVATE TYPES
******************************************************************************/
typedef struct {
volatile bool enabled;
volatile bool do_disable;
volatile bool do_enable;
}servers_Data_t;
uint32_t timeout;
bool enabled;
bool do_disable;
bool do_enable;
bool do_reset;
} servers_data_t;
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
static servers_Data_t servers_data = {.enabled = false, .do_disable = false, .do_enable = false};
static servers_data_t servers_data = {.timeout = SERVERS_DEF_TIMEOUT_MS, .enabled = false, .do_disable = false,
.do_enable = false, .do_reset = false};
static volatile bool sleep_sockets = false;
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
@@ -68,8 +73,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 +83,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 +91,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,42 +99,98 @@ 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;
}
else if (servers_data.do_reset) {
// resetting the servers is needed to prevent half-open sockets
servers_data.do_reset = false;
if (servers_data.enabled) {
telnet_reset();
ftp_reset();
}
// and we should also close all user sockets. We do it here
// for convinience and to save on code size.
modusocket_close_all_user_sockets();
}
if (cycle) {
telnet_run();
}
else {
ftp_run();
}
if (sleep_sockets) {
sleep_sockets = false;
pybwdt_srv_sleeping(true);
modusocket_enter_sleep();
pybwdt_srv_sleeping(false);
}
// set the alive flag for the wdt
pybwdt_srv_alive();
// move to the next cycle
cycle = cycle ? false : true;
HAL_Delay(SERVERS_CYCLE_TIME_MS);
// set the alive flag for the wdt
pybwdt_srv_alive();
}
}
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);
}
void servers_reset (void) {
servers_data.do_reset = true;
}
bool servers_are_enabled (void) {
return servers_data.enabled;
}
void server_sleep_sockets (void) {
sleep_sockets = true;
HAL_Delay (SERVERS_CYCLE_TIME_MS + 1);
}
void servers_close_socket (int16_t *sd) {
if (*sd > 0) {
modusocket_socket_delete(*sd);
sl_Close(*sd);
*sd = -1;
}
}
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);
}
bool servers_set_timeout (uint32_t timeout) {
if (timeout < SERVERS_MIN_TIMEOUT_MS) {
return false;
}
servers_data.timeout = timeout;
return true;
}
uint32_t servers_get_timeout (void) {
return servers_data.timeout;
}
/******************************************************************************

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
@@ -62,8 +56,12 @@ extern char *servers_pass;
extern void TASK_Servers (void *pvParameters);
extern void servers_start (void);
extern void servers_stop (void);
extern void servers_reset (void);
extern bool servers_are_enabled (void);
extern void servers_close_socket (int16_t *sd);
extern void servers_set_login (char *user, char *pass);
extern void server_sleep_sockets (void);
extern bool servers_set_timeout (uint32_t timeout);
extern uint32_t servers_get_timeout (void);
#endif /* SERVERSTASK_H_ */

View File

@@ -25,18 +25,20 @@
*/
#include <stdint.h>
#include <std.h>
#include "py/mpconfig.h"
#include MICROPY_HAL_H
#include "py/obj.h"
#include "telnet.h"
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
#include "modusocket.h"
#include "debug.h"
#include "mpexception.h"
#include "serverstask.h"
#include "genhdr/py-version.h"
#include "genhdr/mpversion.h"
#include "irq.h"
/******************************************************************************
DEFINE PRIVATE CONSTANTS
@@ -45,10 +47,9 @@
// rxRindex and rxWindex must be uint8_t and TELNET_RX_BUFFER_SIZE == 256
#define TELNET_RX_BUFFER_SIZE 256
#define TELNET_MAX_CLIENTS 1
#define TELNET_TX_RETRIES_MAX 25
#define TELNET_TX_RETRIES_MAX 50
#define TELNET_WAIT_TIME_MS 5
#define TELNET_LOGIN_RETRIES_MAX 3
#define TELNET_TIMEOUT_MS 300000 // 5 minutes
#define TELNET_CYCLE_TIME_MS (SERVERS_CYCLE_TIME_MS * 2)
/******************************************************************************
@@ -108,8 +109,8 @@ typedef struct {
******************************************************************************/
static telnet_data_t telnet_data;
static const char* telnet_welcome_msg = "Micro Python " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n";
static const char* telnet_request_user = "Login as:";
static const char* telnet_request_password = "Password:";
static const char* telnet_request_user = "Login as: ";
static const char* telnet_request_password = "Password: ";
static const char* telnet_invalid_loggin = "\r\nInvalid credentials, try again.\r\n";
static const char* telnet_loggin_success = "\r\nLogin succeeded!\r\nType \"help()\" for more information.\r\n";
static const uint8_t telnet_options_user[] = // IAC WONT ECHO IAC WONT SUPPRESS_GO_AHEAD IAC WILL LINEMODE
@@ -129,9 +130,9 @@ 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);
static void telnet_reset_buffer (void);
/******************************************************************************
@@ -150,7 +151,7 @@ void telnet_run (void) {
telnet_wait_for_enabled();
break;
case E_TELNET_STE_START:
if (telnet_create_socket()) {
if (wlan_is_connected() && telnet_create_socket()) {
telnet_data.state = E_TELNET_STE_LISTEN;
}
break;
@@ -171,12 +172,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 +191,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;
@@ -233,7 +237,7 @@ void telnet_run (void) {
}
if (telnet_data.state >= E_TELNET_STE_CONNECTED) {
if (telnet_data.timeout++ > (TELNET_TIMEOUT_MS / TELNET_CYCLE_TIME_MS)) {
if (telnet_data.timeout++ > (servers_get_timeout() / TELNET_CYCLE_TIME_MS)) {
telnet_reset();
}
}
@@ -289,6 +293,13 @@ void telnet_disable (void) {
telnet_data.state = E_TELNET_STE_DISABLED;
}
void telnet_reset (void) {
// close the connection and start all over again
servers_close_socket(&telnet_data.n_sd);
servers_close_socket(&telnet_data.sd);
telnet_data.state = E_TELNET_STE_START;
}
bool telnet_is_enabled (void) {
return telnet_data.enabled;
}
@@ -319,21 +330,27 @@ static bool telnet_create_socket (void) {
// Open a socket for telnet
ASSERT ((telnet_data.sd = sl_Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) > 0);
if (telnet_data.sd > 0) {
// add the socket to the network administration
modusocket_socket_add(telnet_data.sd, false);
// Enable non-blocking mode
nonBlockingOption.NonblockingEnabled = 1;
ASSERT (sl_SetSockOpt(telnet_data.sd, SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption)) == SL_SOC_OK);
ASSERT ((result = sl_SetSockOpt(telnet_data.sd, SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption))) == SL_SOC_OK);
// 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);
ASSERT ((result |= sl_Bind(telnet_data.sd, (const SlSockAddr_t *)&sServerAddress, sizeof(sServerAddress))) == SL_SOC_OK);
// Start listening
ASSERT ((result = sl_Listen (telnet_data.sd, TELNET_MAX_CLIENTS)) == SL_SOC_OK);
ASSERT ((result |= sl_Listen (telnet_data.sd, TELNET_MAX_CLIENTS)) == SL_SOC_OK);
return (result == SL_SOC_OK) ? true : false;
if (result == SL_SOC_OK) {
return true;
}
servers_close_socket(&telnet_data.sd);
}
return false;
@@ -349,15 +366,18 @@ static void telnet_wait_for_connection (void) {
return;
}
else {
// close the listening socket, we don't need it anymore
sl_Close(telnet_data.sd);
if (telnet_data.n_sd <= 0) {
// error
telnet_reset();
return;
}
// close the listening socket, we don't need it anymore
servers_close_socket(&telnet_data.sd);
// add the new socket to the network administration
modusocket_socket_add(telnet_data.n_sd, false);
// client connected, so go on
telnet_data.rxWindex = 0;
telnet_data.rxRindex = 0;
@@ -427,6 +447,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,16 +484,18 @@ 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);
}
}
}
static bool telnet_send_with_retries (int16_t sd, const void *pBuf, int16_t len) {
int32_t retries = 0;
// abort sending if we happen to be within interrupt context
if ((HAL_NVIC_INT_CTRL_REG & HAL_VECTACTIVE_MASK) == 0) {
uint32_t delay = TELNET_WAIT_TIME_MS;
// only if we are not within interrupt context and interrupts are enabled
if ((HAL_NVIC_INT_CTRL_REG & HAL_VECTACTIVE_MASK) == 0 && query_irq() == IRQ_STATE_ENABLED) {
do {
_i16 result = sl_Send(sd, pBuf, len, 0);
if (result > 0) {
@@ -462,19 +504,13 @@ static bool telnet_send_with_retries (int16_t sd, const void *pBuf, int16_t len)
else if (SL_EAGAIN != result) {
return false;
}
HAL_Delay (TELNET_WAIT_TIME_MS);
// start with the default delay and increment it on each retry
HAL_Delay (delay++);
} while (++retries <= TELNET_TX_RETRIES_MAX);
}
return false;
}
static void telnet_reset (void) {
// close the connection and start all over again
servers_close_socket(&telnet_data.n_sd);
servers_close_socket(&telnet_data.sd);
telnet_data.state = E_TELNET_STE_START;
}
static void telnet_reset_buffer (void) {
// erase any characters present in the current line
memset (telnet_data.rxBuffer, '\b', TELNET_RX_BUFFER_SIZE / 2);

View File

@@ -38,6 +38,7 @@ extern bool telnet_rx_any (void);
extern int telnet_rx_char (void);
extern void telnet_enable (void);
extern void telnet_disable (void);
extern void telnet_reset (void);
extern bool telnet_is_enabled (void);
extern bool telnet_is_active (void);

63
cc3200/tools/smoke.py Normal file
View File

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

101
cc3200/tools/smoke.py.exp Normal file
View File

@@ -0,0 +1,101 @@
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
/flash
True
True
True
['main.py', 'sys', 'lib', 'cert', 'boot.py']

56
cc3200/tools/uniflash.py Normal file
View File

@@ -0,0 +1,56 @@
#!/usr/bin/env python
"""
Flash the WiPy (format, update service pack and program).
Example:
> python uniflash.py -u "C:\ti\uniflash_3.2\uniflashCLI.bat" -c "C:\VirtualBoxShared\GitHub\wipy_uniflash.usf" -p 8 -s "C:\ti\CC31xx_CC32xx_ServicePack_1.0.0.10.0\servicepack_1.0.0.10.0.bin"
or:
> python uniflash.py -u "C:\ti\uniflash_3.2\uniflashCLI.bat" -c "C:\VirtualBoxShared\GitHub\launchxl_uniflash.usf" -p 8 -s "C:\ti\CC31xx_CC32xx_ServicePack_1.0.0.10.0\servicepack_1.0.0.10.0.bin"
"""
import sys
import argparse
import subprocess
def print_exception(e):
print ('Exception: {}, on line {}'.format(e, sys.exc_info()[-1].tb_lineno))
def main():
cmd_parser = argparse.ArgumentParser(description='Flash the WiPy and optionally run a small test on it.')
cmd_parser.add_argument('-u', '--uniflash', default=None, help='the path to the uniflash cli executable')
cmd_parser.add_argument('-c', '--config', default=None, help='the path to the uniflash config file')
cmd_parser.add_argument('-p', '--port', default=8, help='the com serial port')
cmd_parser.add_argument('-s', '--servicepack', default=None, help='the path to the servicepack file')
args = cmd_parser.parse_args()
result = 1
com_port = 'com=' + str(args.port)
servicepack_path = 'spPath=' + args.servicepack
try:
if args.uniflash == None or args.config == None:
raise ValueError('uniflash path and config path are mandatory')
if args.servicepack == None:
subprocess.check_call([args.uniflash, '-config', args.config, '-setOptions', com_port, '-operations', 'format', 'program'], stderr=subprocess.STDOUT)
else:
subprocess.check_call([args.uniflash, '-config', args.config, '-setOptions', com_port, servicepack_path, '-operations', 'format', 'servicePackUpdate', 'program'], stderr=subprocess.STDOUT)
result = 0
except Exception as e:
print_exception(e)
finally:
if result:
print ("ERROR: Programming failed!")
else:
print ("Board programmed OK")
sys.exit(result)
if __name__ == "__main__":
main()

189
cc3200/tools/update-wipy.py Normal file
View File

@@ -0,0 +1,189 @@
#!/usr/bin/env python
"""
The WiPy firmware update script. Transmits the specified firmware file
over FTP, and then resets the WiPy and optionally verifies that software
was correctly updated.
Usage:
./update-wipy.py --file "path_to_mcuimg.bin" --verify
Or:
python update-wipy.py --file "path_to_mcuimg.bin"
"""
import sys
import argparse
import time
from ftplib import FTP
from telnetlib import Telnet
def print_exception(e):
print ('Exception: {}, on line {}'.format(e, sys.exc_info()[-1].tb_lineno))
def ftp_directory_exists(ftpobj, directory_name):
filelist = []
ftpobj.retrlines('LIST',filelist.append)
for f in filelist:
if f.split()[-1] == directory_name:
return True
return False
def transfer_file(args):
with FTP(args.ip, timeout=20) as ftp:
print ('FTP connection established')
if '230' in ftp.login(args.user, args.password):
print ('Login successful')
if '250' in ftp.cwd('/flash'):
if not ftp_directory_exists(ftp, 'sys'):
print ('/flash/sys directory does not exist')
if not '550' in ftp.mkd('sys'):
print ('/flash/sys directory created')
else:
print ('Error: cannot create /flash/sys directory')
return False
if '250' in ftp.cwd('sys'):
print ("Entered '/flash/sys' directory")
with open(args.file, "rb") as fwfile:
print ('Firmware image found, initiating transfer...')
if '226' in ftp.storbinary("STOR " + 'mcuimg.bin', fwfile, 512):
print ('File transfer complete')
return True
else:
print ('Error: file transfer failed')
else:
print ('Error: cannot enter /flash/sys directory')
else:
print ('Error: cannot enter /flash directory')
else:
print ('Error: ftp login failed')
return False
def reset_board(args):
success = False
try:
tn = Telnet(args.ip, timeout=5)
print("Connected via Telnet, trying to login now")
if b'Login as:' in tn.read_until(b"Login as:", timeout=5):
tn.write(bytes(args.user, 'ascii') + b"\r\n")
if b'Password:' in tn.read_until(b"Password:", timeout=5):
# needed because of internal implementation details of the WiPy's telnet server
time.sleep(0.2)
tn.write(bytes(args.password, 'ascii') + b"\r\n")
if b'Type "help()" for more information.' in tn.read_until(b'Type "help()" for more information.', timeout=5):
print("Telnet login succeeded")
tn.write(b'\r\x03\x03') # ctrl-C twice: interrupt any running program
time.sleep(1)
tn.write(b'\r\x02') # ctrl-B: enter friendly REPL
if b'Type "help()" for more information.' in tn.read_until(b'Type "help()" for more information.', timeout=5):
tn.write(b"import pyb\r\n")
tn.write(b"pyb.reset()\r\n")
time.sleep(1)
print("Reset performed")
success = True
else:
print("Error: cannot enter friendly REPL")
else:
print("Error: telnet login failed")
except Exception as e:
print_exception(e)
finally:
try:
tn.close()
except Exception as e:
pass
return success
def verify_update(args):
success = False
firmware_tag = ''
def find_tag (tag):
if tag in firmware_tag:
print("Verification passed")
return True
else:
print("Error: verification failed, the git tag doesn't match")
return False
try:
# Specify a longer time out value here because the board has just been
# reset and the wireless connection might not be fully established yet
tn = Telnet(args.ip, timeout=15)
print("Connected via telnet again, lets check the git tag")
firmware_tag = tn.read_until (b'with CC3200')
tag_file_path = args.file.rstrip('mcuimg.bin') + 'genhdr/mpversion.h'
if args.tag is not None:
success = find_tag(bytes(args.tag, 'ascii'))
else:
with open(tag_file_path) as tag_file:
for line in tag_file:
bline = bytes(line, 'ascii')
if b'MICROPY_GIT_HASH' in bline:
bline = bline.lstrip(b'#define MICROPY_GIT_HASH ').replace(b'"', b'').replace(b'\r', b'').replace(b'\n', b'')
success = find_tag(bline)
break
except Exception as e:
print_exception(e)
finally:
try:
tn.close()
except Exception as e:
pass
return success
def main():
cmd_parser = argparse.ArgumentParser(description='Update the WiPy firmware with the specified image file')
cmd_parser.add_argument('-f', '--file', default=None, help='the path of the firmware file')
cmd_parser.add_argument('-u', '--user', default='micro', help='the username')
cmd_parser.add_argument('-p', '--password', default='python', help='the login password')
cmd_parser.add_argument('--ip', default='192.168.1.1', help='the ip address of the WiPy')
cmd_parser.add_argument('--verify', action='store_true', help='verify that the update succeeded')
cmd_parser.add_argument('-t', '--tag', default=None, help='git tag of the firmware image')
args = cmd_parser.parse_args()
result = 1
try:
if args.file is None:
raise ValueError('the image file path must be specified')
if transfer_file(args):
if reset_board(args):
if args.verify:
print ('Waiting for the WiFi connection to come up again...')
# this time is to allow the system's wireless network card to connect to the
# WiPy again. Sometimes it might only take a couple of seconds, but let's
# leave 15s to be on the safe side
time.sleep(15)
if verify_update(args):
result = 0
else:
result = 0
except Exception as e:
print_exception(e)
finally:
sys.exit(result)
if __name__ == "__main__":
main()

View File

@@ -24,7 +24,6 @@
* THE SOFTWARE.
*/
#include "std.h"
#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_types.h"
@@ -36,20 +35,20 @@
#include "rom_map.h"
#include "prcm.h"
#include "shamd5.h"
#include "hash.h"
#include "simplelink.h"
#include "cryptohash.h"
/******************************************************************************
DEFINE PUBLIC FUNCTIONS
******************************************************************************/
void HASH_Init (void) {
__attribute__ ((section (".boot")))
void CRYPTOHASH_Init (void) {
// Enable the Data Hashing and Transform Engine
MAP_PRCMPeripheralClkEnable(PRCM_DTHE, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
MAP_PRCMPeripheralReset(PRCM_DTHE);
}
void HASH_SHAMD5Start (uint32_t algo, uint32_t blocklen) {
void CRYPTOHASH_SHAMD5Start (uint32_t algo, uint32_t blocklen) {
// wait until the context is ready
while ((HWREG(SHAMD5_BASE + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_CONTEXT_READY) == 0);
@@ -65,12 +64,12 @@ void HASH_SHAMD5Start (uint32_t algo, uint32_t blocklen) {
HWREG(SHAMD5_BASE + SHAMD5_O_LENGTH) = blocklen;
}
void HASH_SHAMD5Update (uint8_t *data, uint32_t datalen) {
void CRYPTOHASH_SHAMD5Update (uint8_t *data, uint32_t datalen) {
// write the data
SHAMD5DataWriteMultiple(data, datalen);
}
void HASH_SHAMD5Read (uint8_t *hash) {
void CRYPTOHASH_SHAMD5Read (uint8_t *hash) {
// wait for the output to be ready
while((HWREG(SHAMD5_BASE + SHAMD5_O_IRQSTATUS) & SHAMD5_INT_OUTPUT_READY) == 0);
// read the result

View File

@@ -24,15 +24,15 @@
* THE SOFTWARE.
*/
#ifndef HASH_H_
#define HASH_H_
#ifndef CRYPTOHASH_H_
#define CRYPTOHASH_H_
/******************************************************************************
DECLARE PUBLIC FUNCTIONS
******************************************************************************/
extern void HASH_Init (void);
extern void HASH_SHAMD5Start (uint32_t algo, uint32_t blocklen);
extern void HASH_SHAMD5Update (uint8_t *data, uint32_t datalen);
extern void HASH_SHAMD5Read (uint8_t *hash);
extern void CRYPTOHASH_Init (void);
extern void CRYPTOHASH_SHAMD5Start (uint32_t algo, uint32_t blocklen);
extern void CRYPTOHASH_SHAMD5Update (uint8_t *data, uint32_t datalen);
extern void CRYPTOHASH_SHAMD5Read (uint8_t *hash);
#endif /* HASH_H_ */
#endif /* CRYPTOHASH_H_ */

View File

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

View File

@@ -27,14 +27,15 @@
#include <stdint.h>
#include <stdbool.h>
#include "py/obj.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "rom_map.h"
#include "prcm.h"
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
#include "py/obj.h"
#include "random.h"
#include "debug.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);

32
cc3200/version.h Normal file
View File

@@ -0,0 +1,32 @@
/*
* 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

@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Micro Python documentation build configuration file, created by
# MicroPython documentation build configuration file, created by
# sphinx-quickstart on Sun Sep 21 11:42:03 2014.
#
# This file is execfile()d with the current directory set to its
@@ -47,10 +47,10 @@ source_suffix = '.rst'
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
#master_doc = 'index'
# General information about the project.
project = 'Micro Python'
project = 'MicroPython'
copyright = '2014, Damien P. George'
# The version info for the project you're documenting, acts as replacement for
@@ -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.5'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -134,7 +134,7 @@ else:
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = '../logo/trans-logo.png'
#html_logo = '../../logo/trans-logo.png'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
@@ -213,7 +213,7 @@ latex_elements = {
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
('index', 'MicroPython.tex', 'Micro Python Documentation',
('index', 'MicroPython.tex', 'MicroPython Documentation',
'Damien P. George', 'manual'),
]
@@ -243,7 +243,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'micropython', 'Micro Python Documentation',
('index', 'micropython', 'MicroPython Documentation',
['Damien P. George'], 1),
]
@@ -257,7 +257,7 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'MicroPython', 'Micro Python Documentation',
('index', 'MicroPython', 'MicroPython Documentation',
'Damien P. George', 'MicroPython', 'One line description of project.',
'Miscellaneous'),
]
@@ -277,3 +277,29 @@ texinfo_documents = [
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'http://docs.python.org/': None}
# Work out the port to generate the docs for
from collections import OrderedDict
micropy_port = os.getenv('MICROPY_PORT') or 'pyboard'
tags.add('port_' + micropy_port)
ports = OrderedDict((
("unix", "unix"),
("pyboard", "the pyboard"),
("wipy", "the WiPy"),
("esp8266", "esp8266"),
))
# The members of the html_context dict are available inside topindex.html
url_prefix = os.getenv('MICROPY_URL_PREFIX') or '/'
html_context = {
'port':micropy_port,
'port_name':ports[micropy_port],
'all_ports':[(n, url_prefix + p) for p, n in ports.items()],
}
# Append the other ports' specific folders/files to the exclude pattern
exclude_patterns.extend([port + '*' for port in ports if port != micropy_port])
# Specify a custom master document based on the port name
master_doc = micropy_port + '_' + 'index'

View File

@@ -1,11 +0,0 @@
Micro Python documentation contents
===================================
.. toctree::
quickref.rst
general.rst
tutorial/index.rst
library/index.rst
hardware/index.rst
license.rst

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