mirror of
https://github.com/micropython/micropython.git
synced 2026-01-02 18:20:13 +01:00
Compare commits
123 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4e4526954 | ||
|
|
3c9510d767 | ||
|
|
3372f69586 | ||
|
|
6d11918d49 | ||
|
|
5c73de0337 | ||
|
|
3e5534caf7 | ||
|
|
1bc2911174 | ||
|
|
d2cab0b7be | ||
|
|
8897dcb2a1 | ||
|
|
f84dda7111 | ||
|
|
a9923d190e | ||
|
|
919c54f750 | ||
|
|
1966745689 | ||
|
|
31ad1bb606 | ||
|
|
541e76fa45 | ||
|
|
f71f37e426 | ||
|
|
c2070d771a | ||
|
|
1563388001 | ||
|
|
56eb25f049 | ||
|
|
a4aaf82421 | ||
|
|
fdb411a8c5 | ||
|
|
8a0b6f561c | ||
|
|
e15fb33e10 | ||
|
|
cbef0dba2e | ||
|
|
e0d49b7e1b | ||
|
|
6de37864a2 | ||
|
|
ca59f5f208 | ||
|
|
5b9e7e29f6 | ||
|
|
a931c4eeec | ||
|
|
3d19adf9b3 | ||
|
|
d79342d33e | ||
|
|
ed500e4987 | ||
|
|
c16612ee87 | ||
|
|
7fb31479bf | ||
|
|
b67eb20ed0 | ||
|
|
4a27ad040e | ||
|
|
e33d2383d1 | ||
|
|
bf47b71b78 | ||
|
|
a621333a4c | ||
|
|
efb8aa0ef6 | ||
|
|
ce166e6b68 | ||
|
|
3eb532e974 | ||
|
|
8766bc02dc | ||
|
|
b4564841b6 | ||
|
|
0e4cae5212 | ||
|
|
88d3cd582e | ||
|
|
bc3912980a | ||
|
|
eb0e3bab1e | ||
|
|
4d22ade102 | ||
|
|
64ad838fde | ||
|
|
617bda27e9 | ||
|
|
aac9e8cfa3 | ||
|
|
99061d1dcb | ||
|
|
0dfe849413 | ||
|
|
2ec943284a | ||
|
|
460bceca39 | ||
|
|
afd4909a0f | ||
|
|
37b143ce9e | ||
|
|
61e77a4e88 | ||
|
|
58d9d85a56 | ||
|
|
ba2c503541 | ||
|
|
50fea19416 | ||
|
|
c8b80e4740 | ||
|
|
4f1b0292db | ||
|
|
abd5a57ea1 | ||
|
|
3990b1715d | ||
|
|
f039ac5bd7 | ||
|
|
64da62ec2e | ||
|
|
aa4ada943a | ||
|
|
01816068c8 | ||
|
|
a60b0263ba | ||
|
|
ade36806c8 | ||
|
|
8fac939889 | ||
|
|
6ead9f6f3d | ||
|
|
f2f761c0c3 | ||
|
|
243f8988be | ||
|
|
d1771bbae0 | ||
|
|
ed1c194ebf | ||
|
|
6af90b2972 | ||
|
|
16f324641f | ||
|
|
1a7e28d8b7 | ||
|
|
5a38694f55 | ||
|
|
25df419c67 | ||
|
|
0d221775f5 | ||
|
|
2dd21d9a68 | ||
|
|
614deb82c7 | ||
|
|
a53e0e59f3 | ||
|
|
c141584e1e | ||
|
|
77f0cd8027 | ||
|
|
4d4cfc2ee6 | ||
|
|
1e77e25675 | ||
|
|
e47c2ec64a | ||
|
|
9bdb82ef6b | ||
|
|
43473372e6 | ||
|
|
b652ee705b | ||
|
|
40214b9e26 | ||
|
|
918851e836 | ||
|
|
a1b442bc07 | ||
|
|
707cae7494 | ||
|
|
26b7d8a7be | ||
|
|
43963a8d97 | ||
|
|
68815901d4 | ||
|
|
93e353e384 | ||
|
|
04c27e5eaa | ||
|
|
c3f519adfe | ||
|
|
bd6622abe8 | ||
|
|
6aa7c805cc | ||
|
|
bcd0e9a7fa | ||
|
|
0a6f599cf2 | ||
|
|
780114e398 | ||
|
|
0b52228739 | ||
|
|
ad9b9c7621 | ||
|
|
be313ea215 | ||
|
|
20283aec10 | ||
|
|
e32d1e17bb | ||
|
|
dfe056df6f | ||
|
|
ee622cc1ed | ||
|
|
26d5e91bf3 | ||
|
|
3593d8e10c | ||
|
|
e9f3fb7662 | ||
|
|
9626662819 | ||
|
|
7711d87563 | ||
|
|
e3f0f31e07 |
@@ -198,14 +198,6 @@ typedef long mp_off_t;
|
||||
// disabling/enabling and sleep mode enter/exit
|
||||
#include "cc3200_asm.h"
|
||||
|
||||
// There is no classical C heap in bare-metal ports, only Python
|
||||
// garbage-collected heap. For completeness, emulate C heap via
|
||||
// GC heap. Note that MicroPython core never uses malloc() and friends,
|
||||
// so these defines are mostly to help extension module writers.
|
||||
#define malloc gc_alloc
|
||||
#define free gc_free
|
||||
#define realloc gc_realloc
|
||||
|
||||
// We need to provide a declaration/definition of alloca()
|
||||
#include <alloca.h>
|
||||
|
||||
|
||||
@@ -35,6 +35,6 @@ This can be achieved with:
|
||||
make MICROPY_PORT=<port_name> latexpdf
|
||||
|
||||
but require rather complete install of LaTeX with various extensions. On
|
||||
Debiab/Ubuntu, try (500MB+ download):
|
||||
Debian/Ubuntu, try (500MB+ download):
|
||||
|
||||
apt-get install texlive-latex-recommended texlive-latex-extra
|
||||
|
||||
@@ -99,7 +99,7 @@ copyright = '2014-2016, Damien P. George and contributors'
|
||||
# The short X.Y version.
|
||||
version = '1.8'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.8.2'
|
||||
release = '1.8.3'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
@@ -52,7 +52,7 @@ For your convenience, some of technical specifications are provided below:
|
||||
external FlashROM, UART, deep sleep wake-up, etc.)
|
||||
* UART: One RX/TX UART (no hardware handshaking), one TX-only UART.
|
||||
* SPI: 2 SPI interfaces (one used for FlashROM).
|
||||
* I2C: No native extenal I2C (bitbang implementation available on any pins).
|
||||
* I2C: No native external I2C (bitbang implementation available on any pins).
|
||||
* I2S: 1.
|
||||
* Programming: using BootROM bootloader from UART. Due to external FlashROM
|
||||
and always-available BootROM bootloader, ESP8266 is not brickable.
|
||||
|
||||
@@ -9,6 +9,12 @@ Quick reference for the ESP8266
|
||||
|
||||
The Adafruit Feather HUZZAH board (image attribution: Adafruit).
|
||||
|
||||
Installing MicroPython
|
||||
----------------------
|
||||
|
||||
See the corresponding section of tutorial: :ref:`intro`. It also includes
|
||||
a troubleshooting subsection.
|
||||
|
||||
General board control
|
||||
---------------------
|
||||
|
||||
@@ -291,6 +297,24 @@ For low-level driving of an APA102::
|
||||
import esp
|
||||
esp.apa102_write(clock_pin, data_pin, rgbi_buf)
|
||||
|
||||
DHT driver
|
||||
----------
|
||||
|
||||
The DHT driver is implemented in software and works on all pins::
|
||||
|
||||
import dht
|
||||
import machine
|
||||
|
||||
d = dht.DHT11(machine.Pin(4))
|
||||
d.measure()
|
||||
d.temperature() # eg. 23 (°C)
|
||||
d.humidity() # eg. 41 (% RH)
|
||||
|
||||
d = dht.DHT22(machine.Pin(4))
|
||||
d.measure()
|
||||
d.temperature() # eg. 23.6 (°C)
|
||||
d.humidity() # eg. 41.3 (% RH)
|
||||
|
||||
WebREPL (web browser interactive prompt)
|
||||
----------------------------------------
|
||||
|
||||
|
||||
65
docs/esp8266/tutorial/dht.rst
Normal file
65
docs/esp8266/tutorial/dht.rst
Normal file
@@ -0,0 +1,65 @@
|
||||
Temperature and Humidity
|
||||
========================
|
||||
|
||||
DHT (Digital Humidity & Temperature) sensors are low cost digital sensors with
|
||||
capacitive humidity sensors and thermistors to measure the surrounding air.
|
||||
They feature a chip that handles analog to digital conversion and provide a
|
||||
1-wire interface. Newer sensors additionally provide an I2C interface.
|
||||
|
||||
The DHT11 (blue) and DHT22 (white) sensors provide the same 1-wire interface,
|
||||
however, the DHT22 requires a separate object as it has more complex
|
||||
calculation. DHT22 have 1 decimal place resolution for both humidity and
|
||||
temperature readings. DHT11 have whole number for both.
|
||||
|
||||
A custom 1-wire protocol, which is different to Dallas 1-wire, is used to get
|
||||
the measurements from the sensor. The payload consists of a humidity value,
|
||||
a temperature value and a checksum.
|
||||
|
||||
To use the 1-wire interface, construct the objects referring to their data pin::
|
||||
|
||||
>>> import dht
|
||||
>>> import machine
|
||||
>>> d = dht.DHT11(machine.Pin(4))
|
||||
|
||||
>>> import dht
|
||||
>>> import machine
|
||||
>>> d = dht.DHT22(machine.Pin(4))
|
||||
|
||||
Then measure and read their values with::
|
||||
|
||||
>>> d.measure()
|
||||
>>> d.temperature()
|
||||
>>> d.humidity()
|
||||
|
||||
Values returned from ``temperature()`` are in degrees Celsius and values
|
||||
returned from ``humidity()`` are a percentage of relative humidity.
|
||||
|
||||
The DHT11 can be called no more than once per second and the DHT22 once every
|
||||
two seconds for most accurate results. Sensor accuracy will degrade over time.
|
||||
Each sensor supports a different operating range. Refer to the product
|
||||
datasheets for specifics.
|
||||
|
||||
In 1-wire mode, only three of the four pins are used and in I2C mode, all four
|
||||
pins are used. Older sensors may still have 4 pins even though they do not
|
||||
support I2C. The 3rd pin is simply not connected.
|
||||
|
||||
Pin configurations:
|
||||
|
||||
Sensor without I2C in 1-wire mode (eg. DHT11, DHT22, AM2301, AM2302):
|
||||
|
||||
1=VDD, 2=Data, 3=NC, 4=GND
|
||||
|
||||
Sensor with I2C in 1-wire mode (eg. DHT12, AM2320, AM2321, AM2322):
|
||||
|
||||
1=VDD, 2=Data, 3=GND, 4=GND
|
||||
|
||||
Sensor with I2C in I2C mode (eg. DHT12, AM2320, AM2321, AM2322):
|
||||
|
||||
1=VDD, 2=SDA, 3=GND, 4=SCL
|
||||
|
||||
You should use pull-up resistors for the Data, SDA and SCL pins.
|
||||
|
||||
To make newer I2C sensors work in backwards compatible 1-wire mode, you must
|
||||
connect both pins 3 and 4 to GND. This disables the I2C interface.
|
||||
|
||||
DHT22 sensors are now sold under the name AM2302 and are otherwise identical.
|
||||
@@ -29,4 +29,5 @@ to `<https://www.python.org>`__.
|
||||
powerctrl.rst
|
||||
onewire.rst
|
||||
neopixel.rst
|
||||
dht.rst
|
||||
nextsteps.rst
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
Introduction to MicroPython on the ESP8266
|
||||
==========================================
|
||||
.. _intro:
|
||||
|
||||
Getting started with MicroPython on the ESP8266
|
||||
===============================================
|
||||
|
||||
Using MicroPython is a great way to get the most of your ESP8266 board. And
|
||||
vice versa, the ESP8266 chip is a great platform for using MicroPython. This
|
||||
@@ -74,8 +76,9 @@ PC. You may also need to reduce the baudrate if you get errors when flashing
|
||||
(eg down to 115200). The filename of the firmware should also match the file
|
||||
that you have.
|
||||
|
||||
If you have a NodeMCU board, you may need to use the following command to deploy
|
||||
the firmware (note the "-fm dio" option)::
|
||||
For some boards with a particular FlashROM configuration (e.g. some variants of
|
||||
a NodeMCU board) you may need to use the following command to deploy
|
||||
the firmware (note the ``-fm dio`` option)::
|
||||
|
||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=8m -fm dio 0 esp8266-2016-05-03-v1.8.bin
|
||||
|
||||
@@ -100,3 +103,60 @@ be the same everytime, and most likely different for all ESP8266 chips). The
|
||||
password for the WiFi is micropythoN (note the upper-case N). Its IP address
|
||||
will be 192.168.4.1 once you connect to its network. WiFi configuration will
|
||||
be discussed in more detail later in the tutorial.
|
||||
|
||||
Troubleshooting installation problems
|
||||
-------------------------------------
|
||||
|
||||
If you experience problems during flashing or with running firmware immediately
|
||||
after it, here are troubleshooting recommendations:
|
||||
|
||||
* Be aware of and try to exclude hardware problems. There are 2 common problems:
|
||||
bad power source quality and worn-out/defective FlashROM. Speaking of power
|
||||
source, not just raw amperage is important, but also low ripple and noise/EMI
|
||||
in general. If you experience issues with self-made or wall-wart style power
|
||||
supply, try USB power from a computer. Unearthed power supplies are also known
|
||||
to cause problems as they source of increased EMI (electromagnetic interference)
|
||||
- at the very least, and may lead to electrical devices breakdown. So, you are
|
||||
advised to avoid using unearthed power connections when working with ESP8266
|
||||
and other boards. In regard to FlashROM hardware problems, there are independent
|
||||
(not related to MicroPython in any way) reports
|
||||
`(e.g.) <http://internetofhomethings.com/homethings/?p=538>`_
|
||||
that on some ESP8266 modules, FlashROM can be programmed as little as 20 times
|
||||
before programming errors occur. This is *much* less than 100,000 programming
|
||||
cycles cited for FlashROM chips of a type used with ESP8266 by reputable
|
||||
vendors, which points to either production rejects, or second-hand worn-out
|
||||
flash chips to be used on some (apparently cheap) modules/boards. You may want
|
||||
to use your best judgement about source, price, documentation, warranty,
|
||||
post-sales support for the modules/boards you purchase.
|
||||
|
||||
* The flashing instructions above use flashing speed of 460800 baud, which is
|
||||
good compromise between speed and stability. However, depending on your
|
||||
module/board, USB-UART convertor, cables, host OS, etc., the above baud
|
||||
rate may be too high and lead to errors. Try a more common 115200 baud
|
||||
rate instead in such cases.
|
||||
|
||||
* The ``--flash_size`` option in the commands above is mandatory. Omitting
|
||||
it will lead to a corrupted firmware.
|
||||
|
||||
* To catch incorrect flash content (e.g. from a defective sector on a chip),
|
||||
add ``--verify`` switch to the commands above.
|
||||
|
||||
* Additionally, you can check the firmware integrity from a MicroPython REPL
|
||||
prompt (assuming you were able to flash it and ``--verify`` option doesn't
|
||||
report errors)::
|
||||
import esp
|
||||
esp.check_fw()
|
||||
If the last output value is True, the firmware is OK. Otherwise, it's
|
||||
corrupted and need to be reflashed correctly.
|
||||
|
||||
* If you experience any issues with another flashing application (not
|
||||
esptool.py), try esptool.py, it is a generally accepted flashing
|
||||
application in the ESP8266 community.
|
||||
|
||||
* If you still experience problems with even flashing the firmware, please
|
||||
refer to esptool.py project page, https://github.com/themadinventor/esptool
|
||||
for additional documentation and bug tracker where you can report problems.
|
||||
|
||||
* If you are able to flash firmware, but ``--verify`` option or
|
||||
``esp.check_fw()`` return errors even after multiple retries, you
|
||||
may have a defective FlashROM chip, as explained above.
|
||||
|
||||
@@ -36,7 +36,7 @@ WebREPL - a prompt over WiFi
|
||||
WebREPL allows you to use the Python prompt over WiFi, connecting through a
|
||||
browser. The latest versions of Firefox and Chrome are supported.
|
||||
|
||||
For your convinience, WebREPL client is hosted at
|
||||
For your convenience, WebREPL client is hosted at
|
||||
`<http://micropython.org/webrepl>`__ . Alternatively, you can install it
|
||||
locally from the the GitHub repository
|
||||
`<https://github.com/micropython/webrepl>`__ .
|
||||
|
||||
30
docs/library/array.rst
Normal file
30
docs/library/array.rst
Normal file
@@ -0,0 +1,30 @@
|
||||
:mod:`array` -- arrays of numeric data
|
||||
======================================
|
||||
|
||||
.. module:: array
|
||||
:synopsis: efficient arrays of numeric data
|
||||
|
||||
See `Python array <https://docs.python.org/3/library/array.html>`_ for more
|
||||
information.
|
||||
|
||||
Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``,
|
||||
``L``, ``q``, ``Q``, ``f``, ``d`` (the latter 2 depending on the
|
||||
floating-point support).
|
||||
|
||||
Classes
|
||||
-------
|
||||
|
||||
.. class:: array.array(typecode, [iterable])
|
||||
|
||||
Create array with elements of given type. Initial contents of the
|
||||
array are given by an `iterable`. If it is not provided, an empty
|
||||
array is created.
|
||||
|
||||
.. method:: append(val)
|
||||
|
||||
Append new element to the end of array, growing it.
|
||||
|
||||
.. method:: extend(iterable)
|
||||
|
||||
Append new elements as contained in an iterable to the end of
|
||||
array, growing it.
|
||||
@@ -1,7 +1,7 @@
|
||||
Builtin Functions
|
||||
=================
|
||||
|
||||
All builtin functions are described here. They are alse available via
|
||||
All builtin functions are described here. They are also available via
|
||||
``builtins`` module.
|
||||
|
||||
.. function:: abs()
|
||||
|
||||
@@ -15,7 +15,7 @@ Functions
|
||||
Get or set the sleep type.
|
||||
|
||||
If the ``sleep_type`` parameter is provided, sets the sleep type to its
|
||||
value. If the function is called wihout parameters, returns the current
|
||||
value. If the function is called without parameters, returns the current
|
||||
sleep type.
|
||||
|
||||
The possible sleep types are defined as constants:
|
||||
|
||||
@@ -51,6 +51,7 @@ library.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
array.rst
|
||||
builtins.rst
|
||||
cmath.rst
|
||||
gc.rst
|
||||
@@ -75,6 +76,7 @@ library.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
array.rst
|
||||
builtins.rst
|
||||
cmath.rst
|
||||
gc.rst
|
||||
@@ -99,6 +101,7 @@ library.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
array.rst
|
||||
builtins.rst
|
||||
gc.rst
|
||||
select.rst
|
||||
@@ -116,6 +119,7 @@ library.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
array.rst
|
||||
builtins.rst
|
||||
gc.rst
|
||||
math.rst
|
||||
|
||||
@@ -84,7 +84,7 @@ Methods
|
||||
|
||||
- ``None`` - no pull up or down resistor.
|
||||
- ``Pin.PULL_UP`` - pull up resistor enabled.
|
||||
- ``Pin.PULL_DOWN`` - pull down resitor enabled.
|
||||
- ``Pin.PULL_DOWN`` - pull down resistor enabled.
|
||||
|
||||
- ``drive`` can be one of:
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ Methods
|
||||
|
||||
.. method:: RTC.alarm(id, time, /*, repeat=False)
|
||||
|
||||
Set the RTC alarm. Time might be either a milllisecond value to program the alarm to
|
||||
Set the RTC alarm. Time might be either a millisecond value to program the alarm to
|
||||
current time + time_in_ms in the future, or a datetimetuple. If the time passed is in
|
||||
milliseconds, repeat can be set to ``True`` to make the alarm periodic.
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ Methods
|
||||
respectively.
|
||||
- ``bits`` is the width of each transfer, accepted values are 8, 16 and 32.
|
||||
- ``firstbit`` can be ``SPI.MSB`` only.
|
||||
- ``pins`` is an optional tupple with the pins to assign to the SPI bus.
|
||||
- ``pins`` is an optional tuple with the pins to assign to the SPI bus.
|
||||
|
||||
.. method:: SPI.deinit()
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ Methods
|
||||
If only a channel identifier passed, then a previously initialized channel
|
||||
object is returned (or ``None`` if there is no previous channel).
|
||||
|
||||
Othwerwise, a TimerChannel object is initialized and returned.
|
||||
Otherwise, a TimerChannel object is initialized and returned.
|
||||
|
||||
The operating mode is is the one configured to the Timer object that was used to
|
||||
create the channel.
|
||||
@@ -152,7 +152,7 @@ Methods
|
||||
|
||||
.. method:: timerchannel.irq(\*, trigger, priority=1, handler=None)
|
||||
|
||||
The behavior of this callback is heaviliy dependent on the operating
|
||||
The behavior of this callback is heavily dependent on the operating
|
||||
mode of the timer channel:
|
||||
|
||||
- If mode is ``Timer.PERIODIC`` the callback is executed periodically
|
||||
|
||||
@@ -167,7 +167,7 @@ Methods
|
||||
.. data:: UART.EVEN
|
||||
.. data:: UART.ODD
|
||||
|
||||
parity types (anlong with ``None``)
|
||||
parity types (along with ``None``)
|
||||
|
||||
.. data:: UART.RX_ANY
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ Power related functions
|
||||
Gates the clock to the CPU, useful to reduce power consumption at any time during
|
||||
short or long periods. Peripherals continue working and execution resumes as soon
|
||||
as any interrupt is triggered (on many ports this includes system timer
|
||||
interrupt occuring at regular intervals on the order of millisecond).
|
||||
interrupt occurring at regular intervals on the order of millisecond).
|
||||
|
||||
.. function:: sleep()
|
||||
|
||||
@@ -96,7 +96,7 @@ Miscellaneous functions
|
||||
|
||||
.. function:: unique_id()
|
||||
|
||||
Returns a byte string with a unique idenifier of a board/SoC. It will vary
|
||||
Returns a byte string with a unique identifier of a board/SoC. It will vary
|
||||
from a board/SoC instance to another, if underlying hardware allows. Length
|
||||
varies by hardware (so use substring of a full value if you expect a short
|
||||
ID). In some MicroPython ports, ID corresponds to the network MAC address.
|
||||
|
||||
@@ -237,7 +237,7 @@ For example::
|
||||
Get or set the PHY mode.
|
||||
|
||||
If the ``mode`` parameter is provided, sets the mode to its value. If
|
||||
the function is called wihout parameters, returns the current mode.
|
||||
the function is called without parameters, returns the current mode.
|
||||
|
||||
The possible modes are defined as constants:
|
||||
* ``MODE_11B`` -- IEEE 802.11b,
|
||||
@@ -319,7 +319,7 @@ For example::
|
||||
* ``STAT_WRONG_PASSWORD`` -- failed due to incorrect password,
|
||||
* ``STAT_NO_AP_FOUND`` -- failed because no access point replied,
|
||||
* ``STAT_CONNECT_FAIL`` -- failed due to other problems,
|
||||
* ``STAT_GOT_IP`` -- connection susccessful.
|
||||
* ``STAT_GOT_IP`` -- connection successful.
|
||||
|
||||
.. method:: wlan.isconnected()
|
||||
|
||||
@@ -329,7 +329,7 @@ For example::
|
||||
|
||||
.. method:: wlan.ifconfig([(ip, subnet, gateway, dns)])
|
||||
|
||||
Get/set IP-level network interface paremeters: IP address, subnet mask,
|
||||
Get/set IP-level network interface parameters: IP address, subnet mask,
|
||||
gateway and DNS server. When called with no arguments, this method returns
|
||||
a 4-tuple with the above information. To set the above values, pass a
|
||||
4-tuple with the required information. For example::
|
||||
@@ -343,8 +343,8 @@ For example::
|
||||
with additional parameters beyond standard IP configuration (as dealt with by
|
||||
``wlan.ifconfig()``). These include network-specific and hardware-specific
|
||||
parameters. For setting parameters, keyword argument syntax should be used,
|
||||
multiple parameters can be set at once. For querying, paremeters name should
|
||||
be quoted as a string, and only one paramter can be queries at time::
|
||||
multiple parameters can be set at once. For querying, parameters name should
|
||||
be quoted as a string, and only one parameter can be queries at time::
|
||||
|
||||
# Set WiFi access point name (formally known as ESSID) and WiFi channel
|
||||
ap.config(essid='My AP', channel=11)
|
||||
@@ -397,7 +397,7 @@ For example::
|
||||
.. note::
|
||||
|
||||
The ``WLAN`` constructor is special in the sense that if no arguments besides the id are given,
|
||||
it will return the already exisiting ``WLAN`` instance without re-configuring it. This is
|
||||
it will return the already existing ``WLAN`` instance without re-configuring it. This is
|
||||
because ``WLAN`` is a system feature of the WiPy. If the already existing instance is not
|
||||
initialized it will do the same as the other constructors an will initialize it with default
|
||||
values.
|
||||
|
||||
@@ -13,7 +13,7 @@ class ADC -- analog to digital conversion
|
||||
adc = pyb.ADC(pin) # create an analog object from a pin
|
||||
val = adc.read() # read an analog value
|
||||
|
||||
adc = pyb.ADCAll(resolution) # creale an ADCAll object
|
||||
adc = pyb.ADCAll(resolution) # create an ADCAll object
|
||||
val = adc.read_channel(channel) # read the given channel
|
||||
val = adc.read_core_temp() # read MCU temperature
|
||||
val = adc.read_core_vbat() # read MCU VBAT
|
||||
|
||||
@@ -79,7 +79,7 @@ Methods
|
||||
.. method:: DAC.triangle(freq)
|
||||
|
||||
Generate a triangle wave. The value on the DAC output changes at
|
||||
the given frequency, and the frequence of the repeating triangle wave
|
||||
the given frequency, and the frequency of the repeating triangle wave
|
||||
itself is 2048 times smaller.
|
||||
|
||||
.. method:: DAC.write(value)
|
||||
|
||||
@@ -7,7 +7,7 @@ class ExtInt -- configure I/O pins to interrupt on external events
|
||||
There are a total of 22 interrupt lines. 16 of these can come from GPIO pins
|
||||
and the remaining 6 are from internal sources.
|
||||
|
||||
For lines 0 thru 15, a given line can map to the corresponding line from an
|
||||
For lines 0 through 15, a given line can map to the corresponding line from an
|
||||
arbitrary port. So line 0 can map to Px0 where x is A, B, C, ... and
|
||||
line 1 can map to Px1 where x is A, B, C, ... ::
|
||||
|
||||
@@ -27,7 +27,7 @@ explanation, along with various techniques for debouncing.
|
||||
Trying to register 2 callbacks onto the same pin will throw an exception.
|
||||
|
||||
If pin is passed as an integer, then it is assumed to map to one of the
|
||||
internal interrupt sources, and must be in the range 16 thru 22.
|
||||
internal interrupt sources, and must be in the range 16 through 22.
|
||||
|
||||
All other pin objects go through the pin mapper to come up with one of the
|
||||
gpio pins. ::
|
||||
|
||||
@@ -39,7 +39,7 @@ Printing the i2c object gives you information about its configuration.
|
||||
|
||||
You can specify a timeout (in ms)::
|
||||
|
||||
i2c.send(b'123', timeout=2000) # timout after 2 seconds
|
||||
i2c.send(b'123', timeout=2000) # timeout after 2 seconds
|
||||
|
||||
A master must specify the recipient's address::
|
||||
|
||||
|
||||
@@ -231,7 +231,7 @@ Constants
|
||||
class PinAF -- Pin Alternate Functions
|
||||
======================================
|
||||
|
||||
A Pin represents a physical pin on the microcprocessor. Each pin
|
||||
A Pin represents a physical pin on the microprocessor. Each pin
|
||||
can have a variety of functions (GPIO, I2C SDA, etc). Each PinAF
|
||||
object represents a particular function for a pin.
|
||||
|
||||
@@ -240,7 +240,7 @@ Constants
|
||||
x3 = pyb.Pin.board.X3
|
||||
x3_af = x3.af_list()
|
||||
|
||||
x3_af will now contain an array of PinAF objects which are availble on
|
||||
x3_af will now contain an array of PinAF objects which are available on
|
||||
pin X3.
|
||||
|
||||
For the pyboard, x3_af would contain:
|
||||
|
||||
@@ -73,7 +73,7 @@ Methods
|
||||
value, which is an integer in the range [-511 : 512]. With one
|
||||
argument it sets the RTC calibration.
|
||||
|
||||
The RTC Smooth Calibration mechanism addjusts the RTC clock rate by
|
||||
The RTC Smooth Calibration mechanism adjusts the RTC clock rate by
|
||||
adding or subtracting the given number of ticks from the 32768 Hz
|
||||
clock over a 32 second period (corresponding to 2^20 clock ticks.)
|
||||
Each tick added will speed up the clock by 1 part in 2^20, or 0.954
|
||||
|
||||
@@ -78,7 +78,7 @@ Methods
|
||||
|
||||
Keyword arguments:
|
||||
|
||||
- ``freq`` --- specifies the periodic frequency of the timer. You migh also
|
||||
- ``freq`` --- specifies the periodic frequency of the timer. You might also
|
||||
view this as the frequency with which the timer goes through one complete cycle.
|
||||
|
||||
- ``prescaler`` [0-0xffff] - specifies the value to be loaded into the
|
||||
@@ -97,7 +97,7 @@ Methods
|
||||
|
||||
- ``Timer.UP`` - configures the timer to count from 0 to ARR (default)
|
||||
- ``Timer.DOWN`` - configures the timer to count from ARR down to 0.
|
||||
- ``Timer.CENTER`` - confgures the timer to count from 0 to ARR and
|
||||
- ``Timer.CENTER`` - configures the timer to count from 0 to ARR and
|
||||
then back down to 0.
|
||||
|
||||
- ``div`` can be one of 1, 2, or 4. Divides the timer clock to determine
|
||||
@@ -109,7 +109,7 @@ Methods
|
||||
transitions on complimentary channels (both channels will be inactive)
|
||||
for this time). ``deadtime`` may be an integer between 0 and 1008, with
|
||||
the following restrictions: 0-128 in steps of 1. 128-256 in steps of
|
||||
2, 256-512 in steps of 8, and 512-1008 in steps of 16. ``deadime``
|
||||
2, 256-512 in steps of 8, and 512-1008 in steps of 16. ``deadtime``
|
||||
measures ticks of ``source_freq`` divided by ``div`` clock ticks.
|
||||
``deadtime`` is only available on timers 1 and 8.
|
||||
|
||||
@@ -141,7 +141,7 @@ Methods
|
||||
If only a channel number is passed, then a previously initialized channel
|
||||
object is returned (or ``None`` if there is no previous channel).
|
||||
|
||||
Othwerwise, a TimerChannel object is initialized and returned.
|
||||
Otherwise, a TimerChannel object is initialized and returned.
|
||||
|
||||
Each channel can be configured to perform pwm, output compare, or
|
||||
input capture. All channels share the same underlying timer, which means
|
||||
@@ -183,7 +183,7 @@ Methods
|
||||
- ``polarity`` can be one of:
|
||||
|
||||
- ``Timer.HIGH`` - output is active high
|
||||
- ``Timer.LOW`` - output is acive low
|
||||
- ``Timer.LOW`` - output is active low
|
||||
|
||||
Optional keyword arguments for Timer.IC modes:
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ Time related functions
|
||||
Returns the number of milliseconds which have elapsed since ``start``.
|
||||
|
||||
This function takes care of counter wrap, and always returns a positive
|
||||
number. This means it can be used to measure periods upto about 12.4 days.
|
||||
number. This means it can be used to measure periods up to about 12.4 days.
|
||||
|
||||
Example::
|
||||
|
||||
@@ -59,7 +59,7 @@ Time related functions
|
||||
Returns the number of microseconds which have elapsed since ``start``.
|
||||
|
||||
This function takes care of counter wrap, and always returns a positive
|
||||
number. This means it can be used to measure periods upto about 17.8 minutes.
|
||||
number. This means it can be used to measure periods up to about 17.8 minutes.
|
||||
|
||||
Example::
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ Functions
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
If additional argument, `sep` is supplied, it is used as a seperator
|
||||
If additional argument, `sep` is supplied, it is used as a separator
|
||||
between hexadecimal values.
|
||||
|
||||
.. function:: unhexlify(data)
|
||||
|
||||
@@ -13,10 +13,10 @@ Classes
|
||||
.. function:: namedtuple(name, fields)
|
||||
|
||||
This is factory function to create a new namedtuple type with a specific
|
||||
name and set of fields. A namedtyple is a subclass of tuple which allows
|
||||
name and set of fields. A namedtuple is a subclass of tuple which allows
|
||||
to access its fields not just by numeric index, but also with an attribute
|
||||
access syntax using symbolic field names. Fields is a sequence of strings
|
||||
specifying field names. For compatibily with CPython it can also be a
|
||||
specifying field names. For compatibility with CPython it can also be a
|
||||
a string with space-separated field named (but this is less efficient).
|
||||
Example of use::
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ Module contents
|
||||
|
||||
.. data:: BIG_ENDIAN
|
||||
|
||||
Layour type for a big-endian packed structure.
|
||||
Layout type for a big-endian packed structure.
|
||||
|
||||
.. data:: NATIVE
|
||||
|
||||
@@ -184,7 +184,7 @@ Subscripting a pointer with other integer values but 0 are supported too,
|
||||
with the same semantics as in C.
|
||||
|
||||
Summing up, accessing structure fields generally follows C syntax,
|
||||
except for pointer derefence, when you need to use ``[0]`` operator
|
||||
except for pointer dereference, when you need to use ``[0]`` operator
|
||||
instead of ``*``.
|
||||
|
||||
Limitations
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
This module implements binary data hashing algorithms. Currently, it
|
||||
implements SHA256 algorithm. Choosing SHA256 was a deliberate choice,
|
||||
as a modern, cryptographically secure algorithm. This means that a
|
||||
single algorithm can cover both usecases of "any hash algorithm" and
|
||||
single algorithm can cover both use cases of "any hash algorithm" and
|
||||
security-related usage, and thus save space omitting legacy algorithms
|
||||
like MD5 or SHA1.
|
||||
|
||||
@@ -53,7 +53,7 @@ Constructors
|
||||
|
||||
Example::
|
||||
|
||||
hash = uhashlib.sha1('abcd1234', 1001) # lenght of the initial piece is multiple of 4 bytes
|
||||
hash = uhashlib.sha1('abcd1234', 1001) # length of the initial piece is multiple of 4 bytes
|
||||
hash.update('1234') # also multiple of 4 bytes
|
||||
...
|
||||
hash.update('12345') # last chunk may be of any length
|
||||
@@ -68,7 +68,7 @@ Methods
|
||||
|
||||
.. method:: hash.digest()
|
||||
|
||||
Return hash for all data passed thru hash, as a bytes object. After this
|
||||
Return hash for all data passed through hash, as a bytes object. After this
|
||||
method is called, more data cannot be fed into hash any longer.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
@@ -12,7 +12,7 @@ Functions
|
||||
|
||||
.. function:: open(name, mode='r', **kwargs)
|
||||
|
||||
Open a file. Builtin ``open()`` function is alised to this function.
|
||||
Open a file. Builtin ``open()`` function is aliased to this function.
|
||||
All ports (which provide access to file system) are required to support
|
||||
`mode` parameter, but support for other arguments vary by port.
|
||||
|
||||
@@ -38,8 +38,9 @@ Classes
|
||||
opened with "b" modifier). Initial contents of file-like objects
|
||||
can be specified with `string` parameter (should be normal string
|
||||
for `StringIO` or bytes object for `BytesIO`). All the usual file
|
||||
methods like ``read()``, ``write()``, ``close()`` are available on
|
||||
these objects, and additionally, following method:
|
||||
methods like ``read()``, ``write()``, ``seek()``, ``flush()``,
|
||||
``close()`` are available on these objects, and additionally, a
|
||||
following method:
|
||||
|
||||
.. method:: getvalue()
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ Functions
|
||||
|
||||
.. function:: unmount(path)
|
||||
|
||||
Unmounts a prevoulsy mounted block device from the given path.
|
||||
Unmounts a previously mounted block device from the given path.
|
||||
|
||||
.. function:: mkfs(block_device or path)
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ Functions
|
||||
.. function:: time()
|
||||
|
||||
Returns the number of seconds, as an integer, since the Epoch, assuming that underlying
|
||||
RTC is set and maintained as decsribed above. If an RTC is not set, this function returns
|
||||
RTC is set and maintained as described above. If an RTC is not set, this function returns
|
||||
number of seconds since a port-specific reference point in time (for embedded boards without
|
||||
a battery-backed RTC, usually since power up or reset). If you want to develop portable
|
||||
MicroPython application, you should not rely on this function to provide higher than second
|
||||
|
||||
@@ -95,7 +95,7 @@ We set up timer 2 as follows::
|
||||
|
||||
The prescaler is set at 83, which makes this timer count at 1 MHz.
|
||||
This is because the CPU clock, running at 168 MHz, is divided by
|
||||
2 and then by prescaler+1, giving a freqency of 168 MHz/2/(83+1)=1 MHz
|
||||
2 and then by prescaler+1, giving a frequency of 168 MHz/2/(83+1)=1 MHz
|
||||
for timer 2. The period is set to a large number so that the timer
|
||||
can count up to a large number before wrapping back around to zero.
|
||||
In this case it will take about 17 minutes before it cycles back to
|
||||
|
||||
@@ -61,7 +61,7 @@ The first argument to the function ``osc`` is the number of mouse events to send
|
||||
and the second argument is the delay (in milliseconds) between events. Try
|
||||
playing around with different numbers.
|
||||
|
||||
**Excercise: make the mouse go around in a circle.**
|
||||
**Exercise: make the mouse go around in a circle.**
|
||||
|
||||
Making a mouse with the accelerometer
|
||||
-------------------------------------
|
||||
@@ -85,14 +85,14 @@ the [safe mode tutorial](tut-reset), but we repeat the instructions here:
|
||||
3. The LEDs will then cycle green to orange to green+orange and back again.
|
||||
4. Keep holding down USR until *only the orange LED is lit*, and then let
|
||||
go of the USR switch.
|
||||
5. The orange LED should flash quickly 4 times, and then turn off.
|
||||
5. The orange LED should flash quickly 4 times, and then turn off.
|
||||
6. You are now in safe mode.
|
||||
|
||||
In safe mode, the ``boot.py`` and ``main.py`` files are not executed, and so
|
||||
the pyboard boots up with default settings. This means you now have access
|
||||
to the filesystem (the USB drive should appear), and you can edit ``main.py``.
|
||||
(Leave ``boot.py`` as-is, because we still want to go back to HID-mode after
|
||||
we finish editting ``main.py``.)
|
||||
we finish editing ``main.py``.)
|
||||
|
||||
In ``main.py`` put the following code::
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ Non-integer data types
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
These may be handled by means of arrays of the appropriate data type. For
|
||||
example, single precison floating point data may be processed as follows.
|
||||
example, single precision floating point data may be processed as follows.
|
||||
This code example takes an array of floats and replaces its contents with
|
||||
their squares.
|
||||
|
||||
@@ -172,7 +172,7 @@ thus:
|
||||
|
||||
The const() construct causes MicroPython to replace the variable name
|
||||
with its value at compile time. If constants are declared in an outer
|
||||
Python scope they can be shared between mutiple assembler functions and
|
||||
Python scope they can be shared between multiple assembler functions and
|
||||
with Python code.
|
||||
|
||||
Assembler code as class methods
|
||||
|
||||
@@ -23,7 +23,7 @@ specifiers:
|
||||
* ne Not equal
|
||||
* cs Carry set
|
||||
* cc Carry clear
|
||||
* mi Minus (negaive)
|
||||
* mi Minus (negative)
|
||||
* pl Plus (positive)
|
||||
* vs Overflow set
|
||||
* vc Overflow clear
|
||||
|
||||
@@ -24,7 +24,7 @@ This summarises the points detailed below and lists the principal recommendation
|
||||
* Where an ISR returns multiple bytes use a pre-allocated ``bytearray``. If multiple integers are to be
|
||||
shared between an ISR and the main program consider an array (``array.array``).
|
||||
* Where data is shared between the main program and an ISR, consider disabling interrupts prior to accessing
|
||||
the data in the main program and re-enabling them immediately afterwards (see Critcal Sections).
|
||||
the data in the main program and re-enabling them immediately afterwards (see Critical Sections).
|
||||
* Allocate an emergency exception buffer (see below).
|
||||
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ Finally type ``print(i)``, press RETURN, press BACKSPACE and press RETURN again:
|
||||
>>>
|
||||
|
||||
Auto-indent won't be applied if the previous two lines were all spaces. This
|
||||
means that you can finish entering a compound statment by pressing RETURN
|
||||
means that you can finish entering a compound statement by pressing RETURN
|
||||
twice, and then a third press will finish and execute.
|
||||
|
||||
Auto-completion
|
||||
@@ -80,7 +80,7 @@ expansions:
|
||||
Interrupting a running program
|
||||
------------------------------
|
||||
|
||||
You can interupt a running program by pressing Ctrl-C. This will raise a KeyboardInterrupt
|
||||
You can interrupt a running program by pressing Ctrl-C. This will raise a KeyboardInterrupt
|
||||
which will bring you back to the REPL, providing your program doesn't intercept the
|
||||
KeyboardInterrupt exception.
|
||||
|
||||
@@ -184,8 +184,8 @@ variables no longer exist:
|
||||
The special variable _ (underscore)
|
||||
-----------------------------------
|
||||
|
||||
When you use the REPL, you may perfom computations and see the results.
|
||||
MicroPython stores the results of the previous statment in the variable _ (underscore).
|
||||
When you use the REPL, you may perform computations and see the results.
|
||||
MicroPython stores the results of the previous statement in the variable _ (underscore).
|
||||
So you can use the underscore to save the result in a variable. For example:
|
||||
|
||||
>>> 1 + 2 + 3 + 4 + 5
|
||||
|
||||
@@ -16,7 +16,7 @@ Before applying power
|
||||
|
||||
.. warning::
|
||||
|
||||
The GPIO pins of the WiPy are NOT 5V tolerant, connecting them to voltages higer
|
||||
The GPIO pins of the WiPy are NOT 5V tolerant, connecting them to voltages higher
|
||||
than 3.6V will cause irreparable damage to the board. ADC pins, when configured
|
||||
in analog mode cannot withstand voltages above 1.8V. Keep these considerations in
|
||||
mind when wiring your electronics.
|
||||
|
||||
@@ -205,7 +205,7 @@ See :ref:`network.Server <network.Server>` ::
|
||||
server = Server(login=('user', 'password'), timeout=60)
|
||||
server.timeout(300) # change the timeout
|
||||
server.timeout() # get the timeout
|
||||
server.isrunning() # check wether the server is running or not
|
||||
server.isrunning() # check whether the server is running or not
|
||||
|
||||
Heart beat LED
|
||||
--------------
|
||||
|
||||
@@ -17,7 +17,7 @@ Because the WiPy/expansion board does not have a housing it needs a bit of care:
|
||||
If you experience a lot of static electricity in your area (eg dry and cold
|
||||
climates), take extra care not to shock the WiPy. If your WiPy came
|
||||
in a ESD bag, then this bag is the best way to store and carry the
|
||||
WiPy as it will protect it agains static discharges.
|
||||
WiPy as it will protect it against static discharges.
|
||||
|
||||
As long as you take care of the hardware, you should be okay. It's almost
|
||||
impossible to break the software on the WiPy, so feel free to play around
|
||||
|
||||
@@ -157,7 +157,7 @@ int8_t WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8
|
||||
setSn_PORT(sn,port);
|
||||
setSn_CR(sn,Sn_CR_OPEN);
|
||||
while(getSn_CR(sn));
|
||||
sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn);
|
||||
sock_io_mode |= ((flag & SF_IO_NONBLOCK) << sn);
|
||||
sock_is_sending &= ~(1<<sn);
|
||||
sock_remained_size[sn] = 0;
|
||||
sock_pack_info[sn] = 0;
|
||||
|
||||
@@ -4,6 +4,8 @@ include ../py/mkenv.mk
|
||||
QSTR_DEFS = qstrdefsport.h #$(BUILD)/pins_qstr.h
|
||||
|
||||
MICROPY_PY_USSL = 1
|
||||
MICROPY_SSL_AXTLS = 1
|
||||
MICROPY_PY_BTREE = 1
|
||||
|
||||
# include py core make definitions
|
||||
include ../py/py.mk
|
||||
@@ -87,6 +89,7 @@ SRC_C = \
|
||||
$(BUILD)/frozen.c \
|
||||
fatfs_port.c \
|
||||
axtls_helpers.c \
|
||||
$(SRC_MOD)
|
||||
|
||||
STM_SRC_C = $(addprefix stmhal/,\
|
||||
pybstdio.c \
|
||||
@@ -153,7 +156,7 @@ SRC_QSTR += $(SRC_C) $(STM_SRC_C) $(EXTMOD_SRC_C) $(DRIVERS_SRC_C)
|
||||
# Append any auto-generated sources that are needed by sources listed in SRC_QSTR
|
||||
SRC_QSTR_AUTO_DEPS +=
|
||||
|
||||
all: $(BUILD)/firmware-combined.bin
|
||||
all: $(BUILD)/libaxtls.a $(BUILD)/firmware-combined.bin
|
||||
|
||||
CONFVARS_FILE = $(BUILD)/confvars
|
||||
|
||||
@@ -229,8 +232,11 @@ $(BUILD)/firmware.elf: $(OBJ)
|
||||
|
||||
include ../py/mkrules.mk
|
||||
|
||||
axtls:
|
||||
axtls: $(BUILD)/libaxtls.a
|
||||
|
||||
$(BUILD)/libaxtls.a:
|
||||
cd ../lib/axtls; cp config/upyconfig config/.config
|
||||
cd ../lib/axtls; make oldconfig -B
|
||||
cd ../lib/axtls; make clean
|
||||
cd ../lib/axtls; make all CC="$(CC)" LD="$(LD)" AR="$(AR)" CFLAGS_EXTRA="$(CFLAGS_XTENSA) -Dabort=abort_ -DRT_MAX_PLAIN_LENGTH=1024 -DRT_EXTRA=3072"
|
||||
cp ../lib/axtls/_stage/libaxtls.a $@
|
||||
|
||||
@@ -43,9 +43,6 @@ void *calloc(size_t nmemb, size_t size) {
|
||||
void *realloc(void *ptr, size_t size) {
|
||||
return gc_realloc(ptr, size, true);
|
||||
}
|
||||
void abort_(void) {
|
||||
printf("Aborted\n");
|
||||
}
|
||||
|
||||
#define PLATFORM_HTONL(_n) ((uint32_t)( (((_n) & 0xff) << 24) | (((_n) & 0xff00) << 8) | (((_n) >> 8) & 0xff00) | (((_n) >> 24) & 0xff) ))
|
||||
#undef htonl
|
||||
|
||||
@@ -20,6 +20,7 @@ PROVIDE ( SPI_read_status = 0x400043c8 );
|
||||
PROVIDE ( SPI_write_status = 0x40004400 );
|
||||
PROVIDE ( SPI_write_enable = 0x4000443c );
|
||||
PROVIDE ( Wait_SPI_Idle = 0x4000448c );
|
||||
PROVIDE ( Enable_QMode = 0x400044c0 );
|
||||
PROVIDE ( SPIEraseArea = 0x40004b44 );
|
||||
PROVIDE ( SPIEraseBlock = 0x400049b4 );
|
||||
PROVIDE ( SPIEraseChip = 0x40004984 );
|
||||
|
||||
@@ -5,7 +5,7 @@ MEMORY
|
||||
dport0_0_seg : org = 0x3ff00000, len = 0x10
|
||||
dram0_0_seg : org = 0x3ffe8000, len = 0x14000
|
||||
iram1_0_seg : org = 0x40100000, len = 0x8000
|
||||
irom0_0_seg : org = 0x40209000, len = 0x80000
|
||||
irom0_0_seg : org = 0x40209000, len = 0x87000
|
||||
}
|
||||
|
||||
/* define the top of RAM */
|
||||
@@ -121,6 +121,7 @@ SECTIONS
|
||||
|
||||
*lib/fatfs/*.o*(.literal*, .text*)
|
||||
*/libaxtls.a:(.literal*, .text*)
|
||||
*lib/berkeley-db-1.xx/*.o(.literal*, .text*)
|
||||
*lib/libm/*.o*(.literal*, .text*)
|
||||
*lib/mp-readline/*.o(.literal*, .text*)
|
||||
*lib/netutils/*.o*(.literal*, .text*)
|
||||
|
||||
@@ -259,3 +259,8 @@ int ets_esf_free_bufs(int idx) {
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
extern int mp_stream_errno;
|
||||
int *__errno() {
|
||||
return &mp_stream_errno;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,12 @@ void mp_hal_init(void);
|
||||
void mp_hal_rtc_init(void);
|
||||
|
||||
uint32_t mp_hal_ticks_us(void);
|
||||
__attribute__((always_inline)) static inline uint32_t mp_hal_ticks_cpu(void) {
|
||||
uint32_t ccount;
|
||||
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
|
||||
return ccount;
|
||||
}
|
||||
|
||||
void mp_hal_delay_us(uint32_t);
|
||||
void mp_hal_set_interrupt_char(int c);
|
||||
uint32_t mp_hal_get_cpu_freq(void);
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#if MICROPY_ESP8266_APA102
|
||||
|
||||
#include <stdio.h>
|
||||
#include "c_types.h"
|
||||
#include "eagle_soc.h"
|
||||
@@ -108,3 +111,5 @@ void esp_apa102_write(uint8_t clockPin, uint8_t dataPin, uint8_t *pixels, uint32
|
||||
_esp_apa102_append_additionial_cycles(clockPinMask, dataPinMask, numBytes);
|
||||
_esp_apa102_end_frame(clockPinMask, dataPinMask);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,16 +9,10 @@
|
||||
#include "eagle_soc.h"
|
||||
#include "user_interface.h"
|
||||
#include "espneopixel.h"
|
||||
#include "esp_mphal.h"
|
||||
|
||||
#define NEO_KHZ400 (1)
|
||||
|
||||
static uint32_t _getCycleCount(void) __attribute__((always_inline));
|
||||
static inline uint32_t _getCycleCount(void) {
|
||||
uint32_t ccount;
|
||||
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
|
||||
return ccount;
|
||||
}
|
||||
|
||||
void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz) {
|
||||
|
||||
uint8_t *p, *end, pix, mask;
|
||||
@@ -49,10 +43,10 @@ void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32
|
||||
|
||||
for(t = time0;; t = time0) {
|
||||
if(pix & mask) t = time1; // Bit high duration
|
||||
while(((c = _getCycleCount()) - startTime) < period); // Wait for bit start
|
||||
while(((c = mp_hal_ticks_cpu()) - startTime) < period); // Wait for bit start
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high
|
||||
startTime = c; // Save start time
|
||||
while(((c = _getCycleCount()) - startTime) < t); // Wait high duration
|
||||
while(((c = mp_hal_ticks_cpu()) - startTime) < t); // Wait high duration
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low
|
||||
if(!(mask >>= 1)) { // Next bit/byte
|
||||
if(p >= end) break;
|
||||
@@ -60,5 +54,5 @@ void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32
|
||||
mask = 0x80;
|
||||
}
|
||||
}
|
||||
while((_getCycleCount() - startTime) < period); // Wait for last bit
|
||||
while((mp_hal_ticks_cpu() - startTime) < period); // Wait for last bit
|
||||
}
|
||||
|
||||
@@ -20,6 +20,13 @@ void ets_timer_arm_new(os_timer_t *tim, uint32_t millis, bool repeat, bool is_mi
|
||||
void ets_timer_setfn(os_timer_t *tim, ETSTimerFunc callback, void *cb_data);
|
||||
void ets_timer_disarm(os_timer_t *tim);
|
||||
|
||||
// Opaque structure
|
||||
typedef char MD5_CTX[64];
|
||||
|
||||
void MD5Init(MD5_CTX *context);
|
||||
void MD5Update(MD5_CTX *context, const void *data, unsigned int len);
|
||||
void MD5Final(unsigned char digest[16], MD5_CTX *context);
|
||||
|
||||
// These prototypes are for recent SDKs with "malloc tracking"
|
||||
void *pvPortMalloc(unsigned sz, const char *fname, int line);
|
||||
void vPortFree(void *p, const char *fname, int line);
|
||||
|
||||
@@ -60,6 +60,7 @@ STATIC void mp_reset(void) {
|
||||
MP_STATE_PORT(dupterm_arr_obj) = MP_OBJ_NULL;
|
||||
pin_init0();
|
||||
readline_init0();
|
||||
dupterm_task_init();
|
||||
#if MICROPY_MODULE_FROZEN
|
||||
pyexec_frozen_module("_boot.py");
|
||||
pyexec_file("boot.py");
|
||||
@@ -85,7 +86,6 @@ void init_done(void) {
|
||||
#if MICROPY_REPL_EVENT_DRIVEN
|
||||
pyexec_event_repl_init();
|
||||
#endif
|
||||
dupterm_task_init();
|
||||
|
||||
#if !MICROPY_REPL_EVENT_DRIVEN
|
||||
soft_reset:
|
||||
|
||||
@@ -1,23 +1,40 @@
|
||||
import sys
|
||||
import struct
|
||||
import hashlib
|
||||
|
||||
SEGS_MAX_SIZE = 0x9000
|
||||
|
||||
assert len(sys.argv) == 4
|
||||
|
||||
md5 = hashlib.md5()
|
||||
|
||||
with open(sys.argv[3], 'wb') as fout:
|
||||
|
||||
with open(sys.argv[1], 'rb') as f:
|
||||
data_flash = f.read()
|
||||
fout.write(data_flash)
|
||||
# First 4 bytes include flash size, etc. which may be changed
|
||||
# by esptool.py, etc.
|
||||
md5.update(data_flash[4:])
|
||||
print('flash ', len(data_flash))
|
||||
|
||||
pad = b'\xff' * (SEGS_MAX_SIZE - len(data_flash))
|
||||
fout.write(pad)
|
||||
print('padding ', len(pad))
|
||||
|
||||
with open(sys.argv[2], 'rb') as f:
|
||||
data_rom = f.read()
|
||||
fout.write(data_rom)
|
||||
print('irom0text', len(data_rom))
|
||||
|
||||
pad = b'\xff' * (SEGS_MAX_SIZE - len(data_flash))
|
||||
assert len(pad) >= 4
|
||||
fout.write(pad[:-4])
|
||||
md5.update(pad[:-4])
|
||||
len_data = struct.pack("I", SEGS_MAX_SIZE + len(data_rom))
|
||||
fout.write(len_data)
|
||||
md5.update(len_data)
|
||||
print('padding ', len(pad))
|
||||
|
||||
fout.write(data_rom)
|
||||
md5.update(data_rom)
|
||||
print('irom0text', len(data_rom))
|
||||
|
||||
fout.write(md5.digest())
|
||||
|
||||
print('total ', SEGS_MAX_SIZE + len(data_rom))
|
||||
print('md5 ', md5.hexdigest())
|
||||
|
||||
@@ -633,6 +633,24 @@ STATIC mp_obj_t esp_flash_size(void) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size);
|
||||
|
||||
STATIC mp_obj_t esp_check_fw(void) {
|
||||
MD5_CTX ctx;
|
||||
uint32_t *sz_p = (uint32_t*)0x40208ffc;
|
||||
printf("size: %d\n", *sz_p);
|
||||
MD5Init(&ctx);
|
||||
MD5Update(&ctx, (char*)0x40200004, *sz_p - 4);
|
||||
unsigned char digest[16];
|
||||
MD5Final(digest, &ctx);
|
||||
printf("md5: ");
|
||||
for (int i = 0; i < 16; i++) {
|
||||
printf("%02x", digest[i]);
|
||||
}
|
||||
printf("\n");
|
||||
return mp_obj_new_bool(memcmp(digest, (void*)(0x40200000 + *sz_p), sizeof(digest)) == 0);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_check_fw_obj, esp_check_fw);
|
||||
|
||||
|
||||
STATIC mp_obj_t esp_neopixel_write_(mp_obj_t pin, mp_obj_t buf, mp_obj_t is800k) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
|
||||
@@ -642,6 +660,7 @@ STATIC mp_obj_t esp_neopixel_write_(mp_obj_t pin, mp_obj_t buf, mp_obj_t is800k)
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_neopixel_write_obj, esp_neopixel_write_);
|
||||
|
||||
#if MICROPY_ESP8266_APA102
|
||||
STATIC mp_obj_t esp_apa102_write_(mp_obj_t clockPin, mp_obj_t dataPin, mp_obj_t buf) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
|
||||
@@ -651,6 +670,7 @@ STATIC mp_obj_t esp_apa102_write_(mp_obj_t clockPin, mp_obj_t dataPin, mp_obj_t
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_apa102_write_obj, esp_apa102_write_);
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t esp_freemem() {
|
||||
return MP_OBJ_NEW_SMALL_INT(system_get_free_heap_size());
|
||||
@@ -695,10 +715,13 @@ STATIC const mp_map_elem_t esp_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_getaddrinfo_obj },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&esp_neopixel_write_obj },
|
||||
#if MICROPY_ESP8266_APA102
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_apa102_write), (mp_obj_t)&esp_apa102_write_obj },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_dht_readinto), (mp_obj_t)&dht_readinto_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_freemem), (mp_obj_t)&esp_freemem_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_meminfo), (mp_obj_t)&esp_meminfo_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_check_fw), (mp_obj_t)&esp_check_fw_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_info_obj }, // TODO delete/rename/move elsewhere
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_malloc), (mp_obj_t)&esp_malloc_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_free), (mp_obj_t)&esp_free_obj },
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
@@ -82,6 +83,18 @@ STATIC mp_obj_t machine_unique_id(void) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id);
|
||||
|
||||
STATIC mp_obj_t machine_idle(void) {
|
||||
asm("waiti 0");
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
|
||||
|
||||
STATIC mp_obj_t machine_sleep(void) {
|
||||
printf("Warning: not yet implemented\n");
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_sleep_obj, machine_sleep);
|
||||
|
||||
STATIC mp_obj_t machine_deepsleep(void) {
|
||||
// default to sleep forever
|
||||
uint32_t sleep_us = 0;
|
||||
@@ -222,6 +235,8 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&machine_idle_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_sleep_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) },
|
||||
|
||||
@@ -112,9 +112,11 @@ STATIC void pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_o
|
||||
if (args[ARG_parity].u_obj != MP_OBJ_NULL) {
|
||||
if (args[ARG_parity].u_obj == mp_const_none) {
|
||||
UartDev.parity = UART_NONE_BITS;
|
||||
UartDev.exist_parity = UART_STICK_PARITY_DIS;
|
||||
self->parity = 0;
|
||||
} else {
|
||||
mp_int_t parity = mp_obj_get_int(args[ARG_parity].u_obj);
|
||||
UartDev.exist_parity = UART_STICK_PARITY_EN;
|
||||
if (parity & 1) {
|
||||
UartDev.parity = UART_ODD_BITS;
|
||||
self->parity = 1;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import gc
|
||||
gc.threshold((gc.mem_free() + gc.mem_alloc()) // 4)
|
||||
import uos
|
||||
from flashbdev import bdev
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ import esp
|
||||
class FlashBdev:
|
||||
|
||||
SEC_SIZE = 4096
|
||||
START_SEC = 0x89000 // SEC_SIZE
|
||||
NUM_BLK = 0x73
|
||||
START_SEC = 0x90000 // SEC_SIZE
|
||||
NUM_BLK = 0x6b
|
||||
|
||||
def __init__(self, blocks=NUM_BLK):
|
||||
self.blocks = blocks
|
||||
@@ -64,5 +64,5 @@ size = esp.flash_size()
|
||||
if size < 1024*1024:
|
||||
bdev = None
|
||||
else:
|
||||
# 16K at the flash end is reserved for SDK params storage
|
||||
bdev = FlashBdev((size - 16384) // FlashBdev.SEC_SIZE - FlashBdev.START_SEC)
|
||||
# 20K at the flash end is reserved for SDK params storage
|
||||
bdev = FlashBdev((size - 20480) // FlashBdev.SEC_SIZE - FlashBdev.START_SEC)
|
||||
|
||||
@@ -95,6 +95,11 @@ STATIC mp_obj_t os_mkdir(mp_obj_t path_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir);
|
||||
|
||||
STATIC mp_obj_t os_rmdir(mp_obj_t path_in) {
|
||||
return vfs_proxy_call(MP_QSTR_rmdir, 1, &path_in);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_rmdir_obj, os_rmdir);
|
||||
|
||||
STATIC mp_obj_t os_chdir(mp_obj_t path_in) {
|
||||
return vfs_proxy_call(MP_QSTR_chdir, 1, &path_in);
|
||||
}
|
||||
@@ -155,6 +160,7 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&os_listdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&os_mkdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&os_rmdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&os_chdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&os_getcwd_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&os_remove_obj) },
|
||||
|
||||
@@ -134,8 +134,7 @@ STATIC mp_obj_t time_ticks_us(void) {
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_us_obj, time_ticks_us);
|
||||
|
||||
STATIC mp_obj_t time_ticks_cpu(void) {
|
||||
// TODO
|
||||
return MP_OBJ_NEW_SMALL_INT(0 & MP_SMALL_INT_POSITIVE_MASK);
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_cpu() & MP_SMALL_INT_POSITIVE_MASK);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_cpu_obj, time_ticks_cpu);
|
||||
|
||||
|
||||
@@ -72,7 +72,10 @@
|
||||
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
|
||||
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL)
|
||||
#define MICROPY_WARNINGS (1)
|
||||
#define MICROPY_PY_STR_BYTES_CMP_WARN (1)
|
||||
#define MICROPY_STREAMS_NON_BLOCK (1)
|
||||
#define MICROPY_STREAMS_POSIX_API (1)
|
||||
#define MICROPY_MODULE_FROZEN_STR (1)
|
||||
#define MICROPY_MODULE_FROZEN_MPY (1)
|
||||
#define MICROPY_MODULE_FROZEN_LEXER mp_lexer_new_from_str32
|
||||
@@ -85,6 +88,7 @@
|
||||
#define MICROPY_FATFS_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
|
||||
#define MICROPY_FSUSERMOUNT (1)
|
||||
#define MICROPY_VFS_FAT (1)
|
||||
#define MICROPY_ESP8266_APA102 (1)
|
||||
|
||||
#define MICROPY_EVENT_POLL_HOOK {ets_event_poll();}
|
||||
#define MICROPY_VM_HOOK_COUNT (10)
|
||||
@@ -114,6 +118,8 @@ typedef void *machine_ptr_t; // must be of pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
typedef long mp_off_t;
|
||||
typedef uint32_t sys_prot_t; // for modlwip
|
||||
// ssize_t, off_t as required by POSIX-signatured functions in stream.h
|
||||
#include <sys/types.h>
|
||||
|
||||
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ def setup():
|
||||
with open("/boot.py", "w") as f:
|
||||
f.write("""\
|
||||
# This file is executed on every boot (including wake-boot from deepsleep)
|
||||
#import esp
|
||||
#esp.osdebug(None)
|
||||
import gc
|
||||
#import webrepl
|
||||
#webrepl.start()
|
||||
|
||||
@@ -17,6 +17,8 @@ def main():
|
||||
FREQ_MAP = {0: "40MHZ", 1: "26MHZ", 2: "20MHz", 0xf: "80MHz"}
|
||||
print("Byte @2: %02x" % ROM[2])
|
||||
print("Byte @3: %02x (Flash size: %s Flash freq: %s)" % (ROM[3], SZ_MAP.get(ROM[3] >> 4, "?"), FREQ_MAP.get(ROM[3] & 0xf)))
|
||||
print("Firmware checksum:")
|
||||
print(esp.check_fw())
|
||||
|
||||
print("\nNetworking:")
|
||||
print("STA ifconfig:", network.WLAN(network.STA_IF).ifconfig())
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef _INCLUDED_UART_H_
|
||||
#define _INCLUDED_UART_H_
|
||||
|
||||
#include <eagle_soc.h>
|
||||
|
||||
#define UART0 (0)
|
||||
#define UART1 (1)
|
||||
|
||||
@@ -18,14 +20,14 @@ typedef enum {
|
||||
} UartStopBitsNum;
|
||||
|
||||
typedef enum {
|
||||
UART_NONE_BITS = 0,
|
||||
UART_ODD_BITS = 0,
|
||||
UART_EVEN_BITS = BIT4
|
||||
UART_NONE_BITS = 0,
|
||||
UART_ODD_BITS = BIT0,
|
||||
UART_EVEN_BITS = 0
|
||||
} UartParityMode;
|
||||
|
||||
typedef enum {
|
||||
UART_STICK_PARITY_DIS = 0,
|
||||
UART_STICK_PARITY_EN = BIT3 | BIT5
|
||||
UART_STICK_PARITY_EN = BIT1
|
||||
} UartExistParity;
|
||||
|
||||
typedef enum {
|
||||
|
||||
8
examples/embedding/Makefile
Normal file
8
examples/embedding/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
MPTOP = ../..
|
||||
CFLAGS = -std=c99 -I. -I$(MPTOP) -DNO_QSTR
|
||||
LDFLAGS = -L.
|
||||
|
||||
hello-embed: hello-embed.o -lmicropython
|
||||
|
||||
-lmicropython:
|
||||
$(MAKE) -f $(MPTOP)/examples/embedding/Makefile.upylib MPTOP=$(MPTOP)
|
||||
200
examples/embedding/Makefile.upylib
Normal file
200
examples/embedding/Makefile.upylib
Normal file
@@ -0,0 +1,200 @@
|
||||
MPTOP = ../..
|
||||
-include mpconfigport.mk
|
||||
include $(MPTOP)/py/mkenv.mk
|
||||
|
||||
all: lib
|
||||
|
||||
# OS name, for simple autoconfig
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
# include py core make definitions
|
||||
include $(MPTOP)/py/py.mk
|
||||
|
||||
INC += -I.
|
||||
INC += -I..
|
||||
INC += -I$(MPTOP)
|
||||
INC += -I$(MPTOP)/unix
|
||||
#INC += -I../lib/timeutils
|
||||
INC += -I$(BUILD)
|
||||
|
||||
# compiler settings
|
||||
CWARN = -Wall -Werror
|
||||
CWARN += -Wpointer-arith -Wuninitialized
|
||||
CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
|
||||
|
||||
# Debugging/Optimization
|
||||
ifdef DEBUG
|
||||
CFLAGS += -g
|
||||
COPT = -O0
|
||||
else
|
||||
COPT = -Os #-DNDEBUG
|
||||
# _FORTIFY_SOURCE is a feature in gcc/glibc which is intended to provide extra
|
||||
# security for detecting buffer overflows. Some distros (Ubuntu at the very least)
|
||||
# have it enabled by default.
|
||||
#
|
||||
# gcc already optimizes some printf calls to call puts and/or putchar. When
|
||||
# _FORTIFY_SOURCE is enabled and compiling with -O1 or greater, then some
|
||||
# printf calls will also be optimized to call __printf_chk (in glibc). Any
|
||||
# printfs which get redirected to __printf_chk are then no longer synchronized
|
||||
# with printfs that go through mp_printf.
|
||||
#
|
||||
# In MicroPython, we don't want to use the runtime library's printf but rather
|
||||
# go through mp_printf, so that stdout is properly tied into streams, etc.
|
||||
# This means that we either need to turn off _FORTIFY_SOURCE or provide our
|
||||
# own implementation of __printf_chk. We've chosen to turn off _FORTIFY_SOURCE.
|
||||
# It should also be noted that the use of printf in MicroPython is typically
|
||||
# quite limited anyways (primarily for debug and some error reporting, etc
|
||||
# in the unix version).
|
||||
#
|
||||
# Information about _FORTIFY_SOURCE seems to be rather scarce. The best I could
|
||||
# find was this: https://securityblog.redhat.com/2014/03/26/fortify-and-you/
|
||||
# Original patchset was introduced by
|
||||
# https://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html .
|
||||
#
|
||||
# Turning off _FORTIFY_SOURCE is only required when compiling with -O1 or greater
|
||||
CFLAGS += -U _FORTIFY_SOURCE
|
||||
endif
|
||||
|
||||
# On OSX, 'gcc' is a symlink to clang unless a real gcc is installed.
|
||||
# The unix port of micropython on OSX must be compiled with clang,
|
||||
# while cross-compile ports require gcc, so we test here for OSX and
|
||||
# if necessary override the value of 'CC' set in py/mkenv.mk
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
CC = clang
|
||||
# Use clang syntax for map file
|
||||
LDFLAGS_ARCH = -Wl,-map,$@.map
|
||||
else
|
||||
# Use gcc syntax for map file
|
||||
LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref
|
||||
endif
|
||||
LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA)
|
||||
|
||||
ifeq ($(MICROPY_FORCE_32BIT),1)
|
||||
# Note: you may need to install i386 versions of dependency packages,
|
||||
# starting with linux-libc-dev:i386
|
||||
ifeq ($(MICROPY_PY_FFI),1)
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
CFLAGS_MOD += -I/usr/include/i686-linux-gnu
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(MICROPY_USE_READLINE),1)
|
||||
INC += -I../lib/mp-readline
|
||||
CFLAGS_MOD += -DMICROPY_USE_READLINE=1
|
||||
LIB_SRC_C_EXTRA += mp-readline/readline.c
|
||||
endif
|
||||
ifeq ($(MICROPY_USE_READLINE),2)
|
||||
CFLAGS_MOD += -DMICROPY_USE_READLINE=2
|
||||
LDFLAGS_MOD += -lreadline
|
||||
# the following is needed for BSD
|
||||
#LDFLAGS_MOD += -ltermcap
|
||||
endif
|
||||
ifeq ($(MICROPY_PY_TIME),1)
|
||||
CFLAGS_MOD += -DMICROPY_PY_TIME=1
|
||||
SRC_MOD += modtime.c
|
||||
endif
|
||||
ifeq ($(MICROPY_PY_TERMIOS),1)
|
||||
CFLAGS_MOD += -DMICROPY_PY_TERMIOS=1
|
||||
SRC_MOD += modtermios.c
|
||||
endif
|
||||
ifeq ($(MICROPY_PY_SOCKET),1)
|
||||
CFLAGS_MOD += -DMICROPY_PY_SOCKET=1
|
||||
SRC_MOD += modsocket.c
|
||||
endif
|
||||
|
||||
ifeq ($(MICROPY_PY_FFI),1)
|
||||
|
||||
ifeq ($(MICROPY_STANDALONE),1)
|
||||
LIBFFI_CFLAGS_MOD := -I$(shell ls -1d ../lib/libffi/build_dir/out/lib/libffi-*/include)
|
||||
ifeq ($(MICROPY_FORCE_32BIT),1)
|
||||
LIBFFI_LDFLAGS_MOD = ../lib/libffi/build_dir/out/lib32/libffi.a
|
||||
else
|
||||
LIBFFI_LDFLAGS_MOD = ../lib/libffi/build_dir/out/lib/libffi.a
|
||||
endif
|
||||
else
|
||||
LIBFFI_CFLAGS_MOD := $(shell pkg-config --cflags libffi)
|
||||
LIBFFI_LDFLAGS_MOD := $(shell pkg-config --libs libffi)
|
||||
endif
|
||||
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
LIBFFI_LDFLAGS_MOD += -ldl
|
||||
endif
|
||||
|
||||
CFLAGS_MOD += $(LIBFFI_CFLAGS_MOD) -DMICROPY_PY_FFI=1
|
||||
LDFLAGS_MOD += $(LIBFFI_LDFLAGS_MOD)
|
||||
SRC_MOD += modffi.c
|
||||
endif
|
||||
|
||||
MAIN_C = main.c
|
||||
|
||||
# source files
|
||||
SRC_C = $(addprefix $(MPTOP)/unix/,\
|
||||
$(MAIN_C) \
|
||||
gccollect.c \
|
||||
unix_mphal.c \
|
||||
input.c \
|
||||
file.c \
|
||||
modmachine.c \
|
||||
modos.c \
|
||||
moduselect.c \
|
||||
alloc.c \
|
||||
coverage.c \
|
||||
fatfs_port.c \
|
||||
$(SRC_MOD) \
|
||||
)
|
||||
|
||||
LIB_SRC_C = $(addprefix lib/,\
|
||||
$(LIB_SRC_C_EXTRA) \
|
||||
utils/printf.c \
|
||||
timeutils/timeutils.c \
|
||||
)
|
||||
|
||||
ifeq ($(MICROPY_FATFS),1)
|
||||
LIB_SRC_C += $(addprefix lib/,\
|
||||
fatfs/ff.c \
|
||||
fatfs/option/ccsbcs.c \
|
||||
)
|
||||
endif
|
||||
|
||||
OBJ = $(PY_O)
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(STMHAL_SRC_C:.c=.o))
|
||||
|
||||
# List of sources for qstr extraction
|
||||
SRC_QSTR += $(SRC_C) $(LIB_SRC_C)
|
||||
# Append any auto-generated sources that are needed by sources listed in
|
||||
# SRC_QSTR
|
||||
SRC_QSTR_AUTO_DEPS +=
|
||||
|
||||
include $(MPTOP)/py/mkrules.mk
|
||||
|
||||
# Value of configure's --host= option (required for cross-compilation).
|
||||
# Deduce it from CROSS_COMPILE by default, but can be overriden.
|
||||
ifneq ($(CROSS_COMPILE),)
|
||||
CROSS_COMPILE_HOST = --host=$(patsubst %-,%,$(CROSS_COMPILE))
|
||||
else
|
||||
CROSS_COMPILE_HOST =
|
||||
endif
|
||||
|
||||
deplibs: libffi axtls
|
||||
|
||||
# install-exec-recursive & install-data-am targets are used to avoid building
|
||||
# docs and depending on makeinfo
|
||||
libffi:
|
||||
cd ../lib/libffi; git clean -d -x -f
|
||||
cd ../lib/libffi; ./autogen.sh
|
||||
mkdir -p ../lib/libffi/build_dir; cd ../lib/libffi/build_dir; \
|
||||
../configure $(CROSS_COMPILE_HOST) --prefix=$$PWD/out CC="$(CC)" CXX="$(CXX)" LD="$(LD)"; \
|
||||
make install-exec-recursive; make -C include install-data-am
|
||||
|
||||
axtls: ../lib/axtls/README
|
||||
cd ../lib/axtls; cp config/upyconfig config/.config
|
||||
cd ../lib/axtls; make oldconfig -B
|
||||
cd ../lib/axtls; make clean
|
||||
cd ../lib/axtls; make all CC="$(CC)" LD="$(LD)"
|
||||
|
||||
../lib/axtls/README:
|
||||
@echo "You cloned without --recursive, fetching submodules for you."
|
||||
(cd ..; git submodule update --init --recursive)
|
||||
66
examples/embedding/README
Normal file
66
examples/embedding/README
Normal file
@@ -0,0 +1,66 @@
|
||||
Example of embedding MicroPython in a standlone C application
|
||||
=============================================================
|
||||
|
||||
This directory contains a (very simple!) example of how to embed a MicroPython
|
||||
in an existing C application.
|
||||
|
||||
A C application is represented by the file hello-embed.c. It executes a simple
|
||||
Python statement which prints to the standard output.
|
||||
|
||||
|
||||
Building the example
|
||||
--------------------
|
||||
|
||||
Build the example is as simple as running:
|
||||
|
||||
make
|
||||
|
||||
It's worth to trace what's happening behind the scenes though:
|
||||
|
||||
1. As a first step, a MicroPython library is built. This is handled by a
|
||||
seperate makefile, Makefile.upylib. It is more or less complex, but the
|
||||
good news is that you won't need to change anything in it, just use it
|
||||
as is, the main Makefile shows how. What may need editing though is
|
||||
MicroPython configuration file. MicroPython is highly configurable, so
|
||||
you would need to build a library suiting your application well, while
|
||||
not bloating its size. Check the options in the file "mpconfigport.h".
|
||||
Included is a copy of "minimal" Unix port, which should be good start
|
||||
for minimal embedding. For list of all available options, see py/mpconfig.h.
|
||||
|
||||
2. Once the library is built, your application is compiled and linked with
|
||||
the MicroPython library produced in the previous step. The main Makefile
|
||||
is very simple and shows that changes you would need to do to your
|
||||
application's Makefile (or other build configuration) are also simple:
|
||||
|
||||
a) You would need to use C99 standard (you're using 15+ years old standard
|
||||
already, not a 25+ years old one, right?).
|
||||
|
||||
b) You need to provide path to MicroPython's top-level dir, for includes.
|
||||
|
||||
c) You need to include -DNO_QSTR compile-time flag.
|
||||
|
||||
d) Otherwise, just link with micropython library produced in step 1.
|
||||
|
||||
|
||||
Out of tree build
|
||||
-----------------
|
||||
|
||||
This example set up to work out of the box, being part of the MicroPython
|
||||
tree. Your application of course will be outside of its tree, but the
|
||||
only thing you need to do is to pass MPTOP variable pointing to
|
||||
MicroPython directory to both Makefiles (in this example, the main Makefile
|
||||
automatically pass it to Makefile.upylib; in your own Makefile, don't forget
|
||||
to use suitable value).
|
||||
|
||||
A practical way to embed MicroPython in your application is to include it
|
||||
as a git submodule. Suppose you included it as libs/micropython. Then in
|
||||
your main Makefile you would have something like:
|
||||
|
||||
~~~
|
||||
MPTOP = libs/micropython
|
||||
|
||||
my_app: $(MY_OBJS) -lmicropython
|
||||
|
||||
-lmicropython:
|
||||
$(MAKE) -f $(MPTOP)/examples/embedding/Makefile.upylib MPTOP=$(MPTOP)
|
||||
~~~
|
||||
74
examples/embedding/hello-embed.c
Normal file
74
examples/embedding/hello-embed.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "py/compile.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/stackctrl.h"
|
||||
|
||||
static char heap[16384];
|
||||
|
||||
mp_obj_t execute_from_lexer(mp_lexer_t *lex) {
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
mp_parse_tree_t pt = mp_parse(lex, MP_PARSE_FILE_INPUT);
|
||||
mp_obj_t module_fun = mp_compile(&pt, lex->source_name, MP_EMIT_OPT_NONE, false);
|
||||
mp_call_function_0(module_fun);
|
||||
nlr_pop();
|
||||
return 0;
|
||||
} else {
|
||||
// uncaught exception
|
||||
return (mp_obj_t)nlr.ret_val;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Initialized stack limit
|
||||
mp_stack_set_limit(40000 * (BYTES_PER_WORD / 4));
|
||||
// Initialize heap
|
||||
gc_init(heap, heap + sizeof(heap));
|
||||
// Initialize interpreter
|
||||
mp_init();
|
||||
|
||||
const char str[] = "print('Hello world of easy embedding!')";
|
||||
mp_lexer_t *lex = mp_lexer_new_from_str_len(0/*MP_QSTR_*/, str, strlen(str), false);
|
||||
if (execute_from_lexer(lex)) {
|
||||
printf("Error\n");
|
||||
}
|
||||
}
|
||||
|
||||
uint mp_import_stat(const char *path) {
|
||||
return MP_IMPORT_STAT_NO_EXIST;
|
||||
}
|
||||
|
||||
void nlr_jump_fail(void *val) {
|
||||
printf("FATAL: uncaught NLR %p\n", val);
|
||||
exit(1);
|
||||
}
|
||||
1
examples/embedding/mpconfigport.h
Symbolic link
1
examples/embedding/mpconfigport.h
Symbolic link
@@ -0,0 +1 @@
|
||||
mpconfigport_minimal.h
|
||||
138
examples/embedding/mpconfigport_minimal.h
Normal file
138
examples/embedding/mpconfigport_minimal.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// options to control how Micro Python is built
|
||||
|
||||
#define MICROPY_ALLOC_PATH_MAX (PATH_MAX)
|
||||
#define MICROPY_ENABLE_GC (1)
|
||||
#define MICROPY_ENABLE_FINALISER (0)
|
||||
#define MICROPY_STACK_CHECK (0)
|
||||
#define MICROPY_COMP_CONST (0)
|
||||
#define MICROPY_MEM_STATS (0)
|
||||
#define MICROPY_DEBUG_PRINTERS (0)
|
||||
#define MICROPY_HELPER_REPL (1)
|
||||
#define MICROPY_HELPER_LEXER_UNIX (1)
|
||||
#define MICROPY_ENABLE_SOURCE_LINE (0)
|
||||
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
|
||||
#define MICROPY_WARNINGS (0)
|
||||
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0)
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
|
||||
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
|
||||
#define MICROPY_STREAMS_NON_BLOCK (0)
|
||||
#define MICROPY_OPT_COMPUTED_GOTO (0)
|
||||
#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0)
|
||||
#define MICROPY_CAN_OVERRIDE_BUILTINS (0)
|
||||
#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0)
|
||||
#define MICROPY_CPYTHON_COMPAT (0)
|
||||
#define MICROPY_PY_BUILTINS_BYTEARRAY (0)
|
||||
#define MICROPY_PY_BUILTINS_MEMORYVIEW (0)
|
||||
#define MICROPY_PY_BUILTINS_COMPILE (0)
|
||||
#define MICROPY_PY_BUILTINS_ENUMERATE (0)
|
||||
#define MICROPY_PY_BUILTINS_FILTER (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_STR_UNICODE (0)
|
||||
#define MICROPY_PY_BUILTINS_PROPERTY (0)
|
||||
#define MICROPY_PY_BUILTINS_MIN_MAX (0)
|
||||
#define MICROPY_PY___FILE__ (0)
|
||||
#define MICROPY_PY_MICROPYTHON_MEM_INFO (0)
|
||||
#define MICROPY_PY_GC (0)
|
||||
#define MICROPY_PY_GC_COLLECT_RETVAL (0)
|
||||
#define MICROPY_PY_ARRAY (0)
|
||||
#define MICROPY_PY_COLLECTIONS (0)
|
||||
#define MICROPY_PY_MATH (0)
|
||||
#define MICROPY_PY_CMATH (0)
|
||||
#define MICROPY_PY_IO (0)
|
||||
#define MICROPY_PY_IO_FILEIO (0)
|
||||
#define MICROPY_PY_STRUCT (0)
|
||||
#define MICROPY_PY_SYS (1)
|
||||
#define MICROPY_PY_SYS_EXIT (0)
|
||||
#define MICROPY_PY_SYS_PLATFORM "linux"
|
||||
#define MICROPY_PY_SYS_MAXSIZE (0)
|
||||
#define MICROPY_PY_SYS_STDFILES (0)
|
||||
#define MICROPY_PY_CMATH (0)
|
||||
#define MICROPY_PY_UCTYPES (0)
|
||||
#define MICROPY_PY_UZLIB (0)
|
||||
#define MICROPY_PY_UJSON (0)
|
||||
#define MICROPY_PY_URE (0)
|
||||
#define MICROPY_PY_UHEAPQ (0)
|
||||
#define MICROPY_PY_UHASHLIB (0)
|
||||
#define MICROPY_PY_UBINASCII (0)
|
||||
|
||||
extern const struct _mp_obj_module_t mp_module_os;
|
||||
|
||||
#define MICROPY_PORT_BUILTIN_MODULES \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&mp_module_os }, \
|
||||
|
||||
#define MICROPY_PORT_ROOT_POINTERS \
|
||||
mp_obj_t keyboard_interrupt_obj;
|
||||
|
||||
//////////////////////////////////////////
|
||||
// Do not change anything beyond this line
|
||||
//////////////////////////////////////////
|
||||
|
||||
// Define to 1 to use undertested inefficient GC helper implementation
|
||||
// (if more efficient arch-specific one is not available).
|
||||
#ifndef MICROPY_GCREGS_SETJMP
|
||||
#ifdef __mips__
|
||||
#define MICROPY_GCREGS_SETJMP (1)
|
||||
#else
|
||||
#define MICROPY_GCREGS_SETJMP (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// type definitions for the specific machine
|
||||
|
||||
#ifdef __LP64__
|
||||
typedef long mp_int_t; // must be pointer size
|
||||
typedef unsigned long mp_uint_t; // must be pointer size
|
||||
#else
|
||||
// These are definitions for machines where sizeof(int) == sizeof(void*),
|
||||
// regardless for actual size.
|
||||
typedef int mp_int_t; // must be pointer size
|
||||
typedef unsigned int mp_uint_t; // must be pointer size
|
||||
#endif
|
||||
|
||||
#define BYTES_PER_WORD sizeof(mp_int_t)
|
||||
|
||||
// Cannot include <sys/types.h>, as it may lead to symbol name clashes
|
||||
#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__)
|
||||
typedef long long mp_off_t;
|
||||
#else
|
||||
typedef long mp_off_t;
|
||||
#endif
|
||||
|
||||
typedef void *machine_ptr_t; // must be of pointer size
|
||||
typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
|
||||
// We need to provide a declaration/definition of alloca()
|
||||
#ifdef __FreeBSD__
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
@@ -24,5 +24,7 @@ def main(use_stream=False):
|
||||
s.send(b"GET / HTTP/1.0\n\n")
|
||||
print(s.recv(4096))
|
||||
|
||||
s.close()
|
||||
|
||||
|
||||
main()
|
||||
|
||||
@@ -32,5 +32,7 @@ def main(use_stream=True):
|
||||
s.send(b"GET / HTTP/1.0\n\n")
|
||||
print(s.recv(4096))
|
||||
|
||||
s.close()
|
||||
|
||||
|
||||
main()
|
||||
|
||||
@@ -10,7 +10,7 @@ HTTP/1.0 200 OK
|
||||
Hello #%d from MicroPython!
|
||||
"""
|
||||
|
||||
def main(use_stream=False):
|
||||
def main(micropython_optimize=False):
|
||||
s = socket.socket()
|
||||
|
||||
# Binding to all interfaces - server will be accessible to other hosts!
|
||||
@@ -26,20 +26,37 @@ def main(use_stream=False):
|
||||
counter = 0
|
||||
while True:
|
||||
res = s.accept()
|
||||
client_s = res[0]
|
||||
client_sock = res[0]
|
||||
client_addr = res[1]
|
||||
print("Client address:", client_addr)
|
||||
print("Client socket:", client_s)
|
||||
print("Request:")
|
||||
if use_stream:
|
||||
# MicroPython socket objects support stream (aka file) interface
|
||||
# directly.
|
||||
print(client_s.read(4096))
|
||||
client_s.write(CONTENT % counter)
|
||||
print("Client socket:", client_sock)
|
||||
|
||||
if not micropython_optimize:
|
||||
# To read line-oriented protocol (like HTTP) from a socket (and
|
||||
# avoid short read problem), it must be wrapped in a stream (aka
|
||||
# file-like) object. That's how you do it in CPython:
|
||||
client_stream = client_sock.makefile("rwb")
|
||||
else:
|
||||
print(client_s.recv(4096))
|
||||
client_s.send(CONTENT % counter)
|
||||
client_s.close()
|
||||
# .. but MicroPython socket objects support stream interface
|
||||
# directly, so calling .makefile() method is not required. If
|
||||
# you develop application which will run only on MicroPython,
|
||||
# especially on a resource-constrained embedded device, you
|
||||
# may take this shortcut to save resources.
|
||||
client_stream = client_sock
|
||||
|
||||
print("Request:")
|
||||
req = client_stream.readline()
|
||||
print(req)
|
||||
while True:
|
||||
h = client_stream.readline()
|
||||
if h == b"" or h == b"\r\n":
|
||||
break
|
||||
print(h)
|
||||
client_stream.write(CONTENT % counter)
|
||||
|
||||
client_stream.close()
|
||||
if not micropython_optimize:
|
||||
client_sock.close()
|
||||
counter += 1
|
||||
print()
|
||||
|
||||
|
||||
38
examples/network/http_server_simplistic.py
Normal file
38
examples/network/http_server_simplistic.py
Normal file
@@ -0,0 +1,38 @@
|
||||
try:
|
||||
import usocket as socket
|
||||
except:
|
||||
import socket
|
||||
|
||||
|
||||
CONTENT = b"""\
|
||||
HTTP/1.0 200 OK
|
||||
|
||||
Hello #%d from MicroPython!
|
||||
"""
|
||||
|
||||
def main():
|
||||
s = socket.socket()
|
||||
ai = socket.getaddrinfo("0.0.0.0", 8080)
|
||||
addr = ai[0][-1]
|
||||
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
s.bind(addr)
|
||||
s.listen(5)
|
||||
print("Listening, connect your browser to http://<this_host>:8080/")
|
||||
|
||||
counter = 0
|
||||
while True:
|
||||
res = s.accept()
|
||||
client_s = res[0]
|
||||
client_addr = res[1]
|
||||
req = client_s.recv(4096)
|
||||
print("Request:")
|
||||
print(req)
|
||||
client_s.send(CONTENT % counter)
|
||||
client_s.close()
|
||||
counter += 1
|
||||
print()
|
||||
|
||||
|
||||
main()
|
||||
76
examples/network/http_server_simplistic_commented.py
Normal file
76
examples/network/http_server_simplistic_commented.py
Normal file
@@ -0,0 +1,76 @@
|
||||
#
|
||||
# MicroPython http_server_simplistic.py example
|
||||
#
|
||||
# This example shows how to write the smallest possible HTTP
|
||||
# server in MicroPython. With comments and convenience code
|
||||
# removed, this example can be compressed literally to ten
|
||||
# lines. There's a catch though - read comments below for
|
||||
# details, and use this code only for quick hacks, preferring
|
||||
# http_server.py for "real thing".
|
||||
#
|
||||
try:
|
||||
import usocket as socket
|
||||
except:
|
||||
import socket
|
||||
|
||||
|
||||
CONTENT = b"""\
|
||||
HTTP/1.0 200 OK
|
||||
|
||||
Hello #%d from MicroPython!
|
||||
"""
|
||||
|
||||
def main():
|
||||
s = socket.socket()
|
||||
|
||||
# Bind to (allow to be connected on ) all interfaces. This means
|
||||
# this server will be accessible to other hosts on your local
|
||||
# network, and if your server has direct (non-firewalled) connection
|
||||
# to the Internet, then to anyone on the Internet. We bind to all
|
||||
# interfaces to let this example work easily on embedded MicroPython
|
||||
# targets, which you will likely access from another machine on your
|
||||
# local network. Take care when running this on an Internet-connected
|
||||
# machine though! Replace "0.0.0.0" with "127.0.0.1" if in doubt, to
|
||||
# make the server accessible only on the machine it runs on.
|
||||
ai = socket.getaddrinfo("0.0.0.0", 8080)
|
||||
print("Bind address info:", ai)
|
||||
addr = ai[0][-1]
|
||||
|
||||
# A port on which a socket listened remains inactive during some time.
|
||||
# This means that if you run this sample, terminate it, and run again
|
||||
# you will likely get an error. To avoid this timeout, set SO_REUSEADDR
|
||||
# socket option.
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
s.bind(addr)
|
||||
s.listen(5)
|
||||
print("Listening, connect your browser to http://<this_host>:8080/")
|
||||
|
||||
counter = 0
|
||||
while True:
|
||||
res = s.accept()
|
||||
client_s = res[0]
|
||||
client_addr = res[1]
|
||||
print("Client address:", client_addr)
|
||||
print("Client socket:", client_s)
|
||||
# We assume here that .recv() call will read entire HTTP request
|
||||
# from client. This is usually true, at least on "big OS" systems
|
||||
# like Linux/MacOS/Windows. But that doesn't have to be true in
|
||||
# all cases, in particular on embedded systems, when there can
|
||||
# easily be "short recv", where it returns much less than requested
|
||||
# data size. That's why this example is called "simplistic" - it
|
||||
# shows that writing a web server in Python that *usually works* is
|
||||
# ten lines of code, and you can use this technique for quick hacks
|
||||
# and experimentation. But don't do it like that in production
|
||||
# applications - instead, parse HTTP request properly, as shown
|
||||
# by http_server.py example.
|
||||
req = client_s.recv(4096)
|
||||
print("Request:")
|
||||
print(req)
|
||||
client_s.send(CONTENT % counter)
|
||||
client_s.close()
|
||||
counter += 1
|
||||
print()
|
||||
|
||||
|
||||
main()
|
||||
@@ -42,8 +42,13 @@ def main(use_stream=True):
|
||||
# next request they issue will likely be more well-behaving and
|
||||
# will succeed.
|
||||
try:
|
||||
req = client_s.read(4096)
|
||||
req = client_s.readline()
|
||||
print(req)
|
||||
while True:
|
||||
h = client_s.readline()
|
||||
if h == b"" or h == b"\r\n":
|
||||
break
|
||||
print(h)
|
||||
if req:
|
||||
client_s.write(CONTENT % counter)
|
||||
except Exception as e:
|
||||
|
||||
9
examples/unix/machine_bios.py
Normal file
9
examples/unix/machine_bios.py
Normal file
@@ -0,0 +1,9 @@
|
||||
# This example shows how to access Video BIOS memory area via machine.mem
|
||||
# It requires root privilege and x86 legacy harfware (which has mentioned
|
||||
# Video BIOS at all).
|
||||
# It is expected to print 0xaa55, which is a signature at the start of
|
||||
# Video BIOS.
|
||||
|
||||
import umachine as machine
|
||||
|
||||
print(hex(machine.mem16[0xc0000]))
|
||||
@@ -31,6 +31,8 @@
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/runtime0.h"
|
||||
#include "py/stream.h"
|
||||
|
||||
#if MICROPY_PY_BTREE
|
||||
|
||||
@@ -291,6 +293,24 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t btree_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in);
|
||||
switch (op) {
|
||||
case MP_BINARY_OP_IN: {
|
||||
mp_uint_t v;
|
||||
DBT key, val;
|
||||
key.data = (void*)mp_obj_str_get_data(rhs_in, &v);
|
||||
key.size = v;
|
||||
int res = __bt_get(self->db, &key, &val, 0);
|
||||
CHECK_ERROR(res);
|
||||
return mp_obj_new_bool(res != RET_SPECIAL);
|
||||
}
|
||||
default:
|
||||
// op not supported
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC const mp_rom_map_elem_t btree_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&btree_close_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&btree_get_obj) },
|
||||
@@ -310,27 +330,47 @@ STATIC const mp_obj_type_t btree_type = {
|
||||
.print = btree_print,
|
||||
.getiter = btree_getiter,
|
||||
.iternext = btree_iternext,
|
||||
.binary_op = btree_binary_op,
|
||||
.subscr = btree_subscr,
|
||||
.locals_dict = (void*)&btree_locals_dict,
|
||||
};
|
||||
|
||||
STATIC FILEVTABLE btree_stream_fvtable = {
|
||||
mp_stream_posix_read,
|
||||
mp_stream_posix_write,
|
||||
mp_stream_posix_lseek,
|
||||
mp_stream_posix_fsync
|
||||
};
|
||||
|
||||
STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||
{ MP_QSTR_flags, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_cachesize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_pagesize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_minkeypage, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
};
|
||||
|
||||
const char *fname = NULL;
|
||||
if (pos_args[0] != mp_const_none) {
|
||||
fname = mp_obj_str_get_str(pos_args[0]);
|
||||
}
|
||||
// Make sure we got a stream object
|
||||
mp_get_stream_raise(pos_args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
|
||||
|
||||
struct {
|
||||
mp_arg_val_t server_side;
|
||||
mp_arg_val_t flags;
|
||||
mp_arg_val_t cachesize;
|
||||
mp_arg_val_t pagesize;
|
||||
mp_arg_val_t minkeypage;
|
||||
} args;
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
|
||||
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
|
||||
BTREEINFO openinfo = {0};
|
||||
openinfo.flags = args.flags.u_int;
|
||||
openinfo.cachesize = args.cachesize.u_int;
|
||||
openinfo.psize = args.pagesize.u_int;
|
||||
openinfo.minkeypage = args.minkeypage.u_int;
|
||||
|
||||
DB *db = __bt_open(fname, /*flags*/O_CREAT | O_RDWR, /*mode*/0770, /*openinfo*/NULL, /*dflags*/0);
|
||||
DB *db = __bt_open(pos_args[0], &btree_stream_fvtable, &openinfo, /*dflags*/0);
|
||||
if (db == NULL) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno)));
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(btree_new(db));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_btree_open_obj, 1, mod_btree_open);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
|
||||
#if MICROPY_PY_USSL
|
||||
#if MICROPY_PY_USSL && MICROPY_SSL_AXTLS
|
||||
|
||||
#include "ssl.h"
|
||||
|
||||
@@ -122,14 +122,21 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
|
||||
return r;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
|
||||
// Currently supports only blocking mode
|
||||
(void)self_in;
|
||||
if (!mp_obj_is_true(flag_in)) {
|
||||
mp_not_implemented("");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
|
||||
|
||||
STATIC mp_obj_t socket_close(mp_obj_t self_in) {
|
||||
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
ssl_free(self->ssl_sock);
|
||||
ssl_ctx_free(self->ssl_ctx);
|
||||
|
||||
mp_obj_t dest[2];
|
||||
mp_load_method(self->sock, MP_QSTR_close, dest);
|
||||
return mp_call_method_n_kw(0, 0, dest);
|
||||
return mp_stream_close(self->sock);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close);
|
||||
|
||||
@@ -139,6 +146,7 @@ STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socket_close_obj) },
|
||||
};
|
||||
|
||||
@@ -192,34 +200,4 @@ const mp_obj_module_t mp_module_ussl = {
|
||||
.globals = (mp_obj_dict_t*)&mp_module_ssl_globals,
|
||||
};
|
||||
|
||||
|
||||
// These functions might be split to stream_posix.c. They are referenced by
|
||||
// axtls os_port.h .
|
||||
ssize_t mp_stream_posix_write(void *sock_obj, const void *buf, size_t len);
|
||||
ssize_t mp_stream_posix_read(void *sock_obj, void *buf, size_t len);
|
||||
|
||||
int mp_stream_errno;
|
||||
|
||||
ssize_t mp_stream_posix_write(void *sock_obj, const void *buf, size_t len) {
|
||||
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)sock_obj;
|
||||
const mp_stream_p_t *stream_p = o->type->protocol;
|
||||
mp_uint_t out_sz = stream_p->write(o, buf, len, &mp_stream_errno);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
return -1;
|
||||
} else {
|
||||
return out_sz;
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t mp_stream_posix_read(void *sock_obj, void *buf, size_t len) {
|
||||
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)sock_obj;
|
||||
const mp_stream_p_t *stream_p = o->type->protocol;
|
||||
mp_uint_t out_sz = stream_p->read(o, buf, len, &mp_stream_errno);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
return -1;
|
||||
} else {
|
||||
return out_sz;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // MICROPY_PY_USSL
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "py/mphal.h"
|
||||
#endif
|
||||
#include "extmod/modwebsocket.h"
|
||||
#include "genhdr/mpversion.h"
|
||||
|
||||
#if MICROPY_PY_WEBREPL
|
||||
|
||||
@@ -57,7 +58,7 @@ struct webrepl_file {
|
||||
char fname[64];
|
||||
} __attribute__((packed));
|
||||
|
||||
enum { PUT_FILE = 1, GET_FILE, LIST_DIR };
|
||||
enum { PUT_FILE = 1, GET_FILE, GET_VER };
|
||||
enum { STATE_PASSWD, STATE_NORMAL };
|
||||
|
||||
typedef struct _mp_obj_webrepl_t {
|
||||
@@ -77,12 +78,6 @@ STATIC char denied_prompt[] = "\r\nAccess denied\r\n";
|
||||
|
||||
STATIC char webrepl_passwd[10];
|
||||
|
||||
static inline void close_meth(mp_obj_t stream) {
|
||||
mp_obj_t dest[2];
|
||||
mp_load_method(stream, MP_QSTR_close, dest);
|
||||
mp_call_method_n_kw(0, 0, dest);
|
||||
}
|
||||
|
||||
STATIC void write_webrepl(mp_obj_t websock, const void *buf, size_t len) {
|
||||
const mp_stream_p_t *sock_stream = mp_get_stream_raise(websock, MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
|
||||
int err;
|
||||
@@ -117,7 +112,37 @@ STATIC mp_obj_t webrepl_make_new(const mp_obj_type_t *type, size_t n_args, size_
|
||||
return o;
|
||||
}
|
||||
|
||||
STATIC int write_file_chunk(mp_obj_webrepl_t *self) {
|
||||
const mp_stream_p_t *file_stream =
|
||||
mp_get_stream_raise(self->cur_file, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
|
||||
byte readbuf[2 + 256];
|
||||
int err;
|
||||
mp_uint_t out_sz = file_stream->read(self->cur_file, readbuf + 2, sizeof(readbuf) - 2, &err);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
return out_sz;
|
||||
}
|
||||
readbuf[0] = out_sz;
|
||||
readbuf[1] = out_sz >> 8;
|
||||
DEBUG_printf("webrepl: Sending %d bytes of file\n", out_sz);
|
||||
write_webrepl(self->sock, readbuf, 2 + out_sz);
|
||||
return out_sz;
|
||||
}
|
||||
|
||||
STATIC void handle_op(mp_obj_webrepl_t *self) {
|
||||
|
||||
// Handle operations not requiring opened file
|
||||
|
||||
switch (self->hdr.type) {
|
||||
case GET_VER: {
|
||||
static char ver[] = {MICROPY_VERSION_MAJOR, MICROPY_VERSION_MINOR, MICROPY_VERSION_MICRO};
|
||||
write_webrepl(self->sock, ver, sizeof(ver));
|
||||
self->hdr_to_recv = sizeof(struct webrepl_file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle operations requiring opened file
|
||||
|
||||
mp_obj_t open_args[2] = {
|
||||
mp_obj_new_str(self->hdr.fname, strlen(self->hdr.fname), false),
|
||||
MP_OBJ_NEW_QSTR(MP_QSTR_rb)
|
||||
@@ -128,8 +153,6 @@ STATIC void handle_op(mp_obj_webrepl_t *self) {
|
||||
}
|
||||
|
||||
self->cur_file = mp_builtin_open(2, open_args, (mp_map_t*)&mp_const_empty_map);
|
||||
const mp_stream_p_t *file_stream =
|
||||
mp_get_stream_raise(self->cur_file, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
|
||||
|
||||
#if 0
|
||||
struct mp_stream_seek_t seek = { .offset = self->hdr.offset, .whence = 0 };
|
||||
@@ -143,24 +166,7 @@ STATIC void handle_op(mp_obj_webrepl_t *self) {
|
||||
if (self->hdr.type == PUT_FILE) {
|
||||
self->data_to_recv = self->hdr.size;
|
||||
} else if (self->hdr.type == GET_FILE) {
|
||||
byte readbuf[2 + 256];
|
||||
int err;
|
||||
// TODO: It's not ideal that we block connection while sending file
|
||||
// and don't process any input.
|
||||
while (1) {
|
||||
mp_uint_t out_sz = file_stream->read(self->cur_file, readbuf + 2, sizeof(readbuf) - 2, &err);
|
||||
assert(out_sz != MP_STREAM_ERROR);
|
||||
readbuf[0] = out_sz;
|
||||
readbuf[1] = out_sz >> 8;
|
||||
DEBUG_printf("webrepl: Sending %d bytes of file\n", out_sz);
|
||||
write_webrepl(self->sock, readbuf, 2 + out_sz);
|
||||
if (out_sz == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
write_webrepl_resp(self->sock, 0);
|
||||
self->hdr_to_recv = sizeof(struct webrepl_file);
|
||||
self->data_to_recv = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,17 +254,27 @@ STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int
|
||||
buf_sz += sz;
|
||||
}
|
||||
|
||||
DEBUG_printf("webrepl: Writing %lu bytes to file\n", buf_sz);
|
||||
int err;
|
||||
mp_uint_t res = mp_stream_write_exactly(self->cur_file, filebuf, buf_sz, &err);
|
||||
if (err != 0 || res != buf_sz) {
|
||||
assert(0);
|
||||
if (self->hdr.type == PUT_FILE) {
|
||||
DEBUG_printf("webrepl: Writing %lu bytes to file\n", buf_sz);
|
||||
int err;
|
||||
mp_uint_t res = mp_stream_write_exactly(self->cur_file, filebuf, buf_sz, &err);
|
||||
if (err != 0 || res != buf_sz) {
|
||||
assert(0);
|
||||
}
|
||||
} else if (self->hdr.type == GET_FILE) {
|
||||
assert(buf_sz == 1);
|
||||
assert(self->data_to_recv == 0);
|
||||
assert(filebuf[0] == 0);
|
||||
mp_uint_t out_sz = write_file_chunk(self);
|
||||
if (out_sz != 0) {
|
||||
self->data_to_recv = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->data_to_recv == 0) {
|
||||
close_meth(self->cur_file);
|
||||
mp_stream_close(self->cur_file);
|
||||
self->hdr_to_recv = sizeof(struct webrepl_file);
|
||||
DEBUG_printf("webrepl: Finished writing file\n");
|
||||
DEBUG_printf("webrepl: Finished file operation %d\n", self->hdr.type);
|
||||
write_webrepl_resp(self->sock, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,11 +73,11 @@ STATIC mp_obj_t websocket_make_new(const mp_obj_type_t *type, size_t n_args, siz
|
||||
if (n_args > 1 && args[1] == mp_const_true) {
|
||||
o->opts |= BLOCKING_WRITE;
|
||||
}
|
||||
return o;
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
STATIC mp_uint_t websocket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_websocket_t *self = self_in;
|
||||
mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
const mp_stream_p_t *stream_p = mp_get_stream_raise(self->sock, MP_STREAM_OP_READ);
|
||||
while (1) {
|
||||
if (self->to_recv != 0) {
|
||||
@@ -219,7 +219,7 @@ no_payload:
|
||||
}
|
||||
|
||||
STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_websocket_t *self = self_in;
|
||||
mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
assert(size < 0x10000);
|
||||
byte header[4] = {0x80 | (self->opts & FRAME_OPCODE_MASK)};
|
||||
int hdr_sz;
|
||||
@@ -280,12 +280,13 @@ STATIC mp_obj_t websocket_close(mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(websocket_close_obj, websocket_close);
|
||||
|
||||
STATIC const mp_map_elem_t websocket_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ioctl), (mp_obj_t)&mp_stream_ioctl_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&websocket_close_obj },
|
||||
STATIC const mp_rom_map_elem_t websocket_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&mp_stream_ioctl_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&websocket_close_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(websocket_locals_dict, websocket_locals_dict_table);
|
||||
|
||||
@@ -300,12 +301,12 @@ STATIC const mp_obj_type_t websocket_type = {
|
||||
.name = MP_QSTR_websocket,
|
||||
.make_new = websocket_make_new,
|
||||
.protocol = &websocket_stream_p,
|
||||
.locals_dict = (mp_obj_t)&websocket_locals_dict,
|
||||
.locals_dict = (void*)&websocket_locals_dict,
|
||||
};
|
||||
|
||||
STATIC const mp_map_elem_t websocket_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_websocket) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_websocket), (mp_obj_t)&websocket_type },
|
||||
STATIC const mp_rom_map_elem_t websocket_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_websocket) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_websocket), MP_ROM_PTR(&websocket_type) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(websocket_module_globals, websocket_module_globals_table);
|
||||
|
||||
@@ -90,6 +90,14 @@ STATIC mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_remove_obj, fat_vfs_remove);
|
||||
|
||||
STATIC mp_obj_t fat_vfs_rmdir(mp_obj_t vfs_in, mp_obj_t path_in) {
|
||||
// TODO: Currently just redirects to fat_vfs_remove(), which are
|
||||
// backed by the same underlying FatFs function. Should at least
|
||||
// check that path is actually a dir.
|
||||
return fat_vfs_remove(vfs_in, path_in);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_rmdir_obj, fat_vfs_rmdir);
|
||||
|
||||
STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_out) {
|
||||
(void)vfs_in;
|
||||
const char *old_path = mp_obj_str_get_str(path_in);
|
||||
@@ -247,6 +255,7 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&fat_vfs_listdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&fat_vfs_mkdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&fat_vfs_rmdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&fat_vfs_chdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&fat_vfs_getcwd_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&fat_vfs_remove_obj) },
|
||||
|
||||
Submodule lib/axtls updated: c2690dc100...67d27df4b5
Submodule lib/berkeley-db-1.xx updated: 7b31cae3c0...78a4787948
7
lib/embed/abort_.c
Normal file
7
lib/embed/abort_.c
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <py/runtime.h>
|
||||
|
||||
NORETURN void abort_(void);
|
||||
|
||||
NORETURN void abort_(void) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "abort() called"));
|
||||
}
|
||||
@@ -40,7 +40,7 @@
|
||||
#include "irq.h"
|
||||
#include "usb.h"
|
||||
#endif
|
||||
#include "readline.h"
|
||||
#include "lib/mp-readline/readline.h"
|
||||
#include "lib/utils/pyexec.h"
|
||||
#include "genhdr/mpversion.h"
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "py/mphal.h"
|
||||
|
||||
/*
|
||||
* Extra UART functions
|
||||
* Extra stdout functions
|
||||
* These can be either optimized for a particular port, or reference
|
||||
* implementation below can be used.
|
||||
*/
|
||||
BIN
logo/1bit-logo.png
Normal file
BIN
logo/1bit-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 415 B |
@@ -45,7 +45,7 @@ LIBS =
|
||||
SRC_C = \
|
||||
main.c \
|
||||
uart_core.c \
|
||||
uart_extra.c \
|
||||
lib/utils/stdout_helpers.c \
|
||||
lib/utils/printf.c \
|
||||
lib/utils/pyexec.c \
|
||||
lib/libc/string0.c \
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#define MICROPY_MEM_STATS (0)
|
||||
#define MICROPY_DEBUG_PRINTERS (0)
|
||||
#define MICROPY_ENABLE_GC (1)
|
||||
#define MICROPY_GC_ALLOC_THRESHOLD (0)
|
||||
#define MICROPY_REPL_EVENT_DRIVEN (0)
|
||||
#define MICROPY_HELPER_REPL (1)
|
||||
#define MICROPY_HELPER_LEXER_UNIX (0)
|
||||
|
||||
@@ -37,19 +37,24 @@ endif
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
CC = clang
|
||||
# Use clang syntax for map file
|
||||
LDFLAGS_ARCH = -Wl,-map,$@.map
|
||||
LDFLAGS_ARCH = -Wl,-map,$@.map -Wl,-dead_strip
|
||||
else
|
||||
# Use gcc syntax for map file
|
||||
LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref
|
||||
LDFLAGS_ARCH = -Wl,-Map=$@.map,--cref -Wl,--gc-sections
|
||||
endif
|
||||
LDFLAGS = $(LDFLAGS_MOD) $(LDFLAGS_ARCH) -lm $(LDFLAGS_EXTRA)
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
|
||||
# source files
|
||||
SRC_C = \
|
||||
main.c \
|
||||
gccollect.c \
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
ifeq (,$(findstring MSYS,$(UNAME_S)))
|
||||
SRC_C += windows/fmode.c
|
||||
endif
|
||||
endif
|
||||
|
||||
OBJ = $(PY_O)
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
||||
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/stackctrl.h"
|
||||
#ifdef _WIN32
|
||||
#include "windows/fmode.h"
|
||||
#endif
|
||||
|
||||
// Command line options, with their defaults
|
||||
STATIC uint emit_opt = MP_EMIT_OPT_NONE;
|
||||
@@ -185,6 +188,9 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
gc_init(heap, heap + heap_size);
|
||||
|
||||
mp_init();
|
||||
#ifdef _WIN32
|
||||
set_fmode_binary();
|
||||
#endif
|
||||
mp_obj_list_init(mp_sys_path, 0);
|
||||
mp_obj_list_init(mp_sys_argv, 0);
|
||||
|
||||
|
||||
@@ -87,6 +87,10 @@
|
||||
#ifdef __LP64__
|
||||
typedef long mp_int_t; // must be pointer size
|
||||
typedef unsigned long mp_uint_t; // must be pointer size
|
||||
#elif defined ( __MINGW32__ ) && defined( _WIN64 )
|
||||
#include <stdint.h>
|
||||
typedef __int64 mp_int_t;
|
||||
typedef unsigned __int64 mp_uint_t;
|
||||
#else
|
||||
// These are definitions for machines where sizeof(int) == sizeof(void*),
|
||||
// regardless for actual size.
|
||||
@@ -115,6 +119,8 @@ typedef const void *machine_const_ptr_t; // must be of pointer size
|
||||
// We need to provide a declaration/definition of alloca()
|
||||
#ifdef __FreeBSD__
|
||||
#include <stdlib.h>
|
||||
#elif defined( _WIN32 )
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
22
py/gc.c
22
py/gc.c
@@ -152,6 +152,12 @@ void gc_init(void *start, void *end) {
|
||||
// allow auto collection
|
||||
MP_STATE_MEM(gc_auto_collect_enabled) = 1;
|
||||
|
||||
#if MICROPY_GC_ALLOC_THRESHOLD
|
||||
// by default, maxuint for gc threshold, effectively turning gc-by-threshold off
|
||||
MP_STATE_MEM(gc_alloc_threshold) = (size_t)-1;
|
||||
MP_STATE_MEM(gc_alloc_amount) = 0;
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_THREAD
|
||||
mp_thread_mutex_init(&MP_STATE_MEM(gc_mutex));
|
||||
#endif
|
||||
@@ -294,6 +300,9 @@ STATIC void gc_sweep(void) {
|
||||
void gc_collect_start(void) {
|
||||
GC_ENTER();
|
||||
MP_STATE_MEM(gc_lock_depth)++;
|
||||
#if MICROPY_GC_ALLOC_THRESHOLD
|
||||
MP_STATE_MEM(gc_alloc_amount) = 0;
|
||||
#endif
|
||||
MP_STATE_MEM(gc_stack_overflow) = 0;
|
||||
MP_STATE_MEM(gc_sp) = MP_STATE_MEM(gc_stack);
|
||||
// Trace root pointers. This relies on the root pointers being organised
|
||||
@@ -405,6 +414,15 @@ void *gc_alloc(size_t n_bytes, bool has_finaliser) {
|
||||
size_t start_block;
|
||||
size_t n_free = 0;
|
||||
int collected = !MP_STATE_MEM(gc_auto_collect_enabled);
|
||||
|
||||
#if MICROPY_GC_ALLOC_THRESHOLD
|
||||
if (!collected && MP_STATE_MEM(gc_alloc_amount) >= MP_STATE_MEM(gc_alloc_threshold)) {
|
||||
GC_EXIT();
|
||||
gc_collect();
|
||||
GC_ENTER();
|
||||
}
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
|
||||
// look for a run of n_blocks available blocks
|
||||
@@ -456,6 +474,10 @@ found:
|
||||
void *ret_ptr = (void*)(MP_STATE_MEM(gc_pool_start) + start_block * BYTES_PER_BLOCK);
|
||||
DEBUG_printf("gc_alloc(%p)\n", ret_ptr);
|
||||
|
||||
#if MICROPY_GC_ALLOC_THRESHOLD
|
||||
MP_STATE_MEM(gc_alloc_amount) += n_blocks;
|
||||
#endif
|
||||
|
||||
GC_EXIT();
|
||||
|
||||
// zero out the additional bytes of the newly allocated blocks
|
||||
|
||||
@@ -127,7 +127,7 @@ lib: $(OBJ)
|
||||
$(AR) rcs libmicropython.a $^
|
||||
|
||||
clean:
|
||||
$(RM) -rf $(BUILD)
|
||||
$(RM) -rf $(BUILD) $(CLEAN_EXTRA)
|
||||
.PHONY: clean
|
||||
|
||||
print-cfg:
|
||||
|
||||
22
py/modgc.c
22
py/modgc.c
@@ -83,6 +83,25 @@ STATIC mp_obj_t gc_mem_alloc(void) {
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(gc_mem_alloc_obj, gc_mem_alloc);
|
||||
|
||||
#if MICROPY_GC_ALLOC_THRESHOLD
|
||||
STATIC mp_obj_t gc_threshold(size_t n_args, const mp_obj_t *args) {
|
||||
if (n_args == 0) {
|
||||
if (MP_STATE_MEM(gc_alloc_threshold) == (size_t)-1) {
|
||||
return MP_OBJ_NEW_SMALL_INT(-1);
|
||||
}
|
||||
return mp_obj_new_int(MP_STATE_MEM(gc_alloc_threshold) * MICROPY_BYTES_PER_GC_BLOCK);
|
||||
}
|
||||
mp_int_t val = mp_obj_get_int(args[0]);
|
||||
if (val < 0) {
|
||||
MP_STATE_MEM(gc_alloc_threshold) = (size_t)-1;
|
||||
} else {
|
||||
MP_STATE_MEM(gc_alloc_threshold) = val / MICROPY_BYTES_PER_GC_BLOCK;
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gc_threshold_obj, 0, 1, gc_threshold);
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_gc_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_gc) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_collect), MP_ROM_PTR(&gc_collect_obj) },
|
||||
@@ -91,6 +110,9 @@ STATIC const mp_rom_map_elem_t mp_module_gc_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_isenabled), MP_ROM_PTR(&gc_isenabled_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mem_free), MP_ROM_PTR(&gc_mem_free_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mem_alloc), MP_ROM_PTR(&gc_mem_alloc_obj) },
|
||||
#if MICROPY_GC_ALLOC_THRESHOLD
|
||||
{ MP_ROM_QSTR(MP_QSTR_threshold), MP_ROM_PTR(&gc_threshold_obj) },
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_gc_globals, mp_module_gc_globals_table);
|
||||
|
||||
@@ -107,6 +107,12 @@
|
||||
#define MICROPY_ALLOC_GC_STACK_SIZE (64)
|
||||
#endif
|
||||
|
||||
// Support automatic GC when reaching allocation threshold,
|
||||
// configurable by gc.threshold().
|
||||
#ifndef MICROPY_GC_ALLOC_THRESHOLD
|
||||
#define MICROPY_GC_ALLOC_THRESHOLD (1)
|
||||
#endif
|
||||
|
||||
// Number of bytes to allocate initially when creating new chunks to store
|
||||
// interned string data. Smaller numbers lead to more chunks being needed
|
||||
// and more wastage at the end of the chunk. Larger numbers lead to wasted
|
||||
@@ -516,6 +522,12 @@ typedef double mp_float_t;
|
||||
#define MICROPY_STREAMS_NON_BLOCK (0)
|
||||
#endif
|
||||
|
||||
// Whether to provide stream functions with POSIX-like signatures
|
||||
// (useful for porting existing libraries to MicroPython).
|
||||
#ifndef MICROPY_STREAMS_POSIX_API
|
||||
#define MICROPY_STREAMS_POSIX_API (0)
|
||||
#endif
|
||||
|
||||
// Whether to call __init__ when importing builtin modules for the first time
|
||||
#ifndef MICROPY_MODULE_BUILTIN_INIT
|
||||
#define MICROPY_MODULE_BUILTIN_INIT (0)
|
||||
@@ -584,6 +596,11 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_ASYNC_AWAIT (1)
|
||||
#endif
|
||||
|
||||
// Issue a warning when comparing str and bytes objects
|
||||
#ifndef MICROPY_PY_STR_BYTES_CMP_WARN
|
||||
#define MICROPY_PY_STR_BYTES_CMP_WARN (0)
|
||||
#endif
|
||||
|
||||
// Whether str object is proper unicode
|
||||
#ifndef MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
#define MICROPY_PY_BUILTINS_STR_UNICODE (0)
|
||||
@@ -594,6 +611,11 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_BUILTINS_STR_CENTER (0)
|
||||
#endif
|
||||
|
||||
// Whether str.partition()/str.rpartition() method provided
|
||||
#ifndef MICROPY_PY_BUILTINS_STR_PARTITION
|
||||
#define MICROPY_PY_BUILTINS_STR_PARTITION (0)
|
||||
#endif
|
||||
|
||||
// Whether str.splitlines() method provided
|
||||
#ifndef MICROPY_PY_BUILTINS_STR_SPLITLINES
|
||||
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (0)
|
||||
@@ -1051,6 +1073,11 @@ typedef double mp_float_t;
|
||||
#define MP_NOINLINE __attribute__((noinline))
|
||||
#endif
|
||||
|
||||
// Modifier for functions which should be always inlined
|
||||
#ifndef MP_ALWAYSINLINE
|
||||
#define MP_ALWAYSINLINE __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
// Condition is likely to be true, to help branch prediction
|
||||
#ifndef MP_LIKELY
|
||||
#define MP_LIKELY(x) __builtin_expect((x), 1)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user