Merge tag 'v1.8.3' into parse-bytecode
Many small improvements and additions, with btree support in ESP8266 port This release brings various improvements and additions to the core, extended modules and the ESP8266 port, as well as enhancements to the docs. There is now a "threshold" function in the gc module for the user to configure the garbage collector to run earlier than usual, in order to help reduce fragmentation of the heap. The btree module is now available in the ESP8266 port, and there is improved WebREPL file transfer: get file is now non-blocking (this change requires an update of the client software). py core: - nlrx64.S: prefix mp_thread_get_state with an underscore on Mac - stream: implement 2- and 3-arg write() method as an extension to CPython - gc: implement GC running by allocation threshold, user configurable - fix nlrthumb.c when DEBUG=1 is defined - obj: issue a warning when str and bytes objects are compared - mpconfig.h: fix description for MICROPY_PY_STR_BYTES_CMP_WARN - objstrunicode: str_index_to_ptr: should handle bytes too - objstrunicode: str_index_to_ptr: implement positive indexing properly - stream: implement generic flush() method, in terms of C-level ioctl - objstringio: add MP_STREAM_FLUSH ioctl and flush() method - objstringio: implement MP_STREAM_SEEK ioctl and add seek() method - stream: add adapter methods with POSIX-compatible signatures - mpconfig.h: add MICROPY_STREAMS_POSIX_API setting - py.mk: extra switches to build "embedded" BerkeleyDB BTree lib - mkrules.mk: allow to add more items for "clean" target using CLEAN_EXTRA - objstr: make .partition()/.rpartition() methods configurable - mpconfig.h: define MP_ALWAYSINLINE for reuse extmod: - modussl: rename to modussl_axtls.c, to allow impl using other SSL libs - modussl_axtls: further changes to allow alternative SSL modules - modussl_axtls: add dummy setblocking() method - vfs_fat: implement rmdir() method (aliases to unlink) - modussl_axtls: use mp_stream_close() method - modwebrepl: use mp_stream_close() method - modbtree: check __bt_open() return value for error - modbtree: switch to accepting stream object instead of filename - modbtree: implement __contains__ operation - modwebrepl: factor out "GET" iteration to write_file_chunk() - modwebrepl: make GET_FILE operation non-blocking - modbtree: open(): add option kwargs - modwebsocket: add readline method - modwebsocket: make compatible with non-default object models - modwebsocket: use mp_rom_map_elem_t and friends - modwebrepl: add GET_VER operation to query MicroPython version lib: - axtls: upgrade to axTLS 1.5.4 + MicroPython patchset - axtls: update, fixes esp8266 build - utils/stdout_helpers: move from minimal/uart_extra.c for reuse - embed/abort_: implementation of abort_() function raising uPy exception - berkeley-db-1.xx: switch to "embedded" branch - berkeley-db-1.xx: update, sets default page size to 4096 tests: - add test for extended arguments to stream .write() method - extmod/machine_pinbase: skip if machine.PinBase is not available - bytes_compare: rework test for bytes <-> str comparison - extmod/btree1: close database at the end of test - unicode_subscr.py: detailed test for subscripting unicode strings - run-tests: make "regex'ed .exp" facility available to device tests - io/bytesio_ext: test for .seek()/.flush() on BytesIO - extmod/btree1: tests against in-memory DB (using io.BytesIO) - machine_mem.py: too non-portable, rework as an example for unix port - machine1: revamp to work with unix port (which has "umachine") - basics: bytes/str.partition/rpartition are now optional mpy-cross: - fix Makefile to handle gc-sections linker flags on OS X - use binary file translation mode for creating mpy files on windows - fix mingw and msys2 compilation minimal port: - disable MICROPY_GC_ALLOC_THRESHOLD unix port: - mpthreadport: adjust minimum thread stack, and stack limit check - cache libaxtls.a in local build dir - disable MICROPY_GC_ALLOC_THRESHOLD for minimal build - enable MICROPY_PY_STR_BYTES_CMP_WARN - mpconfigport.h: include stdio.h by default - file: implement MP_STREAM_FLUSH ioctl - file: ioctl(): check that file is open before operations - file: fdfile_ioctl(): fix argument to check_fd_is_open() - file: use generic stream flush() method - enable websocket module - moduselect: allow poll.register(), etc. accept fd-like objects stmhal port: - fix malloc when used with external libraries - make SPI NSS pin definition optional - fix I2C mappings for STM32F429DISC board esp8266 port: - select axTLS for SSL implementation, following recent refactor - moduos: add rmdir() function - cache Xtensa-built libaxtls.a in local build dir - enable MICROPY_PY_STR_BYTES_CMP_WARN - dupterm_task_init() should be called before running _boot.py, etc - _boot.py: set GC alloc threshold to half of heap size - _boot.py: decrease GC alloc threshold to quarter of heap size - modpybuart: fix UART parity setting - axtls_helpers: remove abort_(), now in lib/embed/ - mpconfigport.h: include sys/types.h for POSIX types definitions - esp_mphal: implement libc's errno - enable btree module - eagle.rom.addr.v6.ld: add Enable_QMode symbol from SDK 2.0.0 - make APA102 driver inclusion configurable - makeimg.py: store firmware size as last 4 bytes of padding area - makeimg.py: append md5 hash to the generated binary - modesp: add check_fw() function to check integrity of the firmware - scripts/port_diag.py: include esp.check_fw() call - flashbdev: reserve extra sysparam sector for SDK 2.0.0 compatibility - scripts/inisetup: add commented-out call to esp.osdebug(None) - modmachine: implement idle() function - esp_mphal.h: add mp_hal_ticks_cpu() for reuse - modutime: actually implement ticks_cpu() - modmachine: implement dummy sleep() function - tutorial/intro: reword para abou -fm dio switch - modules/flashbdev: start filesystem at 0x90000 - esp8266.ld: increase firmware image size to 0x90000 (576K) docs: - add DHT to ESP8266 Quick Ref and Tutorial - fix some spelling mistakes - array: document array module - library/index: include array module in ToC - esp8266/intro: rename to "Getting started" from "Introduction" - esp8266/intro: add troubleshooting section - esp8266/quickref: link to installation instructions - esp8266/tutorial/intro: add anchor for link from quickeref - esp8266/intro: focus on hazards of unearthed power wrt electronics - uio: mention seek()/flush() support for io.BytesIO misc: - logo/1bit-logo A black & white version of the logo examples: - http_server*: update for buffered-like streams (read line by line) - embedding: example for embedding MicroPython in an app - embedding: add README - http_client*: be sure to close socket - network: split recv- and read-based HTTP servers qemu-arm: - enable gcc LTO option for nlrthumb.c
This commit is contained in:
commit
bb254ba0ea
|
@ -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)
|
||||
----------------------------------------
|
||||
|
||||
|
|
|
@ -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>`__ .
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
-------------------------------------
|
||||
|
@ -92,7 +92,7 @@ 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
|
||||
|
|
|
@ -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()
|
||||
|
||||
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)
|
||||
|
||||
|
@ -19,13 +21,13 @@ typedef enum {
|
|||
|
||||
typedef enum {
|
||||
UART_NONE_BITS = 0,
|
||||
UART_ODD_BITS = 0,
|
||||
UART_EVEN_BITS = BIT4
|
||||
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 {
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
||||
~~~
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
mpconfigport_minimal.h
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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()
|
|
@ -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:
|
||||
|
|
|
@ -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 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} },
|
||||
STATIC FILEVTABLE btree_stream_fvtable = {
|
||||
mp_stream_posix_read,
|
||||
mp_stream_posix_write,
|
||||
mp_stream_posix_lseek,
|
||||
mp_stream_posix_fsync
|
||||
};
|
||||
|
||||
const char *fname = NULL;
|
||||
if (pos_args[0] != mp_const_none) {
|
||||
fname = mp_obj_str_get_str(pos_args[0]);
|
||||
}
|
||||
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_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} },
|
||||
};
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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) },
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit c2690dc100f272cb01375dcf2f2be7105d0fb7c0
|
||||
Subproject commit 67d27df4b5d097e146599fc4fb160a2adcbf5632
|
|
@ -1 +1 @@
|
|||
Subproject commit 7b31cae3c0892a7fca2089cb0354a4920c98c413
|
||||
Subproject commit 78a4787948bb80cbfafcfd7910f95f61a4dd0d4c
|
|
@ -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.
|
||||
*/
|
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)
|
||||
|
|
|
@ -76,6 +76,11 @@ typedef struct _mp_state_mem_t {
|
|||
// you can still allocate/free memory and also explicitly call gc_collect.
|
||||
uint16_t gc_auto_collect_enabled;
|
||||
|
||||
#if MICROPY_GC_ALLOC_THRESHOLD
|
||||
size_t gc_alloc_amount;
|
||||
size_t gc_alloc_threshold;
|
||||
#endif
|
||||
|
||||
size_t gc_last_free_atb_index;
|
||||
|
||||
#if MICROPY_PY_GC_COLLECT_RETVAL
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#if (!defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP) && (defined(__thumb2__) || defined(__thumb__) || defined(__arm__))
|
||||
|
||||
#undef nlr_push
|
||||
|
||||
// We only need the functions here if we are on arm/thumb, and we are not
|
||||
// using setjmp/longjmp.
|
||||
//
|
||||
|
@ -71,7 +73,7 @@ __attribute__((naked)) unsigned int nlr_push(nlr_buf_t *nlr) {
|
|||
return 0; // needed to silence compiler warning
|
||||
}
|
||||
|
||||
unsigned int nlr_push_tail(nlr_buf_t *nlr) {
|
||||
__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
|
||||
nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
|
||||
nlr->prev = *top;
|
||||
*top = nlr;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue