Merge remote-tracking branch 'micropython/master'

This commit is contained in:
Scott Shawcroft 2016-09-02 19:39:50 -07:00
commit c6c977070e
72 changed files with 1009 additions and 475 deletions

1
.gitignore vendored
View File

@ -32,6 +32,7 @@ tests/*.out
# Python cache files
######################
__pycache__/
*.pyc
# Customized Makefile/project overrides
######################

View File

@ -23,14 +23,14 @@ Tab-completion is useful to find out what methods an object has.
Paste mode (ctrl-E) is useful to paste a large slab of Python code into
the REPL.
The ``machine`` module::
The :mod:`machine` module::
import machine
machine.freq() # get the current frequency of the CPU
machine.freq(160000000) # set the CPU frequency to 160 MHz
The ``esp`` module::
The :mod:`esp` module::
import esp
@ -40,7 +40,7 @@ The ``esp`` module::
Networking
----------
The ``network`` module::
The :mod:`network` module::
import network
@ -69,13 +69,13 @@ A useful function for connecting to your local WiFi network is::
pass
print('network config:', wlan.ifconfig())
Once the network is established the ``socket`` module can be used
Once the network is established the :mod:`socket <usocket>` module can be used
to create and use TCP/UDP sockets as usual.
Delay and timing
----------------
Use the ``time`` module::
Use the :mod:`time <utime>` module::
import time
@ -165,14 +165,14 @@ Use the ``machine.ADC`` class::
SPI bus
-------
The SPI driver is implemented in software and works on all pins::
There are two SPI drivers. One is implemented in software and works on all pins::
from machine import Pin, SPI
# construct an SPI bus on the given pins
# polarity is the idle state of SCK
# phase=0 means sample on the first edge of SCK, phase=1 means the second
spi = SPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
spi = SPI(-1, baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
spi.init(baudrate=200000) # set the baudrate
@ -194,13 +194,13 @@ Hardware SPI
------------
The hardware SPI is faster (up to 80Mhz), but only works on following pins:
``MISO`` is gpio2, ``MOSI`` is gpio13, and ``SCK`` is gpio14. It has the same
``MISO`` is gpio12, ``MOSI`` is gpio13, and ``SCK`` is gpio14. It has the same
methods as SPI, except for the pin parameters for the constructor and init
(as those are fixed).
from machine import Pin, HSPI
from machine import Pin, SPI
hspi = HSPI(baudrate=800000000, polarity=0, phase=0)
hspi = SPI(0, baudrate=80000000, polarity=0, phase=0)
I2C bus
@ -253,15 +253,14 @@ The OneWire driver is implemented in software and works on all pins::
ow.scan() # return a list of devices on the bus
ow.reset() # reset the bus
ow.readbyte() # read a byte
ow.read(5) # read 5 bytes
ow.writebyte(0x12) # write a byte on the bus
ow.write('123') # write bytes on the bus
ow.select_rom(b'12345678') # select a specific device by its ROM code
There is a specific driver for DS18B20 devices::
There is a specific driver for DS18S20 and DS18B20 devices::
import time
ds = onewire.DS18B20(ow)
import time, ds18x20
ds = ds18x20.DS18X20(ow)
roms = ds.scan()
ds.convert_temp()
time.sleep_ms(750)

View File

@ -6,19 +6,19 @@ The 1-wire bus is a serial bus that uses just a single wire for communication
is a very popular 1-wire device, and here we show how to use the onewire module
to read from such a device.
For the following code to work you need to have at least one DS18B20 temperature
For the following code to work you need to have at least one DS18S20 or DS18B20 temperature
sensor with its data line connected to GPIO12. You must also power the sensors
and connect a 4.7k Ohm resistor between the data pin and the power pin. ::
import time
import machine
import onewire
import onewire, ds18x20
# the device is on GPIO12
dat = machine.Pin(12)
# create the onewire object
ds = onewire.DS18B20(onewire.OneWire(dat))
ds = ds18x20.DS18X20(onewire.OneWire(dat))
# scan for devices on the bus
roms = ds.scan()

View File

@ -0,0 +1,28 @@
.. currentmodule:: pyb
class USB_HID -- USB Human Interface Device (HID)
=================================================
The USB_HID class allows creation of an object representing the USB
Human Interface Device (HID) interface. It can be used to emulate
a peripheral such as a mouse or keyboard.
Before you can use this class, you need to use :meth:`pyb.usb_mode()` to set the USB mode to include the HID interface.
Constructors
------------
.. class:: pyb.USB_HID()
Create a new USB_HID object.
Methods
-------
.. method:: USB_HID.send(data)
Send data over the USB HID interface:
- ``data`` is the data to send (a tuple/list of integers, or a
bytearray).

View File

@ -188,7 +188,7 @@ Miscellaneous functions
Takes a 4-tuple (or list) and sends it to the USB host (the PC) to
signal a HID mouse-motion event.
.. note:: This function is deprecated. Use pyb.USB_HID().send(...) instead.
.. note:: This function is deprecated. Use :meth:`pyb.USB_HID.send()` instead.
.. function:: info([dump_alloc_table])
@ -254,6 +254,33 @@ Miscellaneous functions
Returns a string of 12 bytes (96 bits), which is the unique ID of the MCU.
.. function:: usb_mode([modestr], vid=0xf055, pid=0x9801, hid=pyb.hid_mouse)
If called with no arguments, return the current USB mode as a string.
If called with ``modestr`` provided, attempts to set USB mode.
This can only be done when called from ``boot.py`` before
:meth:`pyb.main()` has been called. The following values of
``modestr`` are understood:
- ``None``: disables USB
- ``'VCP'``: enable with VCP (Virtual COM Port) interface
- ``'VCP+MSC'``: enable with VCP and MSC (mass storage device class)
- ``'VCP+HID'``: enable with VCP and HID (human interface device)
For backwards compatibility, ``'CDC'`` is understood to mean
``'VCP'`` (and similarly for ``'CDC+MSC'`` and ``'CDC+HID'``).
The ``vid`` and ``pid`` parameters allow you to specify the VID
(vendor id) and PID (product id).
If enabling HID mode, you may also specify the HID details by
passing the ``hid`` keyword parameter. It takes a tuple of
(subclass, protocol, max packet length, polling interval, report
descriptor). By default it will set appropriate values for a USB
mouse. There is also a ``pyb.hid_keyboard`` constant, which is an
appropriate tuple for a USB keyboard.
Classes
-------
@ -277,4 +304,5 @@ Classes
pyb.Switch.rst
pyb.Timer.rst
pyb.UART.rst
pyb.USB_HID.rst
pyb.USB_VCP.rst

View File

@ -3,6 +3,12 @@
Quick reference for the pyboard
===============================
The below pinout is for PYBv1.0. You can also view pinouts for
other versions of the pyboard:
`PYBv1.1 <http://micropython.org/resources/pybv11-pinout.jpg>`__
or `PYBLITEv1.0-AC <http://micropython.org/resources/pyblitev10ac-pinout.jpg>`__
or `PYBLITEv1.0 <http://micropython.org/resources/pyblitev10-pinout.jpg>`__.
.. image:: http://micropython.org/resources/pybv10-pinout.jpg
:alt: PYBv1.0 pinout
:width: 700px
@ -14,14 +20,25 @@ See :mod:`pyb`. ::
import pyb
pyb.delay(50) # wait 50 milliseconds
pyb.millis() # number of milliseconds since bootup
pyb.repl_uart(pyb.UART(1, 9600)) # duplicate REPL on UART(1)
pyb.wfi() # pause CPU, waiting for interrupt
pyb.freq() # get CPU and bus frequencies
pyb.freq(60000000) # set CPU freq to 60MHz
pyb.stop() # stop CPU, waiting for external interrupt
Delay and timing
----------------
Use the :mod:`time <utime>` module::
import time
time.sleep(1) # sleep for 1 second
time.sleep_ms(500) # sleep for 500 milliseconds
time.sleep_us(10) # sleep for 10 microseconds
start = time.ticks_ms() # get value of millisecond counter
delta = time.ticks_diff(start, time.ticks_ms()) # compute time difference
LEDs
----

View File

@ -13,23 +13,23 @@ will look something like this::
import pyb
#pyb.main('main.py') # main script to run after this one
#pyb.usb_mode('CDC+MSC') # act as a serial and a storage device
#pyb.usb_mode('CDC+HID') # act as a serial device and a mouse
#pyb.usb_mode('VCP+MSC') # act as a serial and a storage device
#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse
To enable the mouse mode, uncomment the last line of the file, to
make it look like::
pyb.usb_mode('CDC+HID') # act as a serial device and a mouse
pyb.usb_mode('VCP+HID') # act as a serial device and a mouse
If you already changed your ``boot.py`` file, then the minimum code it
needs to work is::
import pyb
pyb.usb_mode('CDC+HID')
pyb.usb_mode('VCP+HID')
This tells the pyboard to configure itself as a CDC (serial) and HID
(human interface device, in our case a mouse) USB device when it boots
up.
This tells the pyboard to configure itself as a VCP (Virtual COM Port,
ie serial port) and HID (human interface device, in our case a mouse)
USB device when it boots up.
Eject/unmount the pyboard drive and reset it using the RST switch.
Your PC should now detect the pyboard as a mouse!
@ -41,7 +41,8 @@ To get the py-mouse to do anything we need to send mouse events to the PC.
We will first do this manually using the REPL prompt. Connect to your
pyboard using your serial program and type the following::
>>> pyb.hid((0, 10, 0, 0))
>>> hid = pyb.USB_HID()
>>> hid.send((0, 10, 0, 0))
Your mouse should move 10 pixels to the right! In the command above you
are sending 4 pieces of information: button status, x, y and scroll. The
@ -52,7 +53,7 @@ Let's make the mouse oscillate left and right::
>>> import math
>>> def osc(n, d):
... for i in range(n):
... pyb.hid((0, int(20 * math.sin(i / 10)), 0, 0))
... hid.send((0, int(20 * math.sin(i / 10)), 0, 0))
... pyb.delay(d)
...
>>> osc(100, 50)
@ -100,9 +101,10 @@ In ``main.py`` put the following code::
switch = pyb.Switch()
accel = pyb.Accel()
hid = pyb.USB_HID()
while not switch():
pyb.hid((0, accel.x(), accel.y(), 0))
hid.send((0, accel.x(), accel.y(), 0))
pyb.delay(20)
Save your file, eject/unmount your pyboard drive, and reset it using the RST
@ -112,7 +114,7 @@ the mouse around. Try it out, and see if you can make the mouse stand still!
Press the USR switch to stop the mouse motion.
You'll note that the y-axis is inverted. That's easy to fix: just put a
minus sign in front of the y-coordinate in the ``pyb.hid()`` line above.
minus sign in front of the y-coordinate in the ``hid.send()`` line above.
Restoring your pyboard to normal
--------------------------------
@ -121,9 +123,9 @@ If you leave your pyboard as-is, it'll behave as a mouse everytime you plug
it in. You probably want to change it back to normal. To do this you need
to first enter safe mode (see above), and then edit the ``boot.py`` file.
In the ``boot.py`` file, comment out (put a # in front of) the line with the
``CDC+HID`` setting, so it looks like::
``VCP+HID`` setting, so it looks like::
#pyb.usb_mode('CDC+HID') # act as a serial device and a mouse
#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse
Save your file, eject/unmount the drive, and reset the pyboard. It is now
back to normal operating mode.

View File

@ -4,31 +4,41 @@ Micro Python driver for SD cards using SPI bus.
Requires an SPI bus and a CS pin. Provides readblocks and writeblocks
methods so the device can be mounted as a filesystem.
Example usage:
Example usage on pyboard:
import pyb, sdcard, os
sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
pyb.mount(sd, '/sd2')
os.listdir('/')
Example usage on ESP8266:
import machine, sdcard, os
sd = sdcard.SDCard(machine.SPI(0), machine.Pin(15))
os.umount()
os.VfsFat(sd, "")
os.listdir()
"""
import pyb
import time
_CMD_TIMEOUT = const(100)
_R1_IDLE_STATE = const(1 << 0)
#R1_ERASE_RESET = const(1 << 1)
_R1_ILLEGAL_COMMAND = const(1 << 2)
#R1_COM_CRC_ERROR = const(1 << 3)
#R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
#R1_ADDRESS_ERROR = const(1 << 5)
#R1_PARAMETER_ERROR = const(1 << 6)
_TOKEN_CMD25 = const(0xfc)
_TOKEN_STOP_TRAN = const(0xfd)
_TOKEN_DATA = const(0xfe)
class SDCard:
CMD_TIMEOUT = const(100)
R1_IDLE_STATE = const(1 << 0)
#R1_ERASE_RESET = const(1 << 1)
R1_ILLEGAL_COMMAND = const(1 << 2)
#R1_COM_CRC_ERROR = const(1 << 3)
#R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
#R1_ADDRESS_ERROR = const(1 << 5)
#R1_PARAMETER_ERROR = const(1 << 6)
TOKEN_CMD25 = const(0xfc)
TOKEN_STOP_TRAN = const(0xfd)
TOKEN_DATA = const(0xfe)
def __init__(self, spi, cs):
self.spi = spi
self.cs = cs
@ -42,30 +52,39 @@ class SDCard:
# initialise the card
self.init_card()
def init_spi(self, baudrate):
try:
master = self.spi.MASTER
except AttributeError:
# on ESP8266
self.spi.init(baudrate=baudrate, phase=0, polarity=0)
else:
# on pyboard
self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)
def init_card(self):
# init CS pin
self.cs.high()
self.cs.init(self.cs.OUT_PP)
self.cs.init(self.cs.OUT, value=1)
# init SPI bus; use low data rate for initialisation
self.spi.init(self.spi.MASTER, baudrate=100000, phase=0, polarity=0)
self.init_spi(100000)
# clock card at least 100 cycles with cs high
for i in range(16):
self.spi.send(0xff)
self.spi.write(b'\xff')
# CMD0: init card; should return R1_IDLE_STATE (allow 5 attempts)
# CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
for _ in range(5):
if self.cmd(0, 0, 0x95) == R1_IDLE_STATE:
if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
break
else:
raise OSError("no SD card")
# CMD8: determine card version
r = self.cmd(8, 0x01aa, 0x87, 4)
if r == R1_IDLE_STATE:
if r == _R1_IDLE_STATE:
self.init_card_v2()
elif r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND):
elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
self.init_card_v1()
else:
raise OSError("couldn't determine SD card version")
@ -86,10 +105,10 @@ class SDCard:
raise OSError("can't set 512 block size")
# set to high data rate now that it's initialised
self.spi.init(self.spi.MASTER, baudrate=1320000, phase=0, polarity=0)
self.init_spi(1320000)
def init_card_v1(self):
for i in range(CMD_TIMEOUT):
for i in range(_CMD_TIMEOUT):
self.cmd(55, 0, 0)
if self.cmd(41, 0, 0) == 0:
self.cdv = 512
@ -98,8 +117,8 @@ class SDCard:
raise OSError("timeout waiting for v1 card")
def init_card_v2(self):
for i in range(CMD_TIMEOUT):
pyb.delay(50)
for i in range(_CMD_TIMEOUT):
time.sleep_ms(50)
self.cmd(58, 0, 0, 4)
self.cmd(55, 0, 0)
if self.cmd(41, 0x40000000, 0) == 0:
@ -120,87 +139,87 @@ class SDCard:
buf[3] = arg >> 8
buf[4] = arg
buf[5] = crc
self.spi.send(buf)
self.spi.write(buf)
# wait for the repsonse (response[7] == 0)
for i in range(CMD_TIMEOUT):
response = self.spi.send_recv(0xff)[0]
for i in range(_CMD_TIMEOUT):
response = self.spi.read(1, 0xff)[0]
if not (response & 0x80):
# this could be a big-endian integer that we are getting here
for j in range(final):
self.spi.send(0xff)
self.spi.write(b'\xff')
if release:
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
return response
# timeout
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
return -1
def cmd_nodata(self, cmd):
self.spi.send(cmd)
self.spi.send_recv(0xff) # ignore stuff byte
for _ in range(CMD_TIMEOUT):
if self.spi.send_recv(0xff)[0] == 0xff:
self.spi.write(cmd)
self.spi.read(1, 0xff) # ignore stuff byte
for _ in range(_CMD_TIMEOUT):
if self.spi.read(1, 0xff)[0] == 0xff:
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
return 0 # OK
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
return 1 # timeout
def readinto(self, buf):
self.cs.low()
# read until start byte (0xff)
while self.spi.send_recv(0xff)[0] != 0xfe:
while self.spi.read(1, 0xff)[0] != 0xfe:
pass
# read data
mv = self.dummybuf_memoryview[:len(buf)]
self.spi.send_recv(mv, recv=buf)
self.spi.write_readinto(mv, buf)
# read checksum
self.spi.send(0xff)
self.spi.send(0xff)
self.spi.write(b'\xff')
self.spi.write(b'\xff')
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
def write(self, token, buf):
self.cs.low()
# send: start of block, data, checksum
self.spi.send(token)
self.spi.send(buf)
self.spi.send(0xff)
self.spi.send(0xff)
self.spi.read(1, token)
self.spi.write(buf)
self.spi.write(b'\xff')
self.spi.write(b'\xff')
# check the response
if (self.spi.send_recv(0xff)[0] & 0x1f) != 0x05:
if (self.spi.read(1, 0xff)[0] & 0x1f) != 0x05:
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
return
# wait for write to finish
while self.spi.send_recv(0xff)[0] == 0:
while self.spi.read(1, 0xff)[0] == 0:
pass
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
def write_token(self, token):
self.cs.low()
self.spi.send(token)
self.spi.send(0xff)
self.spi.read(1, token)
self.spi.write(b'\xff')
# wait for write to finish
while self.spi.send_recv(0xff)[0] == 0:
while self.spi.read(1, 0xff)[0] == 0x00:
pass
self.cs.high()
self.spi.send(0xff)
self.spi.write(b'\xff')
def count(self):
return self.sectors
@ -224,7 +243,7 @@ class SDCard:
self.readinto(mv[offset : offset + 512])
offset += 512
nblocks -= 1
return self.cmd_nodata(12)
return self.cmd_nodata(b'\x0c') # cmd 12
return 0
def writeblocks(self, block_num, buf):
@ -236,7 +255,7 @@ class SDCard:
return 1
# send the data
self.write(TOKEN_DATA, buf)
self.write(_TOKEN_DATA, buf)
else:
# CMD25: set write address for first block
if self.cmd(25, block_num * self.cdv, 0) != 0:
@ -245,8 +264,8 @@ class SDCard:
offset = 0
mv = memoryview(buf)
while nblocks:
self.write(TOKEN_CMD25, mv[offset : offset + 512])
self.write(_TOKEN_CMD25, mv[offset : offset + 512])
offset += 512
nblocks -= 1
self.write_token(TOKEN_STOP_TRAN)
self.write_token(_TOKEN_STOP_TRAN)
return 0

View File

@ -78,6 +78,7 @@ SRC_C = \
modpybrtc.c \
modpybadc.c \
modpybuart.c \
modmachinewdt.c \
modmachinespi.c \
modpybspi.c \
modpybhspi.c \
@ -140,7 +141,7 @@ DRIVERS_SRC_C = $(addprefix drivers/,\
SRC_S = \
gchelper.s \
FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR)/ -type f -name '*.py')
FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR) -type f -name '*.py')
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
OBJ =

View File

@ -199,7 +199,11 @@ uint32_t spi_transaction(uint8_t spi_no, uint8_t cmd_bits, uint16_t cmd_data,
// This is rather inefficient but allows for a very generic function.
// CMD ADDR and MOSI are set below to save on an extra if statement.
if (din_bits) {
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO);
if (dout_bits) {
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_DOUTDIN);
} else {
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO);
}
}
if (dummy_bits) {
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_DUMMY);

View File

@ -49,6 +49,8 @@
//#define MACHINE_WAKE_SLEEP (0x02)
#define MACHINE_WAKE_DEEPSLEEP (0x04)
extern const mp_obj_type_t esp_wdt_type;
STATIC mp_obj_t machine_freq(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
// get
@ -246,6 +248,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) },
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&esp_timer_type) },
{ MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&esp_wdt_type) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pyb_pin_type) },
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&pyb_pwm_type) },
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) },

76
esp8266/modmachinewdt.c Normal file
View File

@ -0,0 +1,76 @@
/*
* This file is part of the MicroPython 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 <stdio.h>
#include <string.h>
#include "py/nlr.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "user_interface.h"
const mp_obj_type_t esp_wdt_type;
typedef struct _machine_wdt_obj_t {
mp_obj_base_t base;
} machine_wdt_obj_t;
STATIC machine_wdt_obj_t wdt_default = {{&esp_wdt_type}};
STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_int_t id = 0;
if (n_args > 0) {
id = mp_obj_get_int(args[0]);
}
switch (id) {
case 0:
return &wdt_default;
default:
mp_raise_ValueError("");
}
}
STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) {
(void)self_in;
system_soft_wdt_feed();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed);
STATIC const mp_map_elem_t machine_wdt_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_feed), (mp_obj_t)&machine_wdt_feed_obj }
};
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);
const mp_obj_type_t esp_wdt_type = {
{ &mp_type_type },
.name = MP_QSTR_WDT,
.make_new = machine_wdt_make_new,
.locals_dict = (mp_obj_t)&machine_wdt_locals_dict,
};

View File

@ -35,6 +35,7 @@
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mphal.h"
#include "extmod/machine_spi.h"
#include "hspi.h"
@ -47,6 +48,58 @@ typedef struct _pyb_hspi_obj_t {
} pyb_hspi_obj_t;
STATIC void hspi_transfer(mp_obj_base_t *self_in, size_t src_len, const uint8_t *src_buf, size_t dest_len, uint8_t *dest_buf) {
(void)self_in;
if (dest_len == 0) {
// fast case when we only need to write data
size_t chunk_size = 1024;
size_t count = src_len / chunk_size;
size_t i = 0;
for (size_t j = 0; j < count; ++j) {
for (size_t k = 0; k < chunk_size; ++k) {
spi_tx8fast(HSPI, src_buf[i]);
++i;
}
ets_loop_iter();
}
while (i < src_len) {
spi_tx8fast(HSPI, src_buf[i]);
++i;
}
} else {
// we need to read and write data
// Process data in chunks, let the pending tasks run in between
size_t chunk_size = 1024; // TODO this should depend on baudrate
size_t count = dest_len / chunk_size;
size_t i = 0;
for (size_t j = 0; j < count; ++j) {
for (size_t k = 0; k < chunk_size; ++k) {
uint32_t data_out;
if (src_len == 1) {
data_out = src_buf[0];
} else {
data_out = src_buf[i];
}
dest_buf[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, data_out, 8, 0);
++i;
}
ets_loop_iter();
}
while (i < dest_len) {
uint32_t data_out;
if (src_len == 1) {
data_out = src_buf[0];
} else {
data_out = src_buf[i];
}
dest_buf[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, data_out, 8, 0);
++i;
}
}
}
/******************************************************************************/
// MicroPython bindings for HSPI
@ -126,133 +179,25 @@ STATIC mp_obj_t pyb_hspi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_
}
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_hspi_init_obj, 1, pyb_hspi_init);
STATIC mp_obj_t pyb_hspi_read(size_t n_args, const mp_obj_t *args) {
vstr_t dest_buf;
vstr_init_len(&dest_buf, mp_obj_get_int(args[1]));
uint8_t write_byte = 0;
if (n_args == 3) {
write_byte = mp_obj_get_int(args[2]);
}
// Process data in chunks, let the pending tasks run in between
size_t chunk_size = 1024; // TODO this should depend on baudrate
size_t count = dest_buf.len / chunk_size;
size_t i = 0;
for (size_t j = 0; j < count; ++j) {
for (size_t k = 0; k < chunk_size; ++k) {
((uint8_t*)dest_buf.buf)[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8,
(uint32_t)write_byte, 8, 0);
++i;
}
ets_loop_iter();
}
while (i < dest_buf.len) {
((uint8_t*)dest_buf.buf)[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8,
(uint32_t)write_byte, 8, 0);
++i;
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &dest_buf);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_hspi_read_obj, 2, 3, pyb_hspi_read);
STATIC mp_obj_t pyb_hspi_readinto(size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t dest_buf;
mp_get_buffer_raise(args[1], &dest_buf, MP_BUFFER_WRITE);
uint8_t write_byte = 0;
if (n_args == 3) {
write_byte = mp_obj_get_int(args[2]);
}
size_t chunk_size = 1024;
size_t count = dest_buf.len / chunk_size;
size_t i = 0;
for (size_t j = 0; j < count; ++j) {
for (size_t k = 0; k < chunk_size; ++k) {
((uint8_t*)dest_buf.buf)[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8,
(uint32_t)write_byte, 8, 0);
++i;
}
ets_loop_iter();
}
while (i < dest_buf.len) {
((uint8_t*)dest_buf.buf)[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8,
(uint32_t)write_byte, 8, 0);
++i;
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_hspi_readinto_obj, 2, 3, pyb_hspi_readinto);
STATIC mp_obj_t pyb_hspi_write(mp_obj_t self_in, mp_obj_t wr_buf_in) {
mp_buffer_info_t src_buf;
mp_get_buffer_raise(wr_buf_in, &src_buf, MP_BUFFER_READ);
size_t chunk_size = 1024;
size_t count = src_buf.len / chunk_size;
size_t i = 0;
for (size_t j = 0; j < count; ++j) {
for (size_t k = 0; k < chunk_size; ++k) {
spi_tx8fast(HSPI, ((const uint8_t*)src_buf.buf)[i]);
++i;
}
ets_loop_iter();
}
while (i < src_buf.len) {
spi_tx8fast(HSPI, ((const uint8_t*)src_buf.buf)[i]);
++i;
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(pyb_hspi_write_obj, pyb_hspi_write);
STATIC mp_obj_t pyb_hspi_write_readinto(mp_obj_t self_in, mp_obj_t wr_buf_in, mp_obj_t rd_buf_in) {
mp_buffer_info_t src_buf;
mp_get_buffer_raise(wr_buf_in, &src_buf, MP_BUFFER_READ);
mp_buffer_info_t dest_buf;
mp_get_buffer_raise(rd_buf_in, &dest_buf, MP_BUFFER_WRITE);
if (src_buf.len != dest_buf.len) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"buffers must be the same length"));
}
size_t chunk_size = 1024;
size_t count = src_buf.len / chunk_size;
size_t i = 0;
for (size_t j = 0; j < count; ++j) {
for (size_t k = 0; k < chunk_size; ++k) {
((uint8_t*)dest_buf.buf)[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8,
(uint32_t)(((const uint8_t*)src_buf.buf)[i]), 8, 0);
++i;
}
ets_loop_iter();
}
while (i < src_buf.len) {
((uint8_t*)dest_buf.buf)[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8,
(uint32_t)(((const uint8_t*)src_buf.buf)[i]), 8, 0);
++i;
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(pyb_hspi_write_readinto_obj, pyb_hspi_write_readinto);
STATIC const mp_rom_map_elem_t pyb_hspi_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_hspi_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&pyb_hspi_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&pyb_hspi_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&pyb_hspi_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&pyb_hspi_write_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_hspi_locals_dict, pyb_hspi_locals_dict_table);
STATIC const mp_machine_spi_p_t pyb_hspi_p = {
.transfer = hspi_transfer,
};
const mp_obj_type_t pyb_hspi_type = {
{ &mp_type_type },
.name = MP_QSTR_HSPI,
.print = pyb_hspi_print,
.make_new = pyb_hspi_make_new,
.protocol = &pyb_hspi_p,
.locals_dict = (mp_obj_dict_t*)&pyb_hspi_locals_dict,
};

View File

@ -212,7 +212,7 @@ STATIC mp_obj_t pyb_rtc_alarm(mp_obj_t self_in, mp_obj_t alarm_id, mp_obj_t time
}
// set expiry time (in microseconds)
pyb_rtc_alarm0_expiry = pyb_rtc_get_us_since_2000() + mp_obj_get_int(time_in) * 1000;
pyb_rtc_alarm0_expiry = pyb_rtc_get_us_since_2000() + (uint64_t)mp_obj_get_int(time_in) * 1000;
return mp_const_none;

View File

@ -35,6 +35,7 @@
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mphal.h"
#include "extmod/machine_spi.h"
typedef struct _pyb_spi_obj_t {
mp_obj_base_t base;
@ -46,7 +47,8 @@ typedef struct _pyb_spi_obj_t {
mp_hal_pin_obj_t miso;
} pyb_spi_obj_t;
STATIC void mp_hal_spi_transfer(pyb_spi_obj_t *self, size_t src_len, const uint8_t *src_buf, size_t dest_len, uint8_t *dest_buf) {
STATIC void mp_hal_spi_transfer(mp_obj_base_t *self_in, size_t src_len, const uint8_t *src_buf, size_t dest_len, uint8_t *dest_buf) {
pyb_spi_obj_t *self = (pyb_spi_obj_t*)self_in;
// only MSB transfer is implemented
uint32_t delay_half = 500000 / self->baudrate + 1;
for (size_t i = 0; i < src_len || i < dest_len; ++i) {
@ -154,69 +156,25 @@ STATIC mp_obj_t pyb_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_a
}
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_init_obj, 1, pyb_spi_init);
STATIC mp_obj_t pyb_spi_read(size_t n_args, const mp_obj_t *args) {
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(args[0]);
uint8_t write_byte = 0;
if (n_args == 3) {
write_byte = mp_obj_get_int(args[2]);
}
vstr_t vstr;
vstr_init_len(&vstr, mp_obj_get_int(args[1]));
mp_hal_spi_transfer(self, 1, &write_byte, vstr.len, (uint8_t*)vstr.buf);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_spi_read_obj, 2, 3, pyb_spi_read);
STATIC mp_obj_t pyb_spi_readinto(size_t n_args, const mp_obj_t *args) {
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(args[0]);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
uint8_t write_byte = 0;
if (n_args == 3) {
write_byte = mp_obj_get_int(args[2]);
}
mp_hal_spi_transfer(self, 1, &write_byte, bufinfo.len, (uint8_t*)bufinfo.buf);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_spi_readinto_obj, 2, 3, pyb_spi_readinto);
STATIC mp_obj_t pyb_spi_write(mp_obj_t self_in, mp_obj_t wr_buf_in) {
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t src_buf;
mp_get_buffer_raise(wr_buf_in, &src_buf, MP_BUFFER_READ);
mp_hal_spi_transfer(self, src_buf.len, (const uint8_t*)src_buf.buf, 0, NULL);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(pyb_spi_write_obj, pyb_spi_write);
STATIC mp_obj_t pyb_spi_write_readinto(mp_obj_t self_in, mp_obj_t wr_buf_in, mp_obj_t rd_buf_in) {
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_buffer_info_t src_buf;
mp_get_buffer_raise(wr_buf_in, &src_buf, MP_BUFFER_READ);
mp_buffer_info_t dest_buf;
mp_get_buffer_raise(rd_buf_in, &dest_buf, MP_BUFFER_WRITE);
if (src_buf.len != dest_buf.len) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "buffers must be the same length"));
}
mp_hal_spi_transfer(self, src_buf.len, (const uint8_t*)src_buf.buf, dest_buf.len, (uint8_t*)dest_buf.buf);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(pyb_spi_write_readinto_obj, pyb_spi_write_readinto);
STATIC const mp_rom_map_elem_t pyb_spi_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_spi_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&pyb_spi_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&pyb_spi_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&pyb_spi_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&pyb_spi_write_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) },
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table);
STATIC const mp_machine_spi_p_t pyb_spi_p = {
.transfer = mp_hal_spi_transfer,
};
const mp_obj_type_t pyb_spi_type = {
{ &mp_type_type },
.name = MP_QSTR_SoftSPI,
.print = pyb_spi_print,
.make_new = pyb_spi_make_new,
.protocol = &pyb_spi_p,
.locals_dict = (mp_obj_dict_t*)&pyb_spi_locals_dict,
};

View File

@ -0,0 +1,46 @@
# DS18x20 temperature sensor driver for MicroPython.
# MIT license; Copyright (c) 2016 Damien P. George
_CONVERT = const(0x44)
_RD_SCRATCH = const(0xbe)
_WR_SCRATCH = const(0x4e)
class DS18X20:
def __init__(self, onewire):
self.ow = onewire
self.buf = bytearray(9)
def scan(self):
return [rom for rom in self.ow.scan() if rom[0] == 0x10 or rom[0] == 0x28]
def convert_temp(self):
self.ow.reset(True)
self.ow.writebyte(self.ow.SKIP_ROM)
self.ow.writebyte(_CONVERT)
def read_scratch(self, rom):
self.ow.reset(True)
self.ow.select_rom(rom)
self.ow.writebyte(_RD_SCRATCH)
self.ow.readinto(self.buf)
if self.ow.crc8(self.buf):
raise Exception('CRC error')
return self.buf
def write_scratch(self, rom, buf):
self.ow.reset(True)
self.ow.select_rom(rom)
self.ow.writebyte(_WR_SCRATCH)
self.ow.write(buf)
def read_temp(self, rom):
buf = self.read_scratch(rom)
if rom[0] == 0x10:
if buf[1]:
t = buf[0] >> 1 | 0x80
t = -((~t + 1) & 0xff)
else:
t = buf[0] >> 1
return t - 0.25 + (buf[7] - buf[6]) / buf[7]
else:
return (buf[1] << 8 | buf[0]) / 16

View File

@ -15,8 +15,11 @@ class OneWire:
self.pin = pin
self.pin.init(pin.OPEN_DRAIN)
def reset(self):
return _ow.reset(self.pin)
def reset(self, required=False):
reset = _ow.reset(self.pin)
if required and not reset:
raise OneWireError
return reset
def readbit(self):
return _ow.readbit(self.pin)
@ -24,11 +27,9 @@ class OneWire:
def readbyte(self):
return _ow.readbyte(self.pin)
def read(self, count):
buf = bytearray(count)
for i in range(count):
def readinto(self, buf):
for i in range(len(buf)):
buf[i] = _ow.readbyte(self.pin)
return buf
def writebit(self, value):
return _ow.writebit(self.pin, value)
@ -87,41 +88,3 @@ class OneWire:
def crc8(self, data):
return _ow.crc8(data)
class DS18B20:
CONVERT = const(0x44)
RD_SCRATCH = const(0xbe)
WR_SCRATCH = const(0x4e)
def __init__(self, onewire):
self.ow = onewire
def scan(self):
return [rom for rom in self.ow.scan() if rom[0] == 0x28]
def convert_temp(self):
if not self.ow.reset():
raise OneWireError
self.ow.writebyte(SKIP_ROM)
self.ow.writebyte(CONVERT)
def read_scratch(self, rom):
if not self.ow.reset():
raise OneWireError
self.ow.select_rom(rom)
self.ow.writebyte(RD_SCRATCH)
buf = self.ow.read(9)
if self.ow.crc8(buf):
raise OneWireError
return buf
def write_scratch(self, rom, buf):
if not self.ow.reset():
raise OneWireError
self.ow.select_rom(rom)
self.ow.writebyte(WR_SCRATCH)
self.ow.write(buf)
def read_temp(self, rom):
buf = self.read_scratch(rom)
return (buf[1] << 8 | buf[0]) / 16

View File

@ -123,6 +123,10 @@ STATIC mp_obj_t os_rename(mp_obj_t path_old, mp_obj_t path_new) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename);
STATIC mp_obj_t os_umount(void) {
return vfs_proxy_call(MP_QSTR_umount, 0, NULL);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_umount_obj, os_umount);
#endif
STATIC mp_obj_t os_urandom(mp_obj_t num) {
@ -166,6 +170,7 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&os_remove_obj) },
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&os_rename_obj) },
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&os_stat_obj) },
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&os_umount_obj) },
#endif
};

View File

@ -63,6 +63,7 @@
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_MACHINE_PULSE (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_SPI (1)
#define MICROPY_PY_WEBSOCKET (1)
#define MICROPY_PY_WEBREPL (1)
#define MICROPY_PY_WEBREPL_DELAY (20)

View File

@ -16,10 +16,10 @@ pyb.LED(3).off() # indicate that we finished waiting for the swit
pyb.LED(4).on() # indicate that we are selecting the mode
if switch_value:
pyb.usb_mode('CDC+MSC')
pyb.usb_mode('VCP+MSC')
pyb.main('cardreader.py') # if switch was pressed, run this
else:
pyb.usb_mode('CDC+HID')
pyb.usb_mode('VCP+HID')
pyb.main('datalogger.py') # if switch wasn't pressed, run this
pyb.LED(4).off() # indicate that we finished selecting the mode

View File

@ -162,7 +162,7 @@ STATIC mp_obj_t fatfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
}
MP_DEFINE_CONST_FUN_OBJ_KW(fsuser_mount_obj, 2, fatfs_mount);
STATIC mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in) {
mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in) {
size_t i = 0;
if (MP_OBJ_IS_STR(bdev_or_path_in)) {
mp_uint_t mnt_len;

View File

@ -55,6 +55,7 @@ typedef struct _fs_user_mount_t {
} fs_user_mount_t;
fs_user_mount_t *fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, bool mkfs);
mp_obj_t fatfs_umount(mp_obj_t bdev_or_path_in);
MP_DECLARE_CONST_FUN_OBJ(fsuser_mount_obj);
MP_DECLARE_CONST_FUN_OBJ(fsuser_umount_obj);

85
extmod/machine_spi.c Normal file
View File

@ -0,0 +1,85 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdio.h>
#include "py/runtime.h"
#include "extmod/machine_spi.h"
#if MICROPY_PY_MACHINE_SPI
STATIC void mp_machine_spi_transfer(mp_obj_t self, size_t slen, const uint8_t *src, size_t dlen, uint8_t *dest) {
mp_obj_base_t *s = (mp_obj_base_t*)MP_OBJ_TO_PTR(self);
mp_machine_spi_p_t *spi_p = (mp_machine_spi_p_t*)s->type->protocol;
spi_p->transfer(s, slen, src, dlen, dest);
}
STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) {
uint8_t write_byte = 0;
if (n_args == 3) {
write_byte = mp_obj_get_int(args[2]);
}
vstr_t vstr;
vstr_init_len(&vstr, mp_obj_get_int(args[1]));
mp_machine_spi_transfer(args[0], 1, &write_byte, vstr.len, (uint8_t*)vstr.buf);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read);
STATIC mp_obj_t mp_machine_spi_readinto(size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
uint8_t write_byte = 0;
if (n_args == 3) {
write_byte = mp_obj_get_int(args[2]);
}
mp_machine_spi_transfer(args[0], 1, &write_byte, bufinfo.len, (uint8_t*)bufinfo.buf);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj, 2, 3, mp_machine_spi_readinto);
STATIC mp_obj_t mp_machine_spi_write(mp_obj_t self, mp_obj_t wr_buf) {
mp_buffer_info_t src;
mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ);
mp_machine_spi_transfer(self, src.len, (const uint8_t*)src.buf, 0, NULL);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj, mp_machine_spi_write);
STATIC mp_obj_t mp_machine_spi_write_readinto(mp_obj_t self, mp_obj_t wr_buf, mp_obj_t rd_buf) {
mp_buffer_info_t src;
mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ);
mp_buffer_info_t dest;
mp_get_buffer_raise(rd_buf, &dest, MP_BUFFER_WRITE);
if (src.len != dest.len) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "buffers must be the same length"));
}
mp_machine_spi_transfer(self, src.len, (const uint8_t*)src.buf, dest.len, (uint8_t*)dest.buf);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj, mp_machine_spi_write_readinto);
#endif // MICROPY_PY_MACHINE_SPI

42
extmod/machine_spi.h Normal file
View File

@ -0,0 +1,42 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 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.
*/
#ifndef MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
#define MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H
#include "py/obj.h"
// SPI protocol
typedef struct _mp_machine_spi_p_t {
void (*transfer)(mp_obj_base_t *obj, size_t slen, const uint8_t *src, size_t dlen, uint8_t *dest);
} mp_machine_spi_p_t;
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_read_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_readinto_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_write_obj);
MP_DECLARE_CONST_FUN_OBJ(mp_machine_spi_write_readinto_obj);
#endif // MICROPY_INCLUDED_EXTMOD_MACHINE_SPI_H

View File

@ -68,7 +68,8 @@ STATIC mp_obj_t framebuf1_fill(mp_obj_t self_in, mp_obj_t col_in) {
if (col) {
col = 0xff;
}
for (int y = 0; y < self->height / 8; ++y) {
int end = (self->height + 7) >> 3;
for (int y = 0; y < end; ++y) {
memset(self->buf + y * self->stride, col, self->width);
}
return mp_const_none;
@ -83,7 +84,7 @@ STATIC mp_obj_t framebuf1_pixel(size_t n_args, const mp_obj_t *args) {
int index = (y / 8) * self->stride + x;
if (n_args == 3) {
// get
return MP_OBJ_NEW_SMALL_INT(self->buf[index] >> (y & 7));
return MP_OBJ_NEW_SMALL_INT((self->buf[index] >> (y & 7)) & 1);
} else {
// set
if (mp_obj_get_int(args[3])) {
@ -101,8 +102,9 @@ STATIC mp_obj_t framebuf1_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t y
mp_obj_framebuf1_t *self = MP_OBJ_TO_PTR(self_in);
mp_int_t xstep = mp_obj_get_int(xstep_in);
mp_int_t ystep = mp_obj_get_int(ystep_in);
int end = (self->height + 7) >> 3;
if (xstep == 0 && ystep > 0) {
for (int y = self->height / 8; y > 0;) {
for (int y = end; y > 0;) {
--y;
for (int x = 0; x < self->width; ++x) {
int prev = 0;
@ -113,10 +115,10 @@ STATIC mp_obj_t framebuf1_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t y
}
}
} else if (xstep == 0 && ystep < 0) {
for (int y = 0; y < self->height / 8; ++y) {
for (int y = 0; y < end; ++y) {
for (int x = 0; x < self->width; ++x) {
int prev = 0;
if (y + 1 < self->height / 8) {
if (y + 1 < end) {
prev = self->buf[(y + 1) * self->stride + x] << (8 + ystep);
}
self->buf[y * self->stride + x] = (self->buf[y * self->stride + x] >> -ystep) | prev;

View File

@ -33,6 +33,7 @@
#include "py/binary.h"
#include "extmod/modubinascii.h"
#include "uzlib/tinf.h"
mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {
// Second argument is for an extension to allow a separator to be used
@ -203,6 +204,17 @@ mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
}
MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj, mod_binascii_b2a_base64);
#if MICROPY_PY_UBINASCII_CRC32
mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
uint32_t crc = (n_args > 1) ? mp_obj_get_int(args[1]) : 0;
crc = uzlib_crc32(bufinfo.buf, bufinfo.len, crc ^ 0xffffffff);
return MP_OBJ_NEW_SMALL_INT(crc ^ 0xffffffff);
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_binascii_crc32_obj, 1, 2, mod_binascii_crc32);
#endif
#if MICROPY_PY_UBINASCII
STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = {
@ -211,6 +223,9 @@ STATIC const mp_rom_map_elem_t mp_module_binascii_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_unhexlify), MP_ROM_PTR(&mod_binascii_unhexlify_obj) },
{ MP_ROM_QSTR(MP_QSTR_a2b_base64), MP_ROM_PTR(&mod_binascii_a2b_base64_obj) },
{ MP_ROM_QSTR(MP_QSTR_b2a_base64), MP_ROM_PTR(&mod_binascii_b2a_base64_obj) },
#if MICROPY_PY_UBINASCII_CRC32
{ MP_ROM_QSTR(MP_QSTR_crc32), MP_ROM_PTR(&mod_binascii_crc32_obj) },
#endif
};
STATIC MP_DEFINE_CONST_DICT(mp_module_binascii_globals, mp_module_binascii_globals_table);

View File

@ -31,10 +31,12 @@ extern mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args);
extern mp_obj_t mod_binascii_unhexlify(mp_obj_t data);
extern mp_obj_t mod_binascii_a2b_base64(mp_obj_t data);
extern mp_obj_t mod_binascii_b2a_base64(mp_obj_t data);
extern mp_obj_t mod_binascii_crc32(size_t n_args, const mp_obj_t *args);
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_hexlify_obj);
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_unhexlify_obj);
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_a2b_base64_obj);
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_b2a_base64_obj);
MP_DECLARE_CONST_FUN_OBJ(mod_binascii_crc32_obj);
#endif /* MICROPY_EXTMOD_MODUBINASCII */

View File

@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2014 Paul Sokolovsky
* Copyright (c) 2014-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
@ -29,6 +29,8 @@
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mperrno.h"
#if MICROPY_PY_UZLIB
@ -40,6 +42,85 @@
#define DEBUG_printf(...) (void)0
#endif
typedef struct _mp_obj_decompio_t {
mp_obj_base_t base;
mp_obj_t src_stream;
TINF_DATA decomp;
bool eof;
} mp_obj_decompio_t;
STATIC unsigned char read_src_stream(TINF_DATA *data) {
byte *p = (void*)data;
p -= offsetof(mp_obj_decompio_t, decomp);
mp_obj_decompio_t *self = (mp_obj_decompio_t*)p;
const mp_stream_p_t *stream = mp_get_stream_raise(self->src_stream, MP_STREAM_OP_READ);
int err;
byte c;
mp_uint_t out_sz = stream->read(self->src_stream, &c, 1, &err);
if (out_sz == MP_STREAM_ERROR) {
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(err)));
}
if (out_sz == 0) {
nlr_raise(mp_obj_new_exception(&mp_type_EOFError));
}
return c;
}
#define DICT_SIZE 32768
STATIC mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, 1, false);
mp_obj_decompio_t *o = m_new_obj(mp_obj_decompio_t);
o->base.type = type;
memset(&o->decomp, 0, sizeof(o->decomp));
uzlib_uncompress_init(&o->decomp, m_new(byte, DICT_SIZE), DICT_SIZE);
o->decomp.readSource = read_src_stream;
o->src_stream = args[0];
o->eof = false;
return MP_OBJ_FROM_PTR(o);
}
STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
mp_obj_decompio_t *o = MP_OBJ_TO_PTR(o_in);
if (o->eof) {
return 0;
}
o->decomp.dest = buf;
o->decomp.destSize = size;
int st = uzlib_uncompress_chksum(&o->decomp);
if (st == TINF_DONE) {
o->eof = true;
}
if (st < 0) {
*errcode = MP_EINVAL;
return MP_STREAM_ERROR;
}
return o->decomp.dest - (byte*)buf;
}
STATIC const mp_rom_map_elem_t decompio_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
{ MP_ROM_QSTR(MP_QSTR_readall), MP_ROM_PTR(&mp_stream_readall_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) },
};
STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
STATIC const mp_stream_p_t decompio_stream_p = {
.read = decompio_read,
};
STATIC const mp_obj_type_t decompio_type = {
{ &mp_type_type },
.name = MP_QSTR_DecompIO,
.make_new = decompio_make_new,
.protocol = &decompio_stream_p,
.locals_dict = (void*)&decompio_locals_dict,
};
STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
(void)n_args;
mp_obj_t data = args[0];
@ -102,6 +183,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_uzlib_decompress_obj, 1, 3, mod_u
STATIC const mp_rom_map_elem_t mp_module_uzlib_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uzlib) },
{ MP_ROM_QSTR(MP_QSTR_decompress), MP_ROM_PTR(&mod_uzlib_decompress_obj) },
{ MP_ROM_QSTR(MP_QSTR_DecompIO), MP_ROM_PTR(&decompio_type) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_uzlib_globals, mp_module_uzlib_globals_table);

View File

@ -250,6 +250,13 @@ STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_stat_obj, fat_vfs_stat);
// Unmount the filesystem
STATIC mp_obj_t fat_vfs_umount(mp_obj_t vfs_in) {
fatfs_umount(((fs_user_mount_t *)vfs_in)->readblocks[1]);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, fat_vfs_umount);
STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) },
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) },
@ -261,6 +268,7 @@ STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&fat_vfs_remove_obj) },
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&fat_vfs_rename_obj) },
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&fat_vfs_stat_obj) },
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&fat_vfs_umount_obj) },
};
STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table);

@ -1 +1 @@
Subproject commit 78a4787948bb80cbfafcfd7910f95f61a4dd0d4c
Subproject commit dab957dacddcbf6cbc85d42df62e189e4877bb72

View File

@ -112,7 +112,7 @@ STATIC int parse_compile_execute(void *source, mp_parse_input_kind_t input_kind,
printf("took " UINT_FMT " ms\n", ticks);
// qstr info
{
mp_uint_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes;
size_t n_pool, n_qstr, n_str_data_bytes, n_total_bytes;
qstr_pool_info(&n_pool, &n_qstr, &n_str_data_bytes, &n_total_bytes);
printf("qstr:\n n_pool=" UINT_FMT "\n n_qstr=" UINT_FMT "\n n_str_data_bytes=" UINT_FMT "\n n_total_bytes=" UINT_FMT "\n", n_pool, n_qstr, n_str_data_bytes, n_total_bytes);
}

View File

@ -11,7 +11,7 @@
// Send "cooked" string of given length, where every occurance of
// LF character is replaced with CR LF.
void mp_hal_stdout_tx_strn_cooked(const char *str, mp_uint_t len) {
void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {
while (len--) {
if (*str == '\n') {
mp_hal_stdout_tx_strn("\r", 1);

View File

@ -89,7 +89,7 @@ STATIC void dump_args(const mp_obj_t *a, size_t sz) {
// - code_state->ip should contain the offset in bytes from the start of
// the bytecode chunk to just after n_state and n_exc_stack
// - code_state->n_state should be set to the state size (locals plus stack)
void mp_setup_code_state(mp_code_state *code_state, mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) {
void mp_setup_code_state(mp_code_state_t *code_state, mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) {
// This function is pretty complicated. It's main aim is to be efficient in speed and RAM
// usage for the common case of positional only args.
size_t n_state = code_state->n_state;

14
py/bc.h
View File

@ -60,7 +60,7 @@
// constN : obj
// Exception stack entry
typedef struct _mp_exc_stack {
typedef struct _mp_exc_stack_t {
const byte *handler;
// bit 0 is saved currently_in_except_block value
// bit 1 is whether the opcode was SETUP_WITH or SETUP_FINALLY
@ -69,7 +69,7 @@ typedef struct _mp_exc_stack {
mp_obj_base_t *prev_exc;
} mp_exc_stack_t;
typedef struct _mp_code_state {
typedef struct _mp_code_state_t {
const byte *code_info;
const byte *ip;
const mp_uint_t *const_table;
@ -78,21 +78,21 @@ typedef struct _mp_code_state {
mp_exc_stack_t *exc_sp;
mp_obj_dict_t *old_globals;
#if MICROPY_STACKLESS
struct _mp_code_state *prev;
struct _mp_code_state_t *prev;
#endif
size_t n_state;
// Variable-length
mp_obj_t state[0];
// Variable-length, never accessed by name, only as (void*)(state + n_state)
//mp_exc_stack_t exc_state[0];
} mp_code_state;
} mp_code_state_t;
mp_uint_t mp_decode_uint(const byte **ptr);
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_obj_t inject_exc);
mp_code_state *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args);
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc);
mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args);
struct _mp_obj_fun_bc_t;
void mp_setup_code_state(mp_code_state *code_state, struct _mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args);
void mp_setup_code_state(mp_code_state_t *code_state, struct _mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args);
void mp_bytecode_print(const void *descr, const byte *code, mp_uint_t len, const mp_uint_t *const_table);
void mp_bytecode_print2(const byte *code, mp_uint_t len);
const byte *mp_bytecode_print_str(const byte *ip);

View File

@ -1200,6 +1200,11 @@ STATIC void compile_nonlocal_stmt(compiler_t *comp, mp_parse_node_struct_t *pns)
}
STATIC void compile_assert_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
// with optimisations enabled we don't compile assertions
if (MP_STATE_VM(mp_optimise_value) != 0) {
return;
}
uint l_end = comp_next_label(comp);
c_if_cond(comp, pns->nodes[0], true, l_end);
EMIT_LOAD_GLOBAL(MP_QSTR_AssertionError); // we load_global instead of load_id, to be consistent with CPython

View File

@ -348,12 +348,10 @@ mp_raw_code_t *mp_raw_code_load(mp_reader_t *reader) {
byte header[4];
read_bytes(reader, header, sizeof(header));
if (strncmp((char*)header, "M\x00", 2) != 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"invalid .mpy file"));
mp_raise_ValueError("invalid .mpy file");
}
if (header[2] != MPY_FEATURE_FLAGS || header[3] > mp_small_int_bits()) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"incompatible .mpy file"));
mp_raise_ValueError("incompatible .mpy file");
}
return load_raw_code(reader);
}
@ -559,8 +557,7 @@ STATIC void save_bytecode_qstrs(mp_print_t *print, const byte *ip, const byte *i
STATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc) {
if (rc->kind != MP_CODE_BYTECODE) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
"can only save bytecode"));
mp_raise_ValueError("can only save bytecode");
}
// save bytecode

View File

@ -628,7 +628,7 @@ STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg);
STATIC void emit_native_load_fast(emit_t *emit, qstr qst, mp_uint_t local_num);
STATIC void emit_native_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num);
#define STATE_START (sizeof(mp_code_state) / sizeof(mp_uint_t))
#define STATE_START (sizeof(mp_code_state_t) / sizeof(mp_uint_t))
STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
DEBUG_printf("start_pass(pass=%u, scope=%p)\n", pass, scope);
@ -775,10 +775,10 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
// set code_state.ip (offset from start of this function to prelude info)
// XXX this encoding may change size
ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state, ip) / sizeof(mp_uint_t), REG_ARG_1);
ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state_t, ip) / sizeof(mp_uint_t), REG_ARG_1);
// set code_state.n_state
ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->n_state, offsetof(mp_code_state, n_state) / sizeof(mp_uint_t), REG_ARG_1);
ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->n_state, offsetof(mp_code_state_t, n_state) / sizeof(mp_uint_t), REG_ARG_1);
// put address of code_state into first arg
ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, 0, REG_ARG_1);

10
py/gc.c
View File

@ -480,12 +480,17 @@ found:
GC_EXIT();
#if MICROPY_GC_CONSERVATIVE_CLEAR
// be conservative and zero out all the newly allocated blocks
memset((byte*)ret_ptr, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK);
#else
// zero out the additional bytes of the newly allocated blocks
// This is needed because the blocks may have previously held pointers
// to the heap and will not be set to something else if the caller
// doesn't actually use the entire block. As such they will continue
// to point to the heap and may prevent other blocks from being reclaimed.
memset((byte*)ret_ptr + n_bytes, 0, (end_block - start_block + 1) * BYTES_PER_BLOCK - n_bytes);
#endif
#if MICROPY_ENABLE_FINALISER
if (has_finaliser) {
@ -713,8 +718,13 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) {
GC_EXIT();
#if MICROPY_GC_CONSERVATIVE_CLEAR
// be conservative and zero out all the newly allocated blocks
memset((byte*)ptr_in + n_blocks * BYTES_PER_BLOCK, 0, (new_blocks - n_blocks) * BYTES_PER_BLOCK);
#else
// zero out the additional bytes of the newly allocated blocks (see comment above in gc_alloc)
memset((byte*)ptr_in + n_bytes, 0, new_blocks * BYTES_PER_BLOCK - n_bytes);
#endif
#if EXTENSIVE_HEAP_PROFILING
gc_dump_alloc_table();

View File

@ -14,11 +14,13 @@ import sys
# - codepoint2name lives in a different module
import platform
if platform.python_version_tuple()[0] == '2':
ord_bytes = ord
bytes_cons = lambda val, enc=None: bytearray(val)
from htmlentitydefs import codepoint2name
elif platform.python_version_tuple()[0] == '3':
ord_bytes = lambda x:x
bytes_cons = bytes
from html.entities import codepoint2name
# end compatibility code
codepoint2name[ord('-')] = 'hyphen';
# add some custom names to map characters that aren't in HTML
@ -52,8 +54,8 @@ codepoint2name[ord('~')] = 'tilde'
# this must match the equivalent function in qstr.c
def compute_hash(qstr, bytes_hash):
hash = 5381
for char in qstr:
hash = (hash * 33) ^ ord(char)
for b in qstr:
hash = (hash * 33) ^ b
# Make sure that valid hash is never zero, zero means "hash not computed"
return (hash & ((1 << (8 * bytes_hash)) - 1)) or 1
@ -115,16 +117,15 @@ def parse_input_headers(infiles):
return qcfgs, qstrs
def make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr):
qhash = compute_hash(qstr, cfg_bytes_hash)
qbytes = bytes_cons(qstr, 'utf8')
qlen = len(qbytes)
qhash = compute_hash(qbytes, cfg_bytes_hash)
if all(32 <= ord(c) <= 126 and c != '\\' and c != '"' for c in qstr):
# qstr is all printable ASCII so render it as-is (for easier debugging)
qlen = len(qstr)
qdata = qstr
else:
# qstr contains non-printable codes so render entire thing as hex pairs
qbytes = qstr.encode('utf8')
qlen = len(qbytes)
qdata = ''.join(('\\x%02x' % ord_bytes(b)) for b in qbytes)
qdata = ''.join(('\\x%02x' % b) for b in qbytes)
if qlen >= (1 << (8 * cfg_bytes_len)):
print('qstr is too long:', qstr)
assert False

View File

@ -117,7 +117,10 @@ void *m_malloc0(size_t num_bytes) {
if (ptr == NULL && num_bytes != 0) {
return m_malloc_fail(num_bytes);
}
// If this config is set then the GC clears all memory, so we don't need to.
#if !MICROPY_GC_CONSERVATIVE_CLEAR
memset(ptr, 0, num_bytes);
#endif
return ptr;
}

View File

@ -123,8 +123,9 @@ clean-prog:
.PHONY: clean-prog
endif
lib: $(OBJ)
$(AR) rcs libmicropython.a $^
LIBMICROPYTHON = libmicropython.a
lib $(LIBMICROPYTHON): $(OBJ)
$(AR) rcs $(LIBMICROPYTHON) $^
clean:
$(RM) -rf $(BUILD) $(CLEAN_EXTRA)

View File

@ -114,7 +114,7 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
mp_uint_t align;
size_t sz = mp_binary_get_size(fmt_type, *fmt, &align);
if (sz == 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "unsupported format"));
mp_raise_ValueError("unsupported format");
}
while (cnt--) {
// Apply alignment
@ -149,7 +149,7 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) {
// negative offsets are relative to the end of the buffer
offset = bufinfo.len + offset;
if (offset < 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "buffer too small"));
mp_raise_ValueError("buffer too small");
}
}
p += offset;
@ -164,7 +164,7 @@ STATIC mp_obj_t struct_unpack_from(size_t n_args, const mp_obj_t *args) {
sz = get_fmt_num(&fmt);
}
if (p + sz > end_p) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "buffer too small"));
mp_raise_ValueError("buffer too small");
}
mp_obj_t item;
if (*fmt == 's') {
@ -197,7 +197,7 @@ STATIC void struct_pack_into_internal(mp_obj_t fmt_in, byte *p, byte* end_p, siz
sz = get_fmt_num(&fmt);
}
if (p + sz > end_p) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "buffer too small"));
mp_raise_ValueError("buffer too small");
}
if (*fmt == 's') {
@ -240,7 +240,7 @@ STATIC mp_obj_t struct_pack_into(size_t n_args, const mp_obj_t *args) {
// negative offsets are relative to the end of the buffer
offset = (mp_int_t)bufinfo.len + offset;
if (offset < 0) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "buffer too small"));
mp_raise_ValueError("buffer too small");
}
}
byte *p = (byte *)bufinfo.buf;

View File

@ -107,6 +107,15 @@
#define MICROPY_ALLOC_GC_STACK_SIZE (64)
#endif
// Be conservative and always clear to zero newly (re)allocated memory in the GC.
// This helps eliminate stray pointers that hold on to memory that's no longer
// used. It decreases performance due to unnecessary memory clearing.
// TODO Do analysis to understand why some memory is not properly cleared and
// find a more efficient way to clear it.
#ifndef MICROPY_GC_CONSERVATIVE_CLEAR
#define MICROPY_GC_CONSERVATIVE_CLEAR (1)
#endif
// Support automatic GC when reaching allocation threshold,
// configurable by gc.threshold().
#ifndef MICROPY_GC_ALLOC_THRESHOLD
@ -887,6 +896,11 @@ typedef double mp_float_t;
#define MICROPY_PY_UBINASCII (0)
#endif
// Depends on MICROPY_PY_UZLIB
#ifndef MICROPY_PY_UBINASCII_CRC32
#define MICROPY_PY_UBINASCII_CRC32 (0)
#endif
#ifndef MICROPY_PY_URANDOM
#define MICROPY_PY_URANDOM (0)
#endif
@ -909,6 +923,10 @@ typedef double mp_float_t;
#define MICROPY_PY_MACHINE_I2C (0)
#endif
#ifndef MICROPY_PY_MACHINE_SPI
#define MICROPY_PY_MACHINE_SPI (0)
#endif
#ifndef MICROPY_PY_USSL
#define MICROPY_PY_USSL (0)
#endif

View File

@ -537,10 +537,12 @@ int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args) {
chrs += mp_print_int(print, arg_value, *fmt == 'd', 10, 'a', flags, fill, width);
break;
}
// fall through to default case to print unknown format char
assert(!"unsupported fmt char");
}
#endif
default:
// if it's not %% then it's an unsupported format character
assert(*fmt == '%' || !"unsupported fmt char");
print->print_strn(print->data, fmt, 1);
chrs += 1;
break;

View File

@ -165,7 +165,7 @@ STATIC void dump_args(const mp_obj_t *a, mp_uint_t sz) {
#define VM_DETECT_STACK_OVERFLOW (0)
#if MICROPY_STACKLESS
mp_code_state *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
MP_STACK_CHECK();
mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in);
@ -178,8 +178,8 @@ mp_code_state *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args,
// allocate state for locals and stack
size_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);
mp_code_state *code_state;
code_state = m_new_obj_var_maybe(mp_code_state, byte, state_size);
mp_code_state_t *code_state;
code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size);
if (!code_state) {
return NULL;
}
@ -220,12 +220,12 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
// allocate state for locals and stack
mp_uint_t state_size = n_state * sizeof(mp_obj_t) + n_exc_stack * sizeof(mp_exc_stack_t);
mp_code_state *code_state = NULL;
mp_code_state_t *code_state = NULL;
if (state_size > VM_MAX_STATE_ON_STACK) {
code_state = m_new_obj_var_maybe(mp_code_state, byte, state_size);
code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size);
}
if (code_state == NULL) {
code_state = alloca(sizeof(mp_code_state) + state_size);
code_state = alloca(sizeof(mp_code_state_t) + state_size);
state_size = 0; // indicate that we allocated using alloca
}
@ -287,7 +287,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
// free the state if it was allocated on the heap
if (state_size != 0) {
m_del_var(mp_code_state, byte, state_size, code_state);
m_del_var(mp_code_state_t, byte, state_size, code_state);
}
if (vm_return_kind == MP_VM_RETURN_NORMAL) {

View File

@ -46,7 +46,7 @@ typedef struct _mp_obj_gen_wrap_t {
typedef struct _mp_obj_gen_instance_t {
mp_obj_base_t base;
mp_obj_dict_t *globals;
mp_code_state code_state;
mp_code_state_t code_state;
} mp_obj_gen_instance_t;
STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {

View File

@ -158,6 +158,9 @@ mp_obj_t mp_obj_str_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
if (MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
GET_STR_DATA_LEN(args[0], str_data, str_len);
GET_STR_HASH(args[0], str_hash);
if (str_hash == 0) {
str_hash = qstr_compute_hash(str_data, str_len);
}
mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(type, NULL, str_len));
o->data = str_data;
o->hash = str_hash;
@ -191,6 +194,9 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size
}
GET_STR_DATA_LEN(args[0], str_data, str_len);
GET_STR_HASH(args[0], str_hash);
if (str_hash == 0) {
str_hash = qstr_compute_hash(str_data, str_len);
}
mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(&mp_type_bytes, NULL, str_len));
o->data = str_data;
o->hash = str_hash;

View File

@ -39,6 +39,7 @@ typedef struct _mp_obj_str_t {
#define MP_DEFINE_STR_OBJ(obj_name, str) mp_obj_str_t obj_name = {{&mp_type_str}, 0, sizeof(str) - 1, (const byte*)str}
// use this macro to extract the string hash
// warning: the hash can be 0, meaning invalid, and must then be explicitly computed from the data
#define GET_STR_HASH(str_obj_in, str_hash) \
mp_uint_t str_hash; if (MP_OBJ_IS_QSTR(str_obj_in)) \
{ str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->hash; }

View File

@ -208,6 +208,7 @@ PY_O_BASENAME = \
../extmod/machine_pinbase.o \
../extmod/machine_pulse.o \
../extmod/machine_i2c.o \
../extmod/machine_spi.o \
../extmod/modussl_axtls.o \
../extmod/modurandom.o \
../extmod/modwebsocket.o \

View File

@ -217,6 +217,10 @@ mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) {
} else if (op == MP_UNARY_OP_HASH && MP_OBJ_IS_STR_OR_BYTES(arg)) {
// fast path for hashing str/bytes
GET_STR_HASH(arg, h);
if (h == 0) {
GET_STR_DATA_LEN(arg, data, len);
h = qstr_compute_hash(data, len);
}
return MP_OBJ_NEW_SMALL_INT(h);
} else {
mp_obj_type_t *type = mp_obj_get_type(arg);

10
py/vm.c
View File

@ -127,7 +127,7 @@ typedef enum {
// MP_VM_RETURN_NORMAL, sp valid, return value in *sp
// MP_VM_RETURN_YIELD, ip, sp valid, yielded value in *sp
// MP_VM_RETURN_EXCEPTION, exception in fastn[0]
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_obj_t inject_exc) {
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc) {
#define SELECTIVE_EXC_IP (0)
#if SELECTIVE_EXC_IP
#define MARK_EXC_IP_SELECTIVE() { code_state->ip = ip; } /* stores ip 1 byte past last opcode */
@ -904,7 +904,7 @@ unwind_jump:;
code_state->ip = ip;
code_state->sp = sp;
code_state->exc_sp = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1);
mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, unum & 0xff, (unum >> 8) & 0xff, sp + 1);
if (new_state) {
new_state->prev = code_state;
code_state = new_state;
@ -940,7 +940,7 @@ unwind_jump:;
mp_call_args_t out_args;
mp_call_prepare_args_n_kw_var(false, unum, sp, &out_args);
mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
out_args.n_args, out_args.n_kw, out_args.args);
m_del(mp_obj_t, out_args.args, out_args.n_alloc);
if (new_state) {
@ -976,7 +976,7 @@ unwind_jump:;
mp_uint_t n_kw = (unum >> 8) & 0xff;
int adjust = (sp[1] == MP_OBJ_NULL) ? 0 : 1;
mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust);
mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(*sp, n_args + adjust, n_kw, sp + 2 - adjust);
if (new_state) {
new_state->prev = code_state;
code_state = new_state;
@ -1011,7 +1011,7 @@ unwind_jump:;
mp_call_args_t out_args;
mp_call_prepare_args_n_kw_var(true, unum, sp, &out_args);
mp_code_state *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
mp_code_state_t *new_state = mp_obj_fun_bc_prepare_codestate(out_args.fun,
out_args.n_args, out_args.n_kw, out_args.args);
m_del(mp_obj_t, out_args.args, out_args.n_alloc);
if (new_state) {

View File

@ -284,7 +284,7 @@ endif
ifneq ($(FROZEN_MPY_DIR),)
# To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and
# then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch).
FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR)/ -type f -name '*.py')
FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR) -type f -name '*.py')
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY

View File

@ -54,7 +54,16 @@
#define ADCx (ADC1)
#define ADCx_CLK_ENABLE __ADC1_CLK_ENABLE
#define ADC_NUM_CHANNELS (19)
#define ADC_NUM_GPIO_CHANNELS (16)
#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
#define ADC_FIRST_GPIO_CHANNEL (0)
#define ADC_LAST_GPIO_CHANNEL (15)
#elif defined(MCU_SERIES_L4)
#define ADC_FIRST_GPIO_CHANNEL (1)
#define ADC_LAST_GPIO_CHANNEL (16)
#else
#error Unsupported processor
#endif
#if defined(STM32F405xx) || defined(STM32F415xx) || \
defined(STM32F407xx) || defined(STM32F417xx) || \
@ -124,7 +133,7 @@ STATIC void adc_init_single(pyb_obj_adc_t *adc_obj) {
return;
}
if (adc_obj->channel < ADC_NUM_GPIO_CHANNELS) {
if (ADC_FIRST_GPIO_CHANNEL <= adc_obj->channel && adc_obj->channel <= ADC_LAST_GPIO_CHANNEL) {
// Channels 0-16 correspond to real pins. Configure the GPIO pin in
// ADC mode.
const pin_obj_t *pin = pin_adc1[adc_obj->channel];
@ -253,8 +262,14 @@ STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uin
if (!is_adcx_channel(channel)) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "not a valid ADC Channel: %d", channel));
}
if (pin_adc1[channel] == NULL) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "channel %d not available on this board", channel));
if (ADC_FIRST_GPIO_CHANNEL <= channel && channel <= ADC_LAST_GPIO_CHANNEL) {
// these channels correspond to physical GPIO ports so make sure they exist
if (pin_adc1[channel] == NULL) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"channel %d not available on this board", channel));
}
}
pyb_obj_adc_t *o = m_new_obj(pyb_obj_adc_t);
@ -423,7 +438,7 @@ void adc_init_all(pyb_adc_all_obj_t *adc_all, uint32_t resolution) {
"resolution %d not supported", resolution));
}
for (uint32_t channel = 0; channel < ADC_NUM_GPIO_CHANNELS; channel++) {
for (uint32_t channel = ADC_FIRST_GPIO_CHANNEL; channel <= ADC_LAST_GPIO_CHANNEL; ++channel) {
// Channels 0-16 correspond to real pins. Configure the GPIO pin in
// ADC mode.
const pin_obj_t *pin = pin_adc1[channel];

View File

@ -303,7 +303,9 @@ class Pins(object):
def print_adc(self, adc_num):
print('');
print('const pin_obj_t * const pin_adc{:d}[] = {{'.format(adc_num))
for channel in range(16):
for channel in range(17):
if channel == 16:
print('#if defined(MCU_SERIES_L4)')
adc_found = False
for named_pin in self.cpu_pins:
pin = named_pin.pin()
@ -314,6 +316,8 @@ class Pins(object):
break
if not adc_found:
print(' NULL, // {:d}'.format(channel))
if channel == 16:
print('#endif')
print('};')

View File

@ -137,8 +137,8 @@ static const char fresh_boot_py[] =
"import machine\r\n"
"import pyb\r\n"
"#pyb.main('main.py') # main script to run after this one\r\n"
"#pyb.usb_mode('CDC+MSC') # act as a serial and a storage device\r\n"
"#pyb.usb_mode('CDC+HID') # act as a serial device and a mouse\r\n"
"#pyb.usb_mode('VCP+MSC') # act as a serial and a storage device\r\n"
"#pyb.usb_mode('VCP+HID') # act as a serial device and a mouse\r\n"
;
static const char fresh_main_py[] =

View File

@ -83,6 +83,7 @@ STATIC mp_obj_t socket_close(mp_obj_t self_in) {
mod_network_socket_obj_t *self = self_in;
if (self->nic != MP_OBJ_NULL) {
self->nic_type->close(self);
self->nic = MP_OBJ_NULL;
}
return mp_const_none;
}

View File

@ -93,6 +93,7 @@
#define MICROPY_PY_UHASHLIB (1)
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_SPI (1)
#define MICROPY_PY_FRAMEBUF (1)
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)

View File

@ -199,15 +199,15 @@ STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
if (mode == GPIO_MODE_INPUT) {
mode_qst = MP_QSTR_IN;
} else if (mode == GPIO_MODE_OUTPUT_PP) {
mode_qst = MP_QSTR_OUT_PP;
mode_qst = MP_QSTR_OUT;
} else if (mode == GPIO_MODE_OUTPUT_OD) {
mode_qst = MP_QSTR_OUT_OD;
mode_qst = MP_QSTR_OPEN_DRAIN;
} else {
af = true;
if (mode == GPIO_MODE_AF_PP) {
mode_qst = MP_QSTR_AF_PP;
mode_qst = MP_QSTR_ALT;
} else {
mode_qst = MP_QSTR_AF_OD;
mode_qst = MP_QSTR_ALT_OPEN_DRAIN;
}
}
mp_print_str(print, qstr_str(mode_qst));

View File

@ -30,6 +30,7 @@
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "extmod/machine_spi.h"
#include "irq.h"
#include "pin.h"
#include "genhdr/pins.h"
@ -327,6 +328,90 @@ STATIC HAL_StatusTypeDef spi_wait_dma_finished(SPI_HandleTypeDef *spi, uint32_t
return HAL_OK;
}
STATIC void spi_transfer(mp_obj_base_t *self_in, size_t src_len, const uint8_t *src_buf, size_t dest_len, uint8_t *dest_buf, uint32_t timeout) {
// Note: there seems to be a problem sending 1 byte using DMA the first
// time directly after the SPI/DMA is initialised. The cause of this is
// unknown but we sidestep the issue by using polling for 1 byte transfer.
pyb_spi_obj_t *self = (pyb_spi_obj_t*)self_in;
HAL_StatusTypeDef status;
if (dest_len == 0) {
// send only
if (src_len == 1 || query_irq() == IRQ_STATE_DISABLED) {
status = HAL_SPI_Transmit(self->spi, (uint8_t*)src_buf, src_len, timeout);
} else {
DMA_HandleTypeDef tx_dma;
dma_init(&tx_dma, self->tx_dma_descr, self->spi);
self->spi->hdmatx = &tx_dma;
self->spi->hdmarx = NULL;
status = HAL_SPI_Transmit_DMA(self->spi, (uint8_t*)src_buf, src_len);
if (status == HAL_OK) {
status = spi_wait_dma_finished(self->spi, timeout);
}
dma_deinit(self->tx_dma_descr);
}
} else if (src_len == 0) {
// receive only
if (dest_len == 1 || query_irq() == IRQ_STATE_DISABLED) {
status = HAL_SPI_Receive(self->spi, dest_buf, dest_len, timeout);
} else {
DMA_HandleTypeDef tx_dma, rx_dma;
if (self->spi->Init.Mode == SPI_MODE_MASTER) {
// in master mode the HAL actually does a TransmitReceive call
dma_init(&tx_dma, self->tx_dma_descr, self->spi);
self->spi->hdmatx = &tx_dma;
} else {
self->spi->hdmatx = NULL;
}
dma_init(&rx_dma, self->rx_dma_descr, self->spi);
self->spi->hdmarx = &rx_dma;
status = HAL_SPI_Receive_DMA(self->spi, dest_buf, dest_len);
if (status == HAL_OK) {
status = spi_wait_dma_finished(self->spi, timeout);
}
if (self->spi->hdmatx != NULL) {
dma_deinit(self->tx_dma_descr);
}
dma_deinit(self->rx_dma_descr);
}
} else {
// send and receive
// requires src_len==dest_len
if (src_len == 1 || query_irq() == IRQ_STATE_DISABLED) {
status = HAL_SPI_TransmitReceive(self->spi, (uint8_t*)src_buf, dest_buf, src_len, timeout);
} else {
DMA_HandleTypeDef tx_dma, rx_dma;
dma_init(&tx_dma, self->tx_dma_descr, self->spi);
self->spi->hdmatx = &tx_dma;
dma_init(&rx_dma, self->rx_dma_descr, self->spi);
self->spi->hdmarx = &rx_dma;
status = HAL_SPI_TransmitReceive_DMA(self->spi, (uint8_t*)src_buf, dest_buf, src_len);
if (status == HAL_OK) {
status = spi_wait_dma_finished(self->spi, timeout);
}
dma_deinit(self->tx_dma_descr);
dma_deinit(self->rx_dma_descr);
}
}
if (status != HAL_OK) {
mp_hal_raise(status);
}
}
STATIC void spi_transfer_machine(mp_obj_base_t *self_in, size_t src_len, const uint8_t *src_buf, size_t dest_len, uint8_t *dest_buf) {
if (src_len == 1 && dest_len > 1) {
// this catches read and readinto
// copy the single output byte to the dest buffer and use that as source
memset(dest_buf, src_buf[0], dest_len);
src_len = dest_len;
src_buf = dest_buf;
}
spi_transfer(self_in, src_len, src_buf, dest_len, dest_buf, 100);
}
/******************************************************************************/
/* Micro Python bindings */
@ -556,27 +641,7 @@ STATIC mp_obj_t pyb_spi_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
pyb_buf_get_for_send(args[0].u_obj, &bufinfo, data);
// send the data
// Note: there seems to be a problem sending 1 byte using DMA the first
// time directly after the SPI/DMA is initialised. The cause of this is
// unknown but we sidestep the issue by using polling for 1 byte transfer.
HAL_StatusTypeDef status;
if (bufinfo.len == 1 || query_irq() == IRQ_STATE_DISABLED) {
status = HAL_SPI_Transmit(self->spi, bufinfo.buf, bufinfo.len, args[1].u_int);
} else {
DMA_HandleTypeDef tx_dma;
dma_init(&tx_dma, self->tx_dma_descr, self->spi);
self->spi->hdmatx = &tx_dma;
self->spi->hdmarx = NULL;
status = HAL_SPI_Transmit_DMA(self->spi, bufinfo.buf, bufinfo.len);
if (status == HAL_OK) {
status = spi_wait_dma_finished(self->spi, args[1].u_int);
}
dma_deinit(self->tx_dma_descr);
}
if (status != HAL_OK) {
mp_hal_raise(status);
}
spi_transfer((mp_obj_base_t*)self, bufinfo.len, bufinfo.buf, 0, NULL, args[1].u_int);
return mp_const_none;
}
@ -610,34 +675,7 @@ STATIC mp_obj_t pyb_spi_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
mp_obj_t o_ret = pyb_buf_get_for_recv(args[0].u_obj, &vstr);
// receive the data
HAL_StatusTypeDef status;
if (vstr.len == 1 || query_irq() == IRQ_STATE_DISABLED) {
status = HAL_SPI_Receive(self->spi, (uint8_t*)vstr.buf, vstr.len, args[1].u_int);
} else {
DMA_HandleTypeDef tx_dma, rx_dma;
if (self->spi->Init.Mode == SPI_MODE_MASTER) {
// in master mode the HAL actually does a TransmitReceive call
dma_init(&tx_dma, self->tx_dma_descr, self->spi);
self->spi->hdmatx = &tx_dma;
} else {
self->spi->hdmatx = NULL;
}
dma_init(&rx_dma, self->rx_dma_descr, self->spi);
self->spi->hdmarx = &rx_dma;
status = HAL_SPI_Receive_DMA(self->spi, (uint8_t*)vstr.buf, vstr.len);
if (status == HAL_OK) {
status = spi_wait_dma_finished(self->spi, args[1].u_int);
}
if (self->spi->hdmatx != NULL) {
dma_deinit(self->tx_dma_descr);
}
dma_deinit(self->rx_dma_descr);
}
if (status != HAL_OK) {
mp_hal_raise(status);
}
spi_transfer((mp_obj_base_t*)self, 0, NULL, vstr.len, (uint8_t*)vstr.buf, args[1].u_int);
// return the received data
if (o_ret != MP_OBJ_NULL) {
@ -706,27 +744,8 @@ STATIC mp_obj_t pyb_spi_send_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp
}
}
// send and receive the data
HAL_StatusTypeDef status;
if (bufinfo_send.len == 1 || query_irq() == IRQ_STATE_DISABLED) {
status = HAL_SPI_TransmitReceive(self->spi, bufinfo_send.buf, bufinfo_recv.buf, bufinfo_send.len, args[2].u_int);
} else {
DMA_HandleTypeDef tx_dma, rx_dma;
dma_init(&tx_dma, self->tx_dma_descr, self->spi);
self->spi->hdmatx = &tx_dma;
dma_init(&rx_dma, self->rx_dma_descr, self->spi);
self->spi->hdmarx = &rx_dma;
status = HAL_SPI_TransmitReceive_DMA(self->spi, bufinfo_send.buf, bufinfo_recv.buf, bufinfo_send.len);
if (status == HAL_OK) {
status = spi_wait_dma_finished(self->spi, args[2].u_int);
}
dma_deinit(self->tx_dma_descr);
dma_deinit(self->rx_dma_descr);
}
if (status != HAL_OK) {
mp_hal_raise(status);
}
// do the transfer
spi_transfer((mp_obj_base_t*)self, bufinfo_send.len, bufinfo_send.buf, bufinfo_recv.len, bufinfo_recv.buf, args[2].u_int);
// return the received data
if (o_ret != MP_OBJ_NULL) {
@ -741,6 +760,13 @@ STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_spi_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_spi_deinit_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_machine_spi_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_machine_spi_readinto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_machine_spi_write_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write_readinto), (mp_obj_t)&mp_machine_spi_write_readinto_obj },
// legacy methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_spi_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_spi_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send_recv), (mp_obj_t)&pyb_spi_send_recv_obj },
@ -766,10 +792,15 @@ STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table);
STATIC const mp_machine_spi_p_t pyb_spi_p = {
.transfer = spi_transfer_machine,
};
const mp_obj_type_t pyb_spi_type = {
{ &mp_type_type },
.name = MP_QSTR_SPI,
.print = pyb_spi_print,
.make_new = pyb_spi_make_new,
.protocol = &pyb_spi_p,
.locals_dict = (mp_obj_t)&pyb_spi_locals_dict,
};

View File

@ -0,0 +1,4 @@
# cmdline: -O
# test optimisation output
print(__debug__)
assert 0

View File

@ -0,0 +1 @@
False

View File

@ -0,0 +1,20 @@
try:
import ubinascii as binascii
except ImportError:
import binascii
try:
binascii.crc32
except AttributeError:
print("SKIP")
import sys
sys.exit()
print(hex(binascii.crc32(b'The quick brown fox jumps over the lazy dog')))
print(hex(binascii.crc32(b'\x00' * 32)))
print(hex(binascii.crc32(b'\xff' * 32)))
print(hex(binascii.crc32(bytes(range(32)))))
print(hex(binascii.crc32(b' over the lazy dog', binascii.crc32(b'The quick brown fox jumps'))))
print(hex(binascii.crc32(b'\x00' * 16, binascii.crc32(b'\x00' * 16))))
print(hex(binascii.crc32(b'\xff' * 16, binascii.crc32(b'\xff' * 16))))
print(hex(binascii.crc32(bytes(range(16, 32)), binascii.crc32(bytes(range(16))))))

View File

@ -0,0 +1,19 @@
try:
import zlib
except ImportError:
import uzlib as zlib
import uio as io
# Raw DEFLATE bitstream
buf = io.BytesIO(b'\xcbH\xcd\xc9\xc9\x07\x00')
inp = zlib.DecompIO(buf)
print(buf.seek(0, 1))
print(inp.read(1))
print(buf.seek(0, 1))
print(inp.read(2))
print(inp.read())
print(buf.seek(0, 1))
print(inp.read(1))
print(inp.read())
print(buf.seek(0, 1))

View File

@ -0,0 +1,9 @@
0
b'h'
2
b'el'
b'lo'
7
b''
b''
7

View File

@ -1,5 +1,6 @@
import sys
import uos
import uerrno
try:
uos.VfsFat
except AttributeError:
@ -84,3 +85,15 @@ assert vfs.listdir() == ["sub_file.txt"]
vfs.chdir("..")
print("getcwd:", vfs.getcwd())
vfs.umount()
try:
vfs.listdir()
except OSError as e:
assert e.args[0] == uerrno.ENODEV
else:
raise AssertionError("expected OSError not thrown")
vfs = uos.VfsFat(bdev, "/ramdisk")
assert vfs.listdir() == ['foo_dir', 'moved-to-root.txt']

View File

@ -200,7 +200,9 @@ def run_tests(pyb, tests, args):
# Some tests shouldn't be run under Travis CI
if os.getenv('TRAVIS') == 'true':
skip_tests.add('basics/memoryerror.py')
skip_tests.add('thread/thread_gc1.py') # has reliability issues
skip_tests.add('thread/thread_lock4.py') # has reliability issues
skip_tests.add('thread/stress_heap.py') # has reliability issues
if not has_complex:
skip_tests.add('float/complex1.py')

View File

@ -5,4 +5,11 @@ except NameError:
import sys
sys.exit()
extra_coverage()
data = extra_coverage()
# test hashing of str/bytes that have an invalid hash
print(data)
print(hash(data[0]))
print(hash(data[1]))
print(hash(bytes(data[0], 'utf8')))
print(hash(str(data[1], 'utf8')))

View File

@ -7,7 +7,6 @@ ab abc
false true
(null)
t
-2147483648
2147483648
80000000
@ -36,3 +35,8 @@ ementation
12345678
0
0
('0123456789', b'0123456789')
7300
7300
7300
7300

View File

@ -283,15 +283,15 @@ class RawCode:
# generate constant objects
for i, obj in enumerate(self.objs):
obj_name = 'const_obj_%s_%u' % (self.escaped_name, i)
if is_str_type(obj):
obj = bytes_cons(obj, 'utf8')
print('STATIC const mp_obj_str_t %s = '
'{{&mp_type_str}, 0, %u, (const byte*)"%s"};'
% (obj_name, len(obj), ''.join(('\\x%02x' % b) for b in obj)))
elif is_bytes_type(obj):
print('STATIC const mp_obj_str_t %s = '
'{{&mp_type_bytes}, 0, %u, (const byte*)"%s"};'
% (obj_name, len(obj), ''.join(('\\x%02x' % b) for b in obj)))
if is_str_type(obj) or is_bytes_type(obj):
if is_str_type(obj):
obj = bytes_cons(obj, 'utf8')
obj_type = 'mp_type_str'
else:
obj_type = 'mp_type_bytes'
print('STATIC const mp_obj_str_t %s = {{&%s}, %u, %u, (const byte*)"%s"};'
% (obj_name, obj_type, qstrutil.compute_hash(obj, config.MICROPY_QSTR_BYTES_IN_HASH),
len(obj), ''.join(('\\x%02x' % b) for b in obj)))
elif is_int_type(obj):
if config.MICROPY_LONGINT_IMPL == config.MICROPY_LONGINT_IMPL_NONE:
# TODO check if we can actually fit this long-int into a small-int
@ -320,6 +320,9 @@ class RawCode:
print('STATIC const mp_obj_float_t %s = {{&mp_type_float}, %.16g};'
% (obj_name, obj))
print('#endif')
elif type(obj) is complex:
print('STATIC const mp_obj_complex_t %s = {{&mp_type_complex}, %.16g, %.16g};'
% (obj_name, obj.real, obj.imag))
else:
# TODO
raise FreezeError(self, 'freezing of object %r is not implemented' % (obj,))
@ -444,10 +447,7 @@ def dump_mpy(raw_codes):
for rc in raw_codes:
rc.dump()
def freeze_mpy(qcfgs, base_qstrs, raw_codes):
cfg_bytes_len = int(qcfgs['BYTES_IN_LEN'])
cfg_bytes_hash = int(qcfgs['BYTES_IN_HASH'])
def freeze_mpy(base_qstrs, raw_codes):
# add to qstrs
new = {}
for q in global_qstrs:
@ -488,6 +488,15 @@ def freeze_mpy(qcfgs, base_qstrs, raw_codes):
print('#endif')
print()
print('#if MICROPY_PY_BUILTINS_COMPLEX')
print('typedef struct _mp_obj_complex_t {')
print(' mp_obj_base_t base;')
print(' mp_float_t real;')
print(' mp_float_t imag;')
print('} mp_obj_complex_t;')
print('#endif')
print()
print('enum {')
for i in range(len(new)):
if i == 0:
@ -505,7 +514,8 @@ def freeze_mpy(qcfgs, base_qstrs, raw_codes):
print(' %u, // used entries' % len(new))
print(' {')
for _, _, qstr in new:
print(' %s,' % qstrutil.make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr))
print(' %s,'
% qstrutil.make_bytes(config.MICROPY_QSTR_BYTES_IN_LEN, config.MICROPY_QSTR_BYTES_IN_HASH, qstr))
print(' },')
print('};')
@ -549,10 +559,15 @@ def main():
}[args.mlongint_impl]
config.MPZ_DIG_SIZE = args.mmpz_dig_size
# set config values for qstrs, and get the existing base set of qstrs
if args.qstr_header:
qcfgs, base_qstrs = qstrutil.parse_input_headers([args.qstr_header])
config.MICROPY_QSTR_BYTES_IN_LEN = int(qcfgs['BYTES_IN_LEN'])
config.MICROPY_QSTR_BYTES_IN_HASH = int(qcfgs['BYTES_IN_HASH'])
else:
qcfgs, base_qstrs = {'BYTES_IN_LEN':1, 'BYTES_IN_HASH':1}, {}
config.MICROPY_QSTR_BYTES_IN_LEN = 1
config.MICROPY_QSTR_BYTES_IN_HASH = 1
base_qstrs = {}
raw_codes = [read_mpy(file) for file in args.files]
@ -560,7 +575,7 @@ def main():
dump_mpy(raw_codes)
elif args.freeze:
try:
freeze_mpy(qcfgs, base_qstrs, raw_codes)
freeze_mpy(base_qstrs, raw_codes)
except FreezeError as er:
print(er, file=sys.stderr)
sys.exit(1)

View File

@ -183,7 +183,7 @@ ifneq ($(FROZEN_MPY_DIR),)
# then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch).
MPY_CROSS = ../mpy-cross/mpy-cross
MPY_TOOL = ../tools/mpy-tool.py
FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR)/ -type f -name '*.py')
FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR) -type f -name '*.py')
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY

View File

@ -1,18 +1,22 @@
#include <stdio.h>
#include "py/obj.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "py/repl.h"
#include "py/mpz.h"
#if defined(MICROPY_UNIX_COVERAGE)
// str/bytes objects without a valid hash
STATIC const mp_obj_str_t str_no_hash_obj = {{&mp_type_str}, 0, 10, (const byte*)"0123456789"};
STATIC const mp_obj_str_t bytes_no_hash_obj = {{&mp_type_bytes}, 0, 10, (const byte*)"0123456789"};
// function to run extra tests for things that can't be checked by scripts
STATIC mp_obj_t extra_coverage(void) {
// mp_printf (used by ports that don't have a native printf)
{
mp_printf(&mp_plat_print, "# mp_printf\n");
mp_printf(&mp_plat_print, "%"); // nothing after percent
mp_printf(&mp_plat_print, "%d %+d % d\n", -123, 123, 123); // sign
mp_printf(&mp_plat_print, "%05d\n", -123); // negative number with zero padding
mp_printf(&mp_plat_print, "%ld\n", 123); // long
@ -21,7 +25,6 @@ STATIC mp_obj_t extra_coverage(void) {
mp_printf(&mp_plat_print, "%.*s\n", -1, "abc"); // negative string precision
mp_printf(&mp_plat_print, "%b %b\n", 0, 1); // bools
mp_printf(&mp_plat_print, "%s\n", NULL); // null string
mp_printf(&mp_plat_print, "%t\n"); // non-format char
mp_printf(&mp_plat_print, "%d\n", 0x80000000); // should print signed
mp_printf(&mp_plat_print, "%u\n", 0x80000000); // should print unsigned
mp_printf(&mp_plat_print, "%x\n", 0x80000000); // should print unsigned
@ -111,7 +114,9 @@ STATIC mp_obj_t extra_coverage(void) {
mp_printf(&mp_plat_print, "%d\n", mpz_as_uint_checked(&mpz, &value));
}
return mp_const_none;
// return a tuple of data for testing on the Python side
mp_obj_t items[] = {(mp_obj_t)&str_no_hash_obj, (mp_obj_t)&bytes_no_hash_obj};
return mp_obj_new_tuple(MP_ARRAY_SIZE(items), items);
}
MP_DEFINE_CONST_FUN_OBJ_0(extra_coverage_obj, extra_coverage);

View File

@ -117,6 +117,7 @@
#define MICROPY_PY_UHASHLIB_SHA1 (1)
#endif
#define MICROPY_PY_UBINASCII (1)
#define MICROPY_PY_UBINASCII_CRC32 (1)
#define MICROPY_PY_URANDOM (1)
#ifndef MICROPY_PY_USELECT
#define MICROPY_PY_USELECT (1)