Merge branch 'master' into nrf52
This commit is contained in:
commit
9397583f6c
@ -40,7 +40,8 @@ script:
|
||||
- make -C qemu-arm test
|
||||
- make -C stmhal
|
||||
- make -C stmhal -B MICROPY_PY_WIZNET5K=1 MICROPY_PY_CC3K=1
|
||||
- make -C stmhal BOARD=STM32F4DISC
|
||||
- make -C stmhal BOARD=STM32F7DISC
|
||||
- make -C stmhal BOARD=STM32L476DISC
|
||||
- make -C teensy
|
||||
- make -C cc3200 BTARGET=application BTYPE=release
|
||||
- make -C cc3200 BTARGET=bootloader BTYPE=release
|
||||
@ -55,9 +56,9 @@ script:
|
||||
- (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests)
|
||||
- (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests -d thread)
|
||||
- (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests --emit native)
|
||||
- (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests --via-mpy -d basics)
|
||||
- (cd tests && MICROPY_CPYTHON3=python3.4 MICROPY_MICROPYTHON=../unix/micropython_coverage ./run-tests --via-mpy -d basics float)
|
||||
|
||||
after_success:
|
||||
# run coveralls coverage analysis (try to, even if some builds/tests failed)
|
||||
- (cd unix && coveralls --root .. --build-root . --gcov $(which gcov) --gcov-options '\-o build-coverage/' --include py --include extmod)
|
||||
|
||||
after_failure:
|
||||
|
@ -8,6 +8,9 @@ endif
|
||||
# Make 'release' the default build type
|
||||
BTYPE ?= release
|
||||
|
||||
# Port for flashing firmware
|
||||
PORT ?= /dev/ttyUSB1
|
||||
|
||||
# If the build directory is not given, make it reflect the board name.
|
||||
BUILD ?= build/$(BOARD)/$(BTYPE)
|
||||
|
||||
@ -23,6 +26,9 @@ CFLAGS += -Iboards/$(BOARD)
|
||||
|
||||
LDFLAGS = -Wl,-nostdlib -Wl,--gc-sections -Wl,-Map=$@.map
|
||||
|
||||
FLASH_SIZE_WIPY = 2M
|
||||
FLASH_SIZE_LAUNCHXL = 1M
|
||||
|
||||
ifeq ($(BTARGET), application)
|
||||
# qstr definitions (must come before including py.mk)
|
||||
QSTR_DEFS = qstrdefsport.h $(BUILD)/pins_qstr.h
|
||||
@ -39,3 +45,18 @@ endif
|
||||
|
||||
# always include MicroPython make rules
|
||||
include ../py/mkrules.mk
|
||||
|
||||
erase:
|
||||
cc3200tool -p $(PORT) format_flash --size $(FLASH_SIZE_$(BOARD))
|
||||
|
||||
deploy:
|
||||
cc3200tool -p $(PORT) \
|
||||
write_file bootmgr/build/$(BOARD)/$(BTYPE)/bootloader.bin /sys/mcuimg.bin \
|
||||
write_file build/$(BOARD)/$(BTYPE)/mcuimg.bin /sys/factimg.bin
|
||||
|
||||
# Files *.ucf and *ucf.signed.bin come from CC3200SDK-SERVICEPACK
|
||||
# package from http://www.ti.com/tool/cc3200sdk
|
||||
servicepack:
|
||||
cc3200tool -p $(PORT) \
|
||||
write_file --file-size=0x20000 --signature ota_1.0.1.6-2.7.0.0.ucf.signed.bin \
|
||||
ota_1.0.1.6-2.7.0.0.ucf /sys/servicepack.ucf
|
||||
|
135
cc3200/README.md
135
cc3200/README.md
@ -1,36 +1,66 @@
|
||||
# Build Instructions for the CC3200
|
||||
MicroPython port to CC3200 WiFi SoC
|
||||
===================================
|
||||
|
||||
Currently the CC3200 port of MicroPython builds under Linux and OSX **but not under Windows**.
|
||||
This is a MicroPython port to Texas Instruments CC3200 WiFi SoC (ARM Cortex-M4
|
||||
architecture). This port supports 2 boards: WiPy and TI CC3200-LAUNCHXL.
|
||||
|
||||
The tool chain required for the build can be found at <https://launchpad.net/gcc-arm-embedded>.
|
||||
## Build Instructions for the CC3200
|
||||
|
||||
In order to download the image to the CC3200 you will need the CCS_Uniflash tool from TI, which at this
|
||||
moment is only available for Windows, so, you need Linux/OSX to build and Windows to flash the image.
|
||||
Currently the CC3200 port of MicroPython builds under Linux and OSX,
|
||||
but not under Windows.
|
||||
|
||||
## To build an image suitable for debugging:
|
||||
The toolchain required for the build can be found at
|
||||
<https://launchpad.net/gcc-arm-embedded>.
|
||||
|
||||
In order to flash the image to the CC3200 you will need the
|
||||
[cc3200tool](https://github.com/ALLTERCO/cc3200tool). An alternative is
|
||||
to use CCS_Uniflash tool from TI, which works only under Windows, and all
|
||||
support is provided by TI itself.
|
||||
|
||||
Building the bootloader:
|
||||
|
||||
In order to debug the port specific code, optimizations need to be disabled on the
|
||||
port file (check the Makefile for specific details). You can use CCS from TI.
|
||||
Use the CC3200.ccxml file supplied with this distribution for the debuuger configuration.
|
||||
```bash
|
||||
make BTARGET=application BTYPE=debug BOARD=LAUNCHXL
|
||||
```
|
||||
## To build an image suitable to be flashed to the device:
|
||||
```bash
|
||||
make BTARGET=application BTYPE=release BOARD=LAUNCHXL
|
||||
```
|
||||
## Building the bootloader
|
||||
```bash
|
||||
make BTARGET=bootloader BTYPE=release BOARD=LAUNCHXL
|
||||
```
|
||||
|
||||
## Regarding old revisions of the CC3200-LAUNCHXL
|
||||
First silicon (pre-release) revisions of the CC3200 had issues with the ram blocks, and MicroPython cannot run
|
||||
there. Make sure to use a **v4.1 (or higer) LAUNCHXL board** when trying this port, otherwise it won't work.
|
||||
Building the "release" image:
|
||||
|
||||
```
|
||||
make BTARGET=application BTYPE=release BOARD=LAUNCHXL
|
||||
```
|
||||
|
||||
To build an image suitable for debugging:
|
||||
|
||||
In order to debug the port specific code, optimizations need to be disabled on the
|
||||
port file (check the Makefile for specific details). You can use CCS from TI.
|
||||
Use the CC3200.ccxml file supplied with this distribution for the debuuger configuration.
|
||||
|
||||
```
|
||||
make BTARGET=application BTYPE=debug BOARD=LAUNCHXL
|
||||
```
|
||||
|
||||
## Flashing the CC3200-LAUNCHXL
|
||||
|
||||
Note that WiPy comes factory programmed with a default version of MicroPython,
|
||||
it cannot be programmed via serial, and can be upgraded only with OTA (see
|
||||
below).
|
||||
|
||||
## Flashing the CC3200
|
||||
- Make sure that you have built both the *bootloader* and the *application* in **release** mode.
|
||||
- Make sure the SOP2 jumper is in position.
|
||||
- Make sure you Linux system recognized the board and created `ttyUSB*`
|
||||
devices (see below for configuration of `ftdi_sio` driver).
|
||||
- Run "make erase" and immediately press Reset button on the device.
|
||||
- Wait few seconds.
|
||||
- Run "make deploy" and immediately press Reset button on the device.
|
||||
- You are recommended to install the latest vendor WiFi firmware
|
||||
servicepack from http://www.ti.com/tool/cc3200sdk. Download
|
||||
CC3200SDK-SERVICEPACK package, install it, and locate `ota_*.ucf`
|
||||
and `ota_*.ucf.signed.bin` files. Copy them to the port's directory
|
||||
and run "make servicepack", with immediate press of Reset button.
|
||||
- Remove the SOP2 jumper and reset the board.
|
||||
|
||||
Flashing process using TI Uniflash:
|
||||
|
||||
- Open CCS_Uniflash and connect to the board (by default on port 22).
|
||||
- Format the serial flash (select 1MB size in case of the CC3200-LAUNCHXL, 2MB in case of the WiPy, leave the rest unchecked).
|
||||
- Mark the following files for erasing: `/cert/ca.pem`, `/cert/client.pem`, `/cert/private.key` and `/tmp/pac.bin`.
|
||||
@ -40,26 +70,30 @@ there. Make sure to use a **v4.1 (or higer) LAUNCHXL board** when trying this po
|
||||
- Flash the latest service pack (servicepack_1.0.0.10.0.bin) using the "Service Pack Update" button.
|
||||
- Close CCS_Uniflash, remove the SOP2 jumper and reset the board.
|
||||
|
||||
## Updating the board to with new software version
|
||||
- Make sure the board is running and connected to the same network as the computer.
|
||||
|
||||
```bash
|
||||
make BTARGET=application BTYPE=release BOARD=LAUNCHXL WIPY_IP=192.168.1.1 WIPY_USER=micro WIPY_PWD=python deploy
|
||||
```
|
||||
|
||||
If `WIPY_IP`, `WIPY_USER` or `WIPY_PWD` are omitted the default values (the ones shown above) will be used.
|
||||
|
||||
## Playing with MicroPython and the CC3200:
|
||||
|
||||
Once the software is running, you have two options to access the MicroPython REPL:
|
||||
|
||||
- Through telnet.
|
||||
- Through telnet.
|
||||
* Connect to the network created by the board (as boots up in AP mode), **ssid = "wipy-wlan", key = "www.wipy.io"**.
|
||||
* You can also reinitialize the WLAN in station mode and connect to another AP, or in AP mode but with a
|
||||
different ssid and/or key.
|
||||
* Use your favourite telnet client with the following settings: **host = 192.168.1.1, port = 23.**
|
||||
* Log in with **user = "micro" and password = "python"**
|
||||
|
||||
- Through UART (serial).
|
||||
* This is enabled by default in the standard configuration, for UART0 (speed 115200).
|
||||
* For CC3200-LAUNCHXL, you will need to configure Linux `ftdi_sio` driver as described
|
||||
in the [blog post](http://www.achanceofbrainshowers.com/blog/tech/2014/8/19/cc3200-development-under-linux/).
|
||||
After that, connecting a board will create two `/dev/ttyUSB*` devices, a serial
|
||||
console is available on the 2nd one (usually `/dev/ttyUSB1`).
|
||||
* WiPy doesn't have onboard USB-UART converter, so you will need an external one,
|
||||
connected to GPIO01 (Tx) and GPIO02 (Rx).
|
||||
* Usage of UART port for REPL is controlled by MICROPY_STDIO_UART setting (and
|
||||
is done at the high level, using a suitable call to `os.dupterm()` function
|
||||
in boot.py, so you can override it at runtime regardless of MICROPY_STDIO_UART
|
||||
setting).
|
||||
|
||||
The board has a small file system of 192K (WiPy) or 64K (Launchpad) located in the serial flash connected to the CC3200.
|
||||
SD cards are also supported, you can connect any SD card and configure the pinout using the SD class API.
|
||||
|
||||
@ -68,15 +102,19 @@ SD cards are also supported, you can connect any SD card and configure the pinou
|
||||
To upload your MicroPython scripts to the FTP server, open your FTP client of choice and connect to:
|
||||
**ftp://192.168.1.1, user = "micro", password = "python"**
|
||||
|
||||
I have tested the FTP server with **FileZilla, FireFTP, FireFox, IE and Chrome,** other clients should work as well, but I am
|
||||
not 100% sure of it.
|
||||
Tested FTP clients are: FileZilla, FireFTP, FireFox, IE and Chrome. Other
|
||||
clients should work as well, but you may need to configure them to use a
|
||||
single connection (this should be the default for any compliant FTP client).
|
||||
|
||||
## Upgrading the firmware Over The Air:
|
||||
## Upgrading the firmware Over The Air (OTA)
|
||||
|
||||
OTA software updates can be performed through the FTP server. After building a new **mcuimg.bin** in release mode, upload it to:
|
||||
`/flash/sys/mcuimg.bin` it will take around 6s (The TI simplelink file system is quite slow because every file is mirrored for
|
||||
safety). You won't see the file being stored inside `/flash/sys/` because it's actually saved bypassing FatFS, but rest assured that
|
||||
the file was successfully transferred, and it has been signed with a MD5 checksum to verify its integrity.
|
||||
OTA software updates can be performed through the builtin FTP server. After
|
||||
building a new `mcuimg.bin` in release mode, upload it to:
|
||||
`/flash/sys/mcuimg.bin`. It will take around 6s (The TI SimpleLink file
|
||||
system is quite slow because every file is mirrored for safety). You won't
|
||||
see the file being stored inside `/flash/sys/` because it's actually saved
|
||||
bypassing FatFS, but rest assured that the file was successfully transferred,
|
||||
and it has been signed with a MD5 checksum to verify its integrity.
|
||||
Now, reset the MCU by pressing the switch on the board, or by typing:
|
||||
|
||||
```python
|
||||
@ -84,10 +122,27 @@ import machine
|
||||
machine.reset()
|
||||
```
|
||||
|
||||
### Note regarding FileZilla:
|
||||
There's a script which automates this process from the host side:
|
||||
|
||||
- Make sure the board is running and connected to the same network as the computer.
|
||||
|
||||
```bash
|
||||
make BTARGET=application BTYPE=release BOARD=LAUNCHXL WIPY_IP=192.168.1.1 WIPY_USER=micro WIPY_PWD=python deploy-ota
|
||||
```
|
||||
|
||||
If `WIPY_IP`, `WIPY_USER` or `WIPY_PWD` are omitted the default values (the ones shown above) will be used.
|
||||
|
||||
|
||||
## Notes and known issues
|
||||
|
||||
## Regarding old revisions of the CC3200-LAUNCHXL
|
||||
|
||||
First silicon (pre-release) revisions of the CC3200 had issues with the ram blocks, and MicroPython cannot run
|
||||
there. Make sure to use a **v4.1 (or higer) LAUNCHXL board** when trying this port, otherwise it won't work.
|
||||
|
||||
### Note regarding FileZilla
|
||||
|
||||
Do not use the quick connect button, instead, open the site manager and create a new configuration. In the "General" tab make
|
||||
sure that encryption is set to: "Only use plain FTP (insecure)". In the Transfer Settings tab limit the max number of connections
|
||||
to one, otherwise FileZilla will try to open a second command connection when retrieving and saving files, and for simplicity and
|
||||
to reduce code size, only one command and one data connections are possible.
|
||||
|
||||
|
@ -153,7 +153,6 @@ APP_LIB_SRC_C = $(addprefix lib/,\
|
||||
netutils/netutils.c \
|
||||
timeutils/timeutils.c \
|
||||
utils/pyexec.c \
|
||||
utils/pyhelp.c \
|
||||
)
|
||||
|
||||
APP_STM_SRC_C = $(addprefix stmhal/,\
|
||||
@ -162,8 +161,6 @@ APP_STM_SRC_C = $(addprefix stmhal/,\
|
||||
import.c \
|
||||
input.c \
|
||||
irq.c \
|
||||
lexerfatfs.c \
|
||||
moduselect.c \
|
||||
pybstdio.c \
|
||||
)
|
||||
|
||||
@ -208,9 +205,9 @@ WIPY_PWD ?= 'python'
|
||||
|
||||
all: $(BUILD)/mcuimg.bin
|
||||
|
||||
.PHONY: deploy
|
||||
.PHONY: deploy-ota
|
||||
|
||||
deploy: $(BUILD)/mcuimg.bin
|
||||
deploy-ota: $(BUILD)/mcuimg.bin
|
||||
$(ECHO) "Writing $< to the board"
|
||||
$(Q)$(PYTHON) $(UPDATE_WIPY) --verify --ip $(WIPY_IP) --user $(WIPY_USER) --password $(WIPY_PWD) --file $<
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#define MICROPY_HW_ANTENNA_DIVERSITY (0)
|
||||
|
||||
#define MICROPY_STDIO_UART 0
|
||||
#define MICROPY_STDIO_UART 1
|
||||
#define MICROPY_STDIO_UART_BAUD 115200
|
||||
|
||||
#define MICROPY_SYS_LED_PRCM PRCM_GPIOA1
|
||||
|
@ -32,6 +32,9 @@
|
||||
|
||||
#define MICROPY_HW_ANTENNA_DIVERSITY (1)
|
||||
|
||||
#define MICROPY_STDIO_UART 1
|
||||
#define MICROPY_STDIO_UART_BAUD 115200
|
||||
|
||||
#define MICROPY_SYS_LED_PRCM PRCM_GPIOA3
|
||||
#define MICROPY_SAFE_BOOT_PRCM PRCM_GPIOA3
|
||||
#define MICROPY_SYS_LED_PORT GPIOA3_BASE
|
||||
|
@ -25,23 +25,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "py/builtin.h"
|
||||
|
||||
#include "lib/utils/pyhelp.h"
|
||||
|
||||
STATIC const char help_text[] = "Welcome to MicroPython!\n"
|
||||
const char *cc3200_help_text = "Welcome to MicroPython!\n"
|
||||
"For online help please visit http://micropython.org/help/.\n"
|
||||
"For further help on a specific object, type help(obj)\n";
|
||||
|
||||
STATIC mp_obj_t pyb_help(uint n_args, const mp_obj_t *args) {
|
||||
if (n_args == 0) {
|
||||
// print a general help message
|
||||
printf("%s", help_text);
|
||||
}
|
||||
else {
|
||||
// try to print something sensible about the given object
|
||||
pyhelp_print_obj(args[0]);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj, 0, 1, pyb_help);
|
||||
|
@ -176,7 +176,7 @@ STATIC mp_obj_t mp_irq_flags (mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_irq_flags_obj, mp_irq_flags);
|
||||
|
||||
STATIC mp_obj_t mp_irq_call (mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t mp_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 0, false);
|
||||
mp_irq_handler (self_in);
|
||||
return mp_const_none;
|
||||
|
@ -91,7 +91,7 @@ STATIC const mp_arg_t network_server_args[] = {
|
||||
{ MP_QSTR_login, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
STATIC mp_obj_t network_server_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t network_server_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
|
@ -121,7 +121,7 @@ STATIC mp_obj_t hash_read (mp_obj_t self_in) {
|
||||
|
||||
/// \classmethod \constructor([data[, block_size]])
|
||||
/// initial data must be given if block_size wants to be passed
|
||||
STATIC mp_obj_t hash_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t hash_make_new(mp_obj_t type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 2, false);
|
||||
mp_obj_hash_t *self = m_new0(mp_obj_hash_t, 1);
|
||||
self->base.type = type_in;
|
||||
|
@ -127,7 +127,7 @@ void modusocket_close_all_user_sockets (void) {
|
||||
// socket class
|
||||
|
||||
// constructor socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None)
|
||||
STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t socket_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, 0, 4, false);
|
||||
|
||||
// create socket object
|
||||
@ -434,7 +434,6 @@ STATIC const mp_map_elem_t socket_locals_dict_table[] = {
|
||||
|
||||
// stream methods
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
|
||||
@ -446,7 +445,7 @@ STATIC mp_uint_t socket_read(mp_obj_t self_in, void *buf, mp_uint_t size, int *e
|
||||
mod_network_socket_obj_t *self = self_in;
|
||||
mp_int_t ret = wlan_socket_recv(self, buf, size, errcode);
|
||||
if (ret < 0) {
|
||||
// we need to ignore the socket closed error here because a readall() or read() without params
|
||||
// we need to ignore the socket closed error here because a read() without params
|
||||
// only returns when the socket is closed by the other end
|
||||
if (*errcode != SL_ESECCLOSED) {
|
||||
ret = MP_STREAM_ERROR;
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "modnetwork.h"
|
||||
#include "modusocket.h"
|
||||
#include "modwlan.h"
|
||||
#include "pybioctl.h"
|
||||
#include "pybrtc.h"
|
||||
#include "debug.h"
|
||||
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
|
||||
@ -830,7 +829,7 @@ STATIC const mp_arg_t wlan_init_args[] = {
|
||||
{ MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_antenna, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ANTENNA_TYPE_INTERNAL} },
|
||||
};
|
||||
STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
@ -1250,6 +1249,21 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_irq_obj, 1, wlan_irq);
|
||||
//}
|
||||
//STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wlan_urn_obj, 1, 2, wlan_urn);
|
||||
|
||||
STATIC mp_obj_t wlan_print_ver(void) {
|
||||
SlVersionFull ver;
|
||||
byte config_opt = SL_DEVICE_GENERAL_VERSION;
|
||||
byte config_len = sizeof(ver);
|
||||
sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION, &config_opt, &config_len, (byte*)&ver);
|
||||
printf("NWP: %d.%d.%d.%d\n", ver.NwpVersion[0], ver.NwpVersion[1], ver.NwpVersion[2], ver.NwpVersion[3]);
|
||||
printf("MAC: %d.%d.%d.%d\n", ver.ChipFwAndPhyVersion.FwVersion[0], ver.ChipFwAndPhyVersion.FwVersion[1],
|
||||
ver.ChipFwAndPhyVersion.FwVersion[2], ver.ChipFwAndPhyVersion.FwVersion[3]);
|
||||
printf("PHY: %d.%d.%d.%d\n", ver.ChipFwAndPhyVersion.PhyVersion[0], ver.ChipFwAndPhyVersion.PhyVersion[1],
|
||||
ver.ChipFwAndPhyVersion.PhyVersion[2], ver.ChipFwAndPhyVersion.PhyVersion[3]);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(wlan_print_ver_fun_obj, wlan_print_ver);
|
||||
STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(wlan_print_ver_obj, MP_ROM_PTR(&wlan_print_ver_fun_obj));
|
||||
|
||||
STATIC const mp_map_elem_t wlan_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&wlan_init_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&wlan_scan_obj },
|
||||
@ -1266,6 +1280,7 @@ STATIC const mp_map_elem_t wlan_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&wlan_irq_obj },
|
||||
// { MP_OBJ_NEW_QSTR(MP_QSTR_connections), (mp_obj_t)&wlan_connections_obj },
|
||||
// { MP_OBJ_NEW_QSTR(MP_QSTR_urn), (mp_obj_t)&wlan_urn_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_print_ver), (mp_obj_t)&wlan_print_ver_obj },
|
||||
|
||||
// class constants
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_STA), MP_OBJ_NEW_SMALL_INT(ROLE_STA) },
|
||||
@ -1461,7 +1476,7 @@ int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int
|
||||
|
||||
int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno) {
|
||||
mp_int_t ret;
|
||||
if (request == MP_IOCTL_POLL) {
|
||||
if (request == MP_STREAM_POLL) {
|
||||
mp_uint_t flags = arg;
|
||||
ret = 0;
|
||||
int32_t sd = s->sock_base.sd;
|
||||
@ -1473,13 +1488,13 @@ int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t
|
||||
FD_ZERO(&xfds);
|
||||
|
||||
// set fds if needed
|
||||
if (flags & MP_IOCTL_POLL_RD) {
|
||||
if (flags & MP_STREAM_POLL_RD) {
|
||||
FD_SET(sd, &rfds);
|
||||
}
|
||||
if (flags & MP_IOCTL_POLL_WR) {
|
||||
if (flags & MP_STREAM_POLL_WR) {
|
||||
FD_SET(sd, &wfds);
|
||||
}
|
||||
if (flags & MP_IOCTL_POLL_HUP) {
|
||||
if (flags & MP_STREAM_POLL_HUP) {
|
||||
FD_SET(sd, &xfds);
|
||||
}
|
||||
|
||||
@ -1497,13 +1512,13 @@ int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t
|
||||
|
||||
// check return of select
|
||||
if (FD_ISSET(sd, &rfds)) {
|
||||
ret |= MP_IOCTL_POLL_RD;
|
||||
ret |= MP_STREAM_POLL_RD;
|
||||
}
|
||||
if (FD_ISSET(sd, &wfds)) {
|
||||
ret |= MP_IOCTL_POLL_WR;
|
||||
ret |= MP_STREAM_POLL_WR;
|
||||
}
|
||||
if (FD_ISSET(sd, &xfds)) {
|
||||
ret |= MP_IOCTL_POLL_HUP;
|
||||
ret |= MP_STREAM_POLL_HUP;
|
||||
}
|
||||
} else {
|
||||
*_errno = EINVAL;
|
||||
|
@ -140,7 +140,7 @@ STATIC const mp_arg_t pyb_adc_init_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 12} },
|
||||
};
|
||||
STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
@ -289,7 +289,7 @@ STATIC mp_obj_t adc_channel_value(mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_channel_value_obj, adc_channel_value);
|
||||
|
||||
STATIC mp_obj_t adc_channel_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t adc_channel_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 0, false);
|
||||
return adc_channel_value (self_in);
|
||||
}
|
||||
|
@ -332,7 +332,7 @@ STATIC const mp_arg_t pyb_i2c_init_args[] = {
|
||||
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} },
|
||||
{ MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
|
@ -647,7 +647,7 @@ STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t
|
||||
mp_printf(print, ", alt=%d)", alt);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pin_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t pin_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, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
|
||||
// Run an argument through the mapper and return the result.
|
||||
@ -747,7 +747,7 @@ STATIC mp_obj_t pin_drive(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_drive_obj, 1, 2, pin_drive);
|
||||
|
||||
STATIC mp_obj_t pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_t _args[2] = {self_in, *args};
|
||||
return pin_value (n_args + 1, _args);
|
||||
|
@ -285,7 +285,7 @@ STATIC const mp_arg_t pyb_rtc_init_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_datetime, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
|
@ -64,7 +64,7 @@ STATIC const mp_obj_t pyb_sd_def_pin[3] = {&pin_GP10, &pin_GP11, &pin_GP15};
|
||||
DECLARE PRIVATE FUNCTIONS
|
||||
******************************************************************************/
|
||||
STATIC void pyb_sd_hw_init (pybsd_obj_t *self);
|
||||
STATIC mp_obj_t pyb_sd_make_new (const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
|
||||
STATIC mp_obj_t pyb_sd_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
STATIC mp_obj_t pyb_sd_deinit (mp_obj_t self_in);
|
||||
|
||||
/******************************************************************************
|
||||
@ -123,7 +123,7 @@ STATIC const mp_arg_t pyb_sd_init_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_pins, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
STATIC mp_obj_t pyb_sd_make_new (const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t pyb_sd_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
|
@ -148,7 +148,7 @@ STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxda
|
||||
STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
pyb_spi_obj_t *self = self_in;
|
||||
if (self->baudrate > 0) {
|
||||
mp_printf(print, "SPI(0, SPI.MASTER, baudrate=%u, bits=%u, polarity=%u, phase=%u, firstbit=SPI.MSB)",
|
||||
mp_printf(print, "SPI(0, baudrate=%u, bits=%u, polarity=%u, phase=%u, firstbit=SPI.MSB)",
|
||||
self->baudrate, (self->wlen * 8), self->polarity, self->phase);
|
||||
} else {
|
||||
mp_print_str(print, "SPI(0)");
|
||||
@ -156,13 +156,8 @@ STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, const mp_arg_val_t *args) {
|
||||
// verify that mode is master
|
||||
if (args[0].u_int != SPI_MODE_MASTER) {
|
||||
goto invalid_args;
|
||||
}
|
||||
|
||||
uint bits;
|
||||
switch (args[2].u_int) {
|
||||
switch (args[1].u_int) {
|
||||
case 8:
|
||||
bits = SPI_WL_8;
|
||||
break;
|
||||
@ -177,27 +172,27 @@ STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, const mp_arg_val_t *arg
|
||||
break;
|
||||
}
|
||||
|
||||
uint polarity = args[3].u_int;
|
||||
uint phase = args[4].u_int;
|
||||
uint polarity = args[2].u_int;
|
||||
uint phase = args[3].u_int;
|
||||
if (polarity > 1 || phase > 1) {
|
||||
goto invalid_args;
|
||||
}
|
||||
|
||||
uint firstbit = args[5].u_int;
|
||||
uint firstbit = args[4].u_int;
|
||||
if (firstbit != PYBSPI_FIRST_BIT_MSB) {
|
||||
goto invalid_args;
|
||||
}
|
||||
|
||||
// build the configuration
|
||||
self->baudrate = args[1].u_int;
|
||||
self->wlen = args[2].u_int >> 3;
|
||||
self->baudrate = args[0].u_int;
|
||||
self->wlen = args[1].u_int >> 3;
|
||||
self->config = bits | SPI_CS_ACTIVELOW | SPI_SW_CTRL_CS | SPI_4PIN_MODE | SPI_TURBO_OFF;
|
||||
self->polarity = polarity;
|
||||
self->phase = phase;
|
||||
self->submode = (polarity << 1) | phase;
|
||||
|
||||
// assign the pins
|
||||
mp_obj_t pins_o = args[6].u_obj;
|
||||
mp_obj_t pins_o = args[5].u_obj;
|
||||
if (pins_o != mp_const_none) {
|
||||
mp_obj_t *pins;
|
||||
if (pins_o == MP_OBJ_NULL) {
|
||||
@ -223,7 +218,6 @@ invalid_args:
|
||||
|
||||
static const mp_arg_t pyb_spi_init_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_mode, MP_ARG_INT, {.u_int = SPI_MODE_MASTER} },
|
||||
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1000000} }, // 1MHz
|
||||
{ MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
|
||||
{ MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
@ -231,7 +225,7 @@ static const mp_arg_t pyb_spi_init_args[] = {
|
||||
{ MP_QSTR_firstbit, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYBSPI_FIRST_BIT_MSB} },
|
||||
{ MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
@ -379,7 +373,6 @@ STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_write_readinto), (mp_obj_t)&pyb_spi_write_readinto_obj },
|
||||
|
||||
// class constants
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(SPI_MODE_MASTER) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MSB), MP_OBJ_NEW_SMALL_INT(PYBSPI_FIRST_BIT_MSB) },
|
||||
};
|
||||
|
||||
|
@ -322,7 +322,7 @@ error:
|
||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
|
||||
|
@ -46,7 +46,6 @@
|
||||
#include "uart.h"
|
||||
#include "pybuart.h"
|
||||
#include "mpirq.h"
|
||||
#include "pybioctl.h"
|
||||
#include "pybsleep.h"
|
||||
#include "mpexception.h"
|
||||
#include "py/mpstate.h"
|
||||
@ -443,7 +442,7 @@ STATIC const mp_arg_t pyb_uart_init_args[] = {
|
||||
{ MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// parse args
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
@ -570,8 +569,6 @@ STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
|
||||
|
||||
/// \method read([nbytes])
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
|
||||
/// \method readall()
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
|
||||
/// \method readline()
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
|
||||
/// \method readinto(buf[, nbytes])
|
||||
@ -632,14 +629,14 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t a
|
||||
mp_uint_t ret;
|
||||
uart_check_init(self);
|
||||
|
||||
if (request == MP_IOCTL_POLL) {
|
||||
if (request == MP_STREAM_POLL) {
|
||||
mp_uint_t flags = arg;
|
||||
ret = 0;
|
||||
if ((flags & MP_IOCTL_POLL_RD) && uart_rx_any(self)) {
|
||||
ret |= MP_IOCTL_POLL_RD;
|
||||
if ((flags & MP_STREAM_POLL_RD) && uart_rx_any(self)) {
|
||||
ret |= MP_STREAM_POLL_RD;
|
||||
}
|
||||
if ((flags & MP_IOCTL_POLL_WR) && MAP_UARTSpaceAvail(self->reg)) {
|
||||
ret |= MP_IOCTL_POLL_WR;
|
||||
if ((flags & MP_STREAM_POLL_WR) && MAP_UARTSpaceAvail(self->reg)) {
|
||||
ret |= MP_STREAM_POLL_WR;
|
||||
}
|
||||
} else {
|
||||
*errcode = EINVAL;
|
||||
|
@ -92,7 +92,7 @@ STATIC const mp_arg_t pyb_wdt_init_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_timeout, MP_ARG_INT, {.u_int = 5000} }, // 5 s
|
||||
};
|
||||
STATIC mp_obj_t pyb_wdt_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *all_args) {
|
||||
STATIC mp_obj_t pyb_wdt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
// check the arguments
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
|
||||
|
@ -55,6 +55,7 @@
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
|
||||
#define MICROPY_OPT_COMPUTED_GOTO (0)
|
||||
#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0)
|
||||
#define MICROPY_READER_FATFS (1)
|
||||
#ifndef DEBUG // we need ram on the launchxl while debugging
|
||||
#define MICROPY_CPYTHON_COMPAT (1)
|
||||
#else
|
||||
@ -79,6 +80,8 @@
|
||||
#define MICROPY_PY_ASYNC_AWAIT (0)
|
||||
#define MICROPY_PY_BUILTINS_TIMEOUTERROR (1)
|
||||
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
|
||||
#define MICROPY_PY_BUILTINS_HELP (1)
|
||||
#define MICROPY_PY_BUILTINS_HELP_TEXT cc3200_help_text
|
||||
#ifndef DEBUG
|
||||
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
|
||||
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1)
|
||||
@ -112,13 +115,13 @@
|
||||
#define MICROPY_PY_URE (1)
|
||||
#define MICROPY_PY_UHEAPQ (0)
|
||||
#define MICROPY_PY_UHASHLIB (0)
|
||||
#define MICROPY_PY_USELECT (1)
|
||||
|
||||
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
|
||||
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0)
|
||||
|
||||
// extra built in names to add to the global namespace
|
||||
#define MICROPY_PORT_BUILTINS \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_help), (mp_obj_t)&mp_builtin_help_obj }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_input), (mp_obj_t)&mp_builtin_input_obj }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, \
|
||||
|
||||
@ -192,6 +195,7 @@ typedef long mp_off_t;
|
||||
|
||||
#define MICROPY_BEGIN_ATOMIC_SECTION() disable_irq()
|
||||
#define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state)
|
||||
#define MICROPY_EVENT_POLL_HOOK __WFI();
|
||||
|
||||
// assembly functions to handle critical sections, interrupt
|
||||
// disabling/enabling and sleep mode enter/exit
|
||||
|
@ -98,7 +98,12 @@ static FATFS *sflash_fatfs;
|
||||
|
||||
static const char fresh_main_py[] = "# main.py -- put your code here!\r\n";
|
||||
static const char fresh_boot_py[] = "# boot.py -- run on boot-up\r\n"
|
||||
"# can run arbitrary Python, but best to keep it minimal\r\n";
|
||||
"# can run arbitrary Python, but best to keep it minimal\r\n"
|
||||
#if MICROPY_STDIO_UART
|
||||
"import os, machine\r\n"
|
||||
"os.dupterm(machine.UART(0, " MP_STRINGIFY(MICROPY_STDIO_UART_BAUD) "))\r\n"
|
||||
#endif
|
||||
;
|
||||
|
||||
/******************************************************************************
|
||||
DECLARE PUBLIC FUNCTIONS
|
||||
|
@ -51,7 +51,7 @@ n_w = f.write(test_bytes)
|
||||
print(n_w == len(test_bytes))
|
||||
f.close()
|
||||
f = open('test.txt', 'r')
|
||||
r = bytes(f.readall(), 'ascii')
|
||||
r = bytes(f.read(), 'ascii')
|
||||
# check that we can write and read it correctly
|
||||
print(r == test_bytes)
|
||||
f.close()
|
||||
|
@ -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.5'
|
||||
release = '1.8.7'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -58,6 +58,17 @@ For your convenience, some of technical specifications are provided below:
|
||||
and always-available BootROM bootloader, ESP8266 is not brickable.
|
||||
|
||||
|
||||
Scarcity of runtime resources
|
||||
-----------------------------
|
||||
|
||||
ESP8266 has very modest resources (first of all, RAM memory). So, please
|
||||
avoid allocating too big container objects (lists, dictionaries) and
|
||||
buffers. There is also no full-fledged OS to keep track of resources
|
||||
and automatically clean them up, so that's the task of a user/user
|
||||
application: please be sure to close open files, sockets, etc. as soon
|
||||
as possible after use.
|
||||
|
||||
|
||||
Boot process
|
||||
------------
|
||||
|
||||
@ -71,13 +82,16 @@ and developers, who can diagnose themselves any issues arising from
|
||||
modifying the standard process).
|
||||
|
||||
Once the filesystem is mounted, ``boot.py`` is executed from it. The standard
|
||||
version of this file is created during first-time module set up and by
|
||||
default starts up a WebREPL daemon to handle incoming connections. This
|
||||
file is customizable by end users (for example, you may want to disable
|
||||
WebREPL for extra security, or add other services which should be run on
|
||||
version of this file is created during first-time module set up and has
|
||||
commands to start a WebREPL daemon (disabled by default, configurable
|
||||
with ``webrepl_setup`` module), etc. This
|
||||
file is customizable by end users (for example, you may want to set some
|
||||
parameters or add other services which should be run on
|
||||
a module start-up). But keep in mind that incorrect modifications to boot.py
|
||||
may still lead to boot loops or lock ups, requiring to reflash a module
|
||||
from scratch.
|
||||
from scratch. (In particular, it's recommended that you use either
|
||||
``webrepl_setup`` module or manual editing to configure WebREPL, but not
|
||||
both).
|
||||
|
||||
As a final step of boot procedure, ``main.py`` is executed from filesystem,
|
||||
if exists. This file is a hook to start up a user application each time
|
||||
|
@ -83,7 +83,7 @@ Use the :mod:`time <utime>` module::
|
||||
time.sleep_ms(500) # sleep for 500 milliseconds
|
||||
time.sleep_us(10) # sleep for 10 microseconds
|
||||
start = time.ticks_ms() # get millisecond counter
|
||||
delta = time.ticks_diff(start, time.ticks_ms()) # compute time difference
|
||||
delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference
|
||||
|
||||
Timers
|
||||
------
|
||||
@ -336,29 +336,27 @@ WebREPL (web browser interactive prompt)
|
||||
WebREPL (REPL over WebSockets, accessible via a web browser) is an
|
||||
experimental feature available in ESP8266 port. Download web client
|
||||
from https://github.com/micropython/webrepl (hosted version available
|
||||
at http://micropython.org/webrepl), and start the daemon on a device
|
||||
using::
|
||||
at http://micropython.org/webrepl), and configure it by executing::
|
||||
|
||||
import webrepl_setup
|
||||
|
||||
and following on-screen instructions. After reboot, it will be available
|
||||
for connection. If you disabled automatic start-up on boot, you may
|
||||
run configured daemon on demand using::
|
||||
|
||||
import webrepl
|
||||
webrepl.start()
|
||||
|
||||
(Release versions have it started on boot by default.)
|
||||
|
||||
On a first connection, you will be prompted to set password for future
|
||||
sessions to use.
|
||||
|
||||
The supported way to use WebREPL is by connecting to ESP8266 access point,
|
||||
but the daemon is also started on STA interface if it is active, so if your
|
||||
router is set up and works correctly, you may also use WebREPL while connected
|
||||
to your normal Internet access point (use the ESP8266 AP connection method
|
||||
if you face any issues).
|
||||
|
||||
WebREPL is an experimental feature and a work in progress, and has known
|
||||
issues.
|
||||
Besides terminal/command prompt access, WebREPL also has provision for file
|
||||
transfer (both upload and download). Web client has buttons for the
|
||||
corresponding functions, or you can use command-line client ``webrepl_cli.py``
|
||||
from the repository above.
|
||||
|
||||
There's also provision to transfer (both upload and download)
|
||||
files over WebREPL connection, but it has even more experimental status
|
||||
than the WebREPL terminal mode. It is still a practical way to
|
||||
get script files onto ESP8266, so give it a try using ``webrepl_cli.py``
|
||||
from the repository above. See the MicroPython forum for other
|
||||
community-supported alternatives to transfer files to ESP8266.
|
||||
See the MicroPython forum for other community-supported alternatives
|
||||
to transfer files to ESP8266.
|
||||
|
@ -64,7 +64,6 @@ device starts up.
|
||||
Accessing the filesystem via WebREPL
|
||||
------------------------------------
|
||||
|
||||
You can access the filesystem over WebREPL using the provided command-line
|
||||
tool. This tool is found at `<https://github.com/micropython/webrepl>`__
|
||||
and is called webrepl_cli.py. Please refer to that program for information
|
||||
on how to use it.
|
||||
You can access the filesystem over WebREPL using the web client in a browser
|
||||
or via the command-line tool. Please refer to Quick Reference and Tutorial
|
||||
sections for more information about WebREPL.
|
||||
|
@ -35,11 +35,30 @@ If your board has a USB connector on it then most likely it is powered through
|
||||
this when connected to your PC. Otherwise you will need to power it directly.
|
||||
Please refer to the documentation for your board for further details.
|
||||
|
||||
Getting the firmware
|
||||
--------------------
|
||||
|
||||
The first thing you need to do is download the most recent MicroPython firmware
|
||||
.bin file to load onto your ESP8266 device. You can download it from the
|
||||
`MicroPython downloads page <http://micropython.org/download#esp8266>`_.
|
||||
From here, you have 3 main choices
|
||||
|
||||
* Stable firmware builds for 1024kb modules and above.
|
||||
* Daily firmware builds for 1024kb modules and above.
|
||||
* Daily firmware builds for 512kb modules.
|
||||
|
||||
The best bet is nearly always to go for the Stable firmware builds.
|
||||
An exception to this though is if you have an ESP8266 module with only 512kb
|
||||
of onboard storage. You can easily tell by trying to load a Stable firmware
|
||||
build and if you get the error below, then you may have to use the Daily
|
||||
firmware builds for 512kb modules.
|
||||
WARNING: Unlikely to work as data goes beyond end of flash.
|
||||
|
||||
Deploying the firmware
|
||||
----------------------
|
||||
|
||||
The very first thing you need to do is put the MicroPython firmware (compiled
|
||||
code) on your ESP8266 device. There are two main steps to do this: first you
|
||||
Once you have the MicroPython firmware (compiled code), you need to load it onto
|
||||
your ESP8266 device. There are two main steps to do this: first you
|
||||
need to put your device in boot-loader mode, and second you need to copy across
|
||||
the firmware. The exact procedure for these steps is highly dependent on the
|
||||
particular board and you will need to refer to its documentation for details.
|
||||
@ -54,7 +73,7 @@ device before putting on new MicroPython firmware.
|
||||
|
||||
Currently we only support esptool.py to copy across the firmware. You can find
|
||||
this tool here: `<https://github.com/themadinventor/esptool/>`__, or install it
|
||||
using pip::
|
||||
using pip (at least version 1.2.1 is required)::
|
||||
|
||||
pip install esptool
|
||||
|
||||
@ -69,7 +88,7 @@ Using esptool.py you can erase the flash with the command::
|
||||
|
||||
And then deploy the new firmware using::
|
||||
|
||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=8m 0 esp8266-2016-05-03-v1.8.bin
|
||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-2016-05-03-v1.8.bin
|
||||
|
||||
You might need to change the "port" setting to something else relevant for your
|
||||
PC. You may also need to reduce the baudrate if you get errors when flashing
|
||||
@ -80,7 +99,7 @@ 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
|
||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect -fm dio 0 esp8266-2016-05-03-v1.8.bin
|
||||
|
||||
If the above commands run without error then MicroPython should be installed on
|
||||
your board!
|
||||
@ -138,6 +157,8 @@ after it, here are troubleshooting recommendations:
|
||||
* If lower baud rate didn't help, you may want to try older version of
|
||||
esptool.py, which had a different programming algorithm::
|
||||
pip install esptool==1.0.1
|
||||
This version doesn't support ``--flash_size=detect`` option, so you will
|
||||
need to specify FlashROM size explicitly (in megabits).
|
||||
|
||||
* The ``--flash_size`` option in the commands above is mandatory. Omitting
|
||||
it will lead to a corrupted firmware.
|
||||
|
@ -72,6 +72,7 @@ Let's define a function that can download and print a URL::
|
||||
print(str(data, 'utf8'), end='')
|
||||
else:
|
||||
break
|
||||
s.close()
|
||||
|
||||
Make sure that you import the socket module before running this function. Then
|
||||
you can try::
|
||||
|
@ -41,6 +41,18 @@ For your convenience, WebREPL client is hosted at
|
||||
locally from the the GitHub repository
|
||||
`<https://github.com/micropython/webrepl>`__ .
|
||||
|
||||
Before connecting to WebREPL, you should set a password and enable it via
|
||||
a normal serial connection. Initial versions of MicroPython for ESP8266
|
||||
came with WebREPL automatically enabled on the boot and with the
|
||||
ability to set a password via WiFi on the first connection, but as WebREPL
|
||||
was becoming more widely known and popular, the initial setup has switched
|
||||
to a wired connection for improved security::
|
||||
|
||||
import webrepl_setup
|
||||
|
||||
Follow the on-screen instructions and prompts. To make any changes active,
|
||||
you will need to reboot your device.
|
||||
|
||||
To use WebREPL connect your computer to the ESP8266's access point
|
||||
(MicroPython-xxxxxx, see the previous section about this). If you have
|
||||
already reconfigured your ESP8266 to connect to a router then you can
|
||||
@ -49,19 +61,11 @@ skip this part.
|
||||
Once you are on the same network as the ESP8266 you click the "Connect" button
|
||||
(if you are connecting via a router then you may need to change the IP address,
|
||||
by default the IP address is correct when connected to the ESP8266's access
|
||||
point). If the connection succeeds then you should see a welcome message.
|
||||
point). If the connection succeeds then you should see a password prompt.
|
||||
|
||||
On the first connection you need to set a password. Make sure that the
|
||||
terminal widget is selected by clicking on it, and then follow prompts to
|
||||
type in your password twice (they should match each other). Then ESP8266
|
||||
will then reboot with the password applied (the WiFi will go down but come
|
||||
back up again). Note that some modules may have troubles rebooting
|
||||
automatically and need reset button press or power cycle (do this if
|
||||
you don't see ESP8266 access point appearing in a minute or so).
|
||||
|
||||
You should then click the "Connect" button again, and enter your password
|
||||
to connect. If you type in the correct password you should get a prompt
|
||||
looking like ``>>>``. You can now start typing Python commands!
|
||||
Once you type the password configured at the setup step above, press Enter once
|
||||
more and you should get a prompt looking like ``>>>``. You can now start
|
||||
typing Python commands!
|
||||
|
||||
Using the REPL
|
||||
--------------
|
||||
|
@ -45,3 +45,39 @@ Functions
|
||||
.. function:: flash_write(byte_offset, bytes)
|
||||
|
||||
.. function:: flash_erase(sector_no)
|
||||
|
||||
.. function:: set_native_code_location(start, length)
|
||||
|
||||
Set the location that native code will be placed for execution after it is
|
||||
compiled. Native code is emitted when the ``@micropython.native``,
|
||||
``@micropython.viper`` and ``@micropython.asm_xtensa`` decorators are applied
|
||||
to a function. The ESP8266 must execute code from either iRAM or the lower
|
||||
1MByte of flash (which is memory mapped), and this function controls the
|
||||
location.
|
||||
|
||||
If `start` and `length` are both `None` then the native code location is
|
||||
set to the unused portion of memory at the end of the iRAM1 region. The
|
||||
size of this unused portion depends on the firmware and is typically quite
|
||||
small (around 500 bytes), and is enough to store a few very small
|
||||
functions. The advantage of using this iRAM1 region is that it does not
|
||||
get worn out by writing to it.
|
||||
|
||||
If neither `start` nor `length` are `None` then they should be integers.
|
||||
`start` should specify the byte offset from the beginning of the flash at
|
||||
which native code should be stored. `length` specifies how many bytes of
|
||||
flash from `start` can be used to store native code. `start` and `length`
|
||||
should be multiples of the sector size (being 4096 bytes). The flash will
|
||||
be automatically erased before writing to it so be sure to use a region of
|
||||
flash that is not otherwise used, for example by the firmware or the
|
||||
filesystem.
|
||||
|
||||
When using the flash to store native code `start+length` must be less
|
||||
than or equal to 1MByte. Note that the flash can be worn out if repeated
|
||||
erasures (and writes) are made so use this feature sparingly.
|
||||
In particular, native code needs to be recompiled and rewritten to flash
|
||||
on each boot (including wake from deepsleep).
|
||||
|
||||
In both cases above, using iRAM1 or flash, if there is no more room left
|
||||
in the specified region then the use of a native decorator on a function
|
||||
will lead to `MemoryError` exception being raised during compilation of
|
||||
that function.
|
||||
|
@ -36,15 +36,20 @@ Python standard libraries and micro-libraries
|
||||
The following standard Python libraries have been "micro-ified" to fit in with
|
||||
the philosophy of MicroPython. They provide the core functionality of that
|
||||
module and are intended to be a drop-in replacement for the standard Python
|
||||
library.
|
||||
library. Some modules below use a standard Python name, but prefixed with "u",
|
||||
e.g. ``ujson`` instead of ``json``. This is to signify that such a module is
|
||||
micro-library, i.e. implements only a subset of CPython module functionality.
|
||||
By naming them differently, a user has a choice to write a Python-level module
|
||||
to extend functionality for better compatibility with CPython (indeed, this is
|
||||
what done by micropython-lib project mentioned above).
|
||||
|
||||
.. only:: not port_unix
|
||||
|
||||
The modules are available by their u-name, and also by their non-u-name. The
|
||||
non-u-name can be overridden by a file of that name in your package path.
|
||||
For example, ``import json`` will first search for a file ``json.py`` or
|
||||
directory ``json`` and load that package if it is found. If nothing is found,
|
||||
it will fallback to loading the built-in ``ujson`` module.
|
||||
On some embedded platforms, where it may be cumbersome to add Python-level
|
||||
wrapper modules to achieve naming compatibility with CPython, micro-modules
|
||||
are available both by their u-name, and also by their non-u-name. The
|
||||
non-u-name can be overridden by a file of that name in your package path.
|
||||
For example, ``import json`` will first search for a file ``json.py`` or
|
||||
directory ``json`` and load that package if it is found. If nothing is found,
|
||||
it will fallback to loading the built-in ``ujson`` module.
|
||||
|
||||
.. only:: port_unix
|
||||
|
||||
|
@ -49,12 +49,23 @@ Constructors
|
||||
Construct an I2C object on the given bus. `bus` can only be 0.
|
||||
If the bus is not given, the default one will be selected (0).
|
||||
|
||||
.. only:: port_esp8266
|
||||
.. only:: not port_wipy
|
||||
|
||||
.. class:: I2C(scl, sda, \*, freq=400000)
|
||||
.. class:: I2C(id=-1, \*, scl, sda, freq=400000)
|
||||
|
||||
Construct and return a new I2C object.
|
||||
See the init method below for a description of the arguments.
|
||||
Construct and return a new I2C object using the following parameters:
|
||||
|
||||
- `id` identifies the particular I2C peripheral. The default
|
||||
value of -1 selects a software implementation of I2C which can
|
||||
work (in most cases) with arbitrary pins for SCL and SDA.
|
||||
If `id` is -1 then `scl` and `sda` must be specified. Other
|
||||
allowed values for `id` depend on the particular port/board,
|
||||
and specifying `scl` and `sda` may or may not be required or
|
||||
allowed in this case.
|
||||
- `scl` should be a pin object specifying the pin to use for SCL.
|
||||
- `sda` should be a pin object specifying the pin to use for SDA.
|
||||
- `freq` should be an integer which sets the maximum frequency
|
||||
for SCL.
|
||||
|
||||
General Methods
|
||||
---------------
|
||||
@ -102,29 +113,31 @@ control over the bus, otherwise the standard methods (see below) can be used.
|
||||
|
||||
.. method:: I2C.start()
|
||||
|
||||
Send a start bit on the bus (SDA transitions to low while SCL is high).
|
||||
Generate a START condition on the bus (SDA transitions to low while SCL is high).
|
||||
|
||||
Availability: ESP8266.
|
||||
|
||||
.. method:: I2C.stop()
|
||||
|
||||
Send a stop bit on the bus (SDA transitions to high while SCL is high).
|
||||
Generate a STOP condition on the bus (SDA transitions to high while SCL is high).
|
||||
|
||||
Availability: ESP8266.
|
||||
|
||||
.. method:: I2C.readinto(buf)
|
||||
.. method:: I2C.readinto(buf, nack=True)
|
||||
|
||||
Reads bytes from the bus and stores them into `buf`. The number of bytes
|
||||
read is the length of `buf`. An ACK will be sent on the bus after
|
||||
receiving all but the last byte, and a NACK will be sent following the last
|
||||
byte.
|
||||
receiving all but the last byte. After the last byte is received, if `nack`
|
||||
is true then a NACK will be sent, otherwise an ACK will be sent (and in this
|
||||
case the slave assumes more bytes are going to be read in a later call).
|
||||
|
||||
Availability: ESP8266.
|
||||
|
||||
.. method:: I2C.write(buf)
|
||||
|
||||
Write all the bytes from `buf` to the bus. Checks that an ACK is received
|
||||
after each byte and raises an OSError if not.
|
||||
Write the bytes from `buf` to the bus. Checks that an ACK is received
|
||||
after each byte and stops transmitting the remaining bytes if a NACK is
|
||||
received. The function returns the number of ACKs that were received.
|
||||
|
||||
Availability: ESP8266.
|
||||
|
||||
@ -134,29 +147,27 @@ Standard bus operations
|
||||
The following methods implement the standard I2C master read and write
|
||||
operations that target a given slave device.
|
||||
|
||||
.. method:: I2C.readfrom(addr, nbytes)
|
||||
.. method:: I2C.readfrom(addr, nbytes, stop=True)
|
||||
|
||||
Read `nbytes` from the slave specified by `addr`.
|
||||
If `stop` is true then a STOP condition is generated at the end of the transfer.
|
||||
Returns a `bytes` object with the data read.
|
||||
|
||||
.. method:: I2C.readfrom_into(addr, buf)
|
||||
.. method:: I2C.readfrom_into(addr, buf, stop=True)
|
||||
|
||||
Read into `buf` from the slave specified by `addr`.
|
||||
The number of bytes read will be the length of `buf`.
|
||||
If `stop` is true then a STOP condition is generated at the end of the transfer.
|
||||
|
||||
On WiPy the return value is the number of bytes read. Otherwise the
|
||||
return value is `None`.
|
||||
The method returns `None`.
|
||||
|
||||
.. method:: I2C.writeto(addr, buf, \*, stop=True)
|
||||
.. method:: I2C.writeto(addr, buf, stop=True)
|
||||
|
||||
Write the bytes from `buf` to the slave specified by `addr`.
|
||||
|
||||
The `stop` argument (only available on WiPy) tells if a stop bit should be
|
||||
sent at the end of the transfer. If `False` the transfer should be
|
||||
continued later on.
|
||||
|
||||
On WiPy the return value is the number of bytes written. Otherwise the
|
||||
return value is `None`.
|
||||
Write the bytes from `buf` to the slave specified by `addr`. If a
|
||||
NACK is received following the write of a byte from `buf` then the
|
||||
remaining bytes are not sent. If `stop` is true then a STOP condition is
|
||||
generated at the end of the transfer, even if a NACK is received.
|
||||
The function returns the number of ACKs that were received.
|
||||
|
||||
Memory operations
|
||||
-----------------
|
||||
|
@ -3,16 +3,44 @@
|
||||
class Pin -- control I/O pins
|
||||
=============================
|
||||
|
||||
A pin is the basic object to control I/O pins (also known as GPIO -
|
||||
general-purpose input/output). It has methods to set
|
||||
the mode of the pin (input, output, etc) and methods to get and set the
|
||||
digital logic level. For analog control of a pin, see the ADC class.
|
||||
A pin object is used to control I/O pins (also known as GPIO - general-purpose
|
||||
input/output). Pin objects are commonly associated with a physical pin that can
|
||||
drive an output voltage and read input voltages. The pin class has methods to set the mode of
|
||||
the pin (IN, OUT, etc) and methods to get and set the digital logic level.
|
||||
For analog control of a pin, see the :class:`ADC` class.
|
||||
|
||||
Usage Model:
|
||||
A pin object is constructed by using an identifier which unambiguously
|
||||
specifies a certain I/O pin. The allowed forms of the identifier and the
|
||||
physical pin that the identifier maps to are port-specific. Possibilities
|
||||
for the identifier are an integer, a string or a tuple with port and pin
|
||||
number.
|
||||
|
||||
Usage Model::
|
||||
|
||||
from machine import Pin
|
||||
|
||||
# create an output pin on pin #0
|
||||
p0 = Pin(0, Pin.OUT)
|
||||
|
||||
# set the value low then high
|
||||
p0.value(0)
|
||||
p0.value(1)
|
||||
|
||||
# create an input pin on pin #2, with a pull up resistor
|
||||
p2 = Pin(2, Pin.IN, Pin.PULL_UP)
|
||||
|
||||
# read and print the pin value
|
||||
print(p2.value())
|
||||
|
||||
# reconfigure pin #0 in input mode
|
||||
p0.mode(p0.IN)
|
||||
|
||||
# configure an irq callback
|
||||
p0.irq(lambda p:print(p))
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
Board pins are identified by their string id::
|
||||
On the WiPy board the pins are identified by their string id::
|
||||
|
||||
from machine import Pin
|
||||
g = machine.Pin('GP9', mode=Pin.OUT, pull=None, drive=Pin.MED_POWER, alt=-1)
|
||||
@ -40,174 +68,224 @@ Usage Model:
|
||||
All pin objects go through the pin mapper to come up with one of the
|
||||
gpio pins.
|
||||
|
||||
.. only:: port_esp8266
|
||||
For the ``drive`` parameter the strengths are:
|
||||
|
||||
::
|
||||
- ``Pin.LOW_POWER`` - 2mA drive capability.
|
||||
- ``Pin.MED_POWER`` - 4mA drive capability.
|
||||
- ``Pin.HIGH_POWER`` - 6mA drive capability.
|
||||
|
||||
from machine import Pin
|
||||
For the ``alt`` parameter please refer to the pinout and alternate functions
|
||||
table at <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
|
||||
for the specific alternate functions that each pin supports.
|
||||
|
||||
# create an output pin on GPIO0
|
||||
p0 = Pin(0, Pin.OUT)
|
||||
p0.value(0)
|
||||
p0.value(1)
|
||||
For interrupts, the ``priority`` can take values in the range 1-7. And the
|
||||
``wake`` parameter has the following properties:
|
||||
|
||||
# create an input pin on GPIO2
|
||||
p2 = Pin(2, Pin.IN, Pin.PULL_UP)
|
||||
print(p2.value())
|
||||
- If ``wake_from=machine.Sleep.ACTIVE`` any pin can wake the board.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, GP17`` or ``GP24`` can wake the board. Note that only 1
|
||||
of this pins can be enabled as a wake source at the same time, so, only
|
||||
the last enabled pin as a ``machine.Sleep.SUSPENDED`` wake source will have effect.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, ``GP17`` and ``GP24`` can wake the board. In this case all of the
|
||||
6 pins can be enabled as a ``machine.Sleep.HIBERNATE`` wake source at the same time.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: Pin(id, ...)
|
||||
.. class:: Pin(id, mode=-1, pull=-1, \*, value, drive, alt)
|
||||
|
||||
Create a new Pin object associated with the id. If additional arguments are given,
|
||||
they are used to initialise the pin. See :meth:`Pin.init`.
|
||||
Access the pin peripheral (GPIO pin) associated with the given ``id``. If
|
||||
additional arguments are given in the constructor then they are used to initialise
|
||||
the pin. Any settings that are not specified will remain in their previous state.
|
||||
|
||||
The arguments are:
|
||||
|
||||
- ``id`` is mandatory and can be an arbitrary object. Among possible value
|
||||
types are: int (an internal Pin identifier), str (a Pin name), and tuple
|
||||
(pair of [port, pin]).
|
||||
|
||||
- ``mode`` specifies the pin mode, which can be one of:
|
||||
|
||||
- ``Pin.IN`` - Pin is configured for input. If viewed as an output the pin
|
||||
is in high-impedance state.
|
||||
|
||||
- ``Pin.OUT`` - Pin is configured for (normal) output.
|
||||
|
||||
- ``Pin.OPEN_DRAIN`` - Pin is configured for open-drain output. Open-drain
|
||||
output works in the following way: if the output value is set to 0 the pin
|
||||
is active at a low level; if the output value is 1 the pin is in a high-impedance
|
||||
state. Not all ports implement this mode, or some might only on certain pins.
|
||||
|
||||
- ``Pin.ALT`` - Pin is configured to perform an alternative function, which is
|
||||
port specific. For a pin configured in such a way any other Pin methods
|
||||
(except :meth:`Pin.init`) are not applicable (calling them will lead to undefined,
|
||||
or a hardware-specific, result). Not all ports implement this mode.
|
||||
|
||||
- ``Pin.ALT_OPEN_DRAIN`` - The Same as ``Pin.ALT``, but the pin is configured as
|
||||
open-drain. Not all ports implement this mode.
|
||||
|
||||
- ``pull`` specifies if the pin has a (weak) pull resistor attached, and can be
|
||||
one of:
|
||||
|
||||
- ``None`` - No pull up or down resistor.
|
||||
- ``Pin.PULL_UP`` - Pull up resistor enabled.
|
||||
- ``Pin.PULL_DOWN`` - Pull down resistor enabled.
|
||||
|
||||
- ``value`` is valid only for Pin.OUT and Pin.OPEN_DRAIN modes and specifies initial
|
||||
output pin value if given, otherwise the state of the pin peripheral remains
|
||||
unchanged.
|
||||
|
||||
- ``drive`` specifies the output power of the pin and can be one of: ``Pin.LOW_POWER``,
|
||||
``Pin.MED_POWER`` or ``Pin.HIGH_POWER``. The actual current driving capabilities
|
||||
are port dependent. Not all ports implement this argument.
|
||||
|
||||
- ``alt`` specifies an alternate function for the pin and the values it can take are
|
||||
port dependent. This argument is valid only for ``Pin.ALT`` and ``Pin.ALT_OPEN_DRAIN``
|
||||
modes. It may be used when a pin supports more than one alternate function. If only
|
||||
one pin alternate function is supported the this argument is not required. Not all
|
||||
ports implement this argument.
|
||||
|
||||
As specified above, the Pin class allows to set an alternate function for a particular
|
||||
pin, but it does not specify any further operations on such a pin. Pins configured in
|
||||
alternate-function mode are usually not used as GPIO but are instead driven by other
|
||||
hardware peripherals. The only operation supported on such a pin is re-initialising,
|
||||
by calling the constructor or :meth:`Pin.init` method. If a pin that is configured in
|
||||
alternate-function mode is re-initialised with ``Pin.IN``, ``Pin.OUT``, or
|
||||
``Pin.OPEN_DRAIN``, the alternate function will be removed from the pin.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. only:: port_wipy
|
||||
.. method:: Pin.init(mode=-1, pull=-1, \*, value, drive, alt)
|
||||
|
||||
.. method:: Pin.init(mode, pull, \*, drive, alt)
|
||||
|
||||
Initialise the pin:
|
||||
Re-initialise the pin using the given parameters. Only those arguments that
|
||||
are specified will be set. The rest of the pin peripheral state will remain
|
||||
unchanged. See the constructor documentation for details of the arguments.
|
||||
|
||||
- ``mode`` can be one of:
|
||||
Returns ``None``.
|
||||
|
||||
- ``Pin.IN`` - input pin.
|
||||
- ``Pin.OUT`` - output pin in push-pull mode.
|
||||
- ``Pin.OPEN_DRAIN`` - output pin in open-drain mode.
|
||||
- ``Pin.ALT`` - pin mapped to an alternate function.
|
||||
- ``Pin.ALT_OPEN_DRAIN`` - pin mapped to an alternate function in open-drain mode.
|
||||
.. method:: Pin.value([x])
|
||||
|
||||
- ``pull`` can be one of:
|
||||
This method allows to set and get the value of the pin, depending on whether
|
||||
the argument ``x`` is supplied or not.
|
||||
|
||||
- ``None`` - no pull up or down resistor.
|
||||
- ``Pin.PULL_UP`` - pull up resistor enabled.
|
||||
- ``Pin.PULL_DOWN`` - pull down resistor enabled.
|
||||
If the argument is omitted then this method gets the digital logic level of
|
||||
the pin, returning 0 or 1 corresponding to low and high voltage signals
|
||||
respectively. The behaviour of this method depends on the mode of the pin:
|
||||
|
||||
- ``drive`` can be one of:
|
||||
- ``Pin.IN`` - The method returns the actual input value currently present
|
||||
on the pin.
|
||||
- ``Pin.OUT`` - The behaviour and return value of the method is undefined.
|
||||
- ``Pin.OPEN_DRAIN`` - If the pin is in state '0' then the behaviour and
|
||||
return value of the method is undefined. Otherwise, if the pin is in
|
||||
state '1', the method returns the actual input value currently present
|
||||
on the pin.
|
||||
|
||||
- ``Pin.LOW_POWER`` - 2mA drive capability.
|
||||
- ``Pin.MED_POWER`` - 4mA drive capability.
|
||||
- ``Pin.HIGH_POWER`` - 6mA drive capability.
|
||||
If the argument is supplied then this method sets the digital logic level of
|
||||
the pin. The argument ``x`` can be anything that converts to a boolean.
|
||||
If it converts to ``True``, the pin is set to state '1', otherwise it is set
|
||||
to state '0'. The behaviour of this method depends on the mode of the pin:
|
||||
|
||||
- ``alt`` is the number of the alternate function. Please refer to the
|
||||
`pinout and alternate functions table. <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
|
||||
for the specific alternate functions that each pin supports.
|
||||
- ``Pin.IN`` - The value is stored in the output buffer for the pin. The
|
||||
pin state does not change, it remains in the high-impedance state. The
|
||||
stored value will become active on the pin as soon as it is changed to
|
||||
``Pin.OUT`` or ``Pin.OPEN_DRAIN`` mode.
|
||||
- ``Pin.OUT`` - The output buffer is set to the given value immediately.
|
||||
- ``Pin.OPEN_DRAIN`` - If the value is '0' the pin is set to a low voltage
|
||||
state. Otherwise the pin is set to high-impedance state.
|
||||
|
||||
Returns: ``None``.
|
||||
When setting the value this method returns ``None``.
|
||||
|
||||
.. method:: Pin.id()
|
||||
.. method:: Pin.out_value()
|
||||
|
||||
Get the pin id.
|
||||
Return the value stored in the output buffer of a pin, regardless of its mode.
|
||||
|
||||
.. only:: port_esp8266
|
||||
Not all ports implement this method.
|
||||
|
||||
.. method:: Pin.init(mode, pull=None, \*, value)
|
||||
.. method:: Pin.__call__([x])
|
||||
|
||||
Initialise the pin:
|
||||
Pin objects are callable. The call method provides a (fast) shortcut to set
|
||||
and get the value of the pin. It is equivalent to Pin.value([x]).
|
||||
See :meth:`Pin.value` for more details.
|
||||
|
||||
- `mode` can be one of:
|
||||
.. method:: Pin.toggle()
|
||||
|
||||
- ``Pin.IN`` - input pin.
|
||||
- ``Pin.OUT`` - output pin in push-pull mode.
|
||||
Toggle the output value of the pin. Equivalent to ``pin.value(not pin.out_value())``.
|
||||
Returns ``None``.
|
||||
|
||||
- `pull` can be one of:
|
||||
Not all ports implement this method.
|
||||
|
||||
- ``None`` - no pull up or down resistor.
|
||||
- ``Pin.PULL_UP`` - pull up resistor enabled.
|
||||
Availability: WiPy.
|
||||
|
||||
- if `value` is given then it is the output value to set the pin
|
||||
if it is in output mode.
|
||||
.. method:: Pin.id()
|
||||
|
||||
.. method:: Pin.value([value])
|
||||
Get the pin identifier. This may return the ``id`` as specified in the
|
||||
constructor. Or it may return a canonical software-specific pin id.
|
||||
|
||||
Get or set the digital logic level of the pin:
|
||||
.. method:: Pin.mode([mode])
|
||||
|
||||
- With no argument, return 0 or 1 depending on the logic level of the pin.
|
||||
- With ``value`` given, set the logic level of the pin. ``value`` can be
|
||||
anything that converts to a boolean. If it converts to ``True``, the pin
|
||||
is set high, otherwise it is set low.
|
||||
Get or set the pin mode.
|
||||
See the constructor documentation for details of the ``mode`` argument.
|
||||
|
||||
.. method:: Pin.__call__([value])
|
||||
.. method:: Pin.pull([pull])
|
||||
|
||||
Pin objects are callable. The call method provides a (fast) shortcut to set and get the value of the pin.
|
||||
See :func:`Pin.value` for more details.
|
||||
Get or set the pin pull state.
|
||||
See the constructor documentation for details of the ``pull`` argument.
|
||||
|
||||
.. method:: Pin.alt_list()
|
||||
.. method:: Pin.drive([drive])
|
||||
|
||||
Returns a list of the alternate functions supported by the pin. List items are
|
||||
a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
|
||||
Get or set the pin drive strength.
|
||||
See the constructor documentation for details of the ``drive`` argument.
|
||||
|
||||
Availability: WiPy.
|
||||
Not all ports implement this method.
|
||||
|
||||
Availability: WiPy.
|
||||
|
||||
.. method:: Pin.irq(handler=None, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING), \*, priority=1, wake=None)
|
||||
|
||||
Configure an interrupt handler to be called when the trigger source of the
|
||||
pin is active. If the pin mode is ``Pin.IN`` then the trigger source is
|
||||
the external value on the pin. If the pin mode is ``Pin.OUT`` then the
|
||||
trigger source is the output buffer of the pin. Otherwise, if the pin mode
|
||||
is ``Pin.OPEN_DRAIN`` then the trigger source is the output buffer for
|
||||
state '0' and the external pin value for state '1'.
|
||||
|
||||
The arguments are:
|
||||
|
||||
- ``handler`` is an optional function to be called when the interrupt
|
||||
triggers.
|
||||
|
||||
- ``trigger`` configures the event which can generate an interrupt.
|
||||
Possible values are:
|
||||
|
||||
- ``Pin.IRQ_FALLING`` interrupt on falling edge.
|
||||
- ``Pin.IRQ_RISING`` interrupt on rising edge.
|
||||
- ``Pin.IRQ_LOW_LEVEL`` interrupt on low level.
|
||||
- ``Pin.IRQ_HIGH_LEVEL`` interrupt on high level.
|
||||
|
||||
These values can be OR'ed together to trigger on multiple events.
|
||||
|
||||
- ``priority`` sets the priority level of the interrupt. The values it
|
||||
can take are port-specific, but higher values always represent higher
|
||||
priorities.
|
||||
|
||||
- ``wake`` selects the power mode in which this interrupt can wake up the
|
||||
system. It can be ``machine.IDLE``, ``machine.SLEEP`` or ``machine.DEEPSLEEP``.
|
||||
These values can also be OR'ed together to make a pin generate interrupts in
|
||||
more than one power mode.
|
||||
|
||||
This method returns a callback object.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. method:: Pin.toggle()
|
||||
.. method:: Pin.alt_list()
|
||||
|
||||
Toggle the value of the pin.
|
||||
Returns a list of the alternate functions supported by the pin. List items are
|
||||
a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
|
||||
|
||||
.. method:: Pin.mode([mode])
|
||||
Availability: WiPy.
|
||||
|
||||
Get or set the pin mode.
|
||||
|
||||
.. method:: Pin.pull([pull])
|
||||
|
||||
Get or set the pin pull.
|
||||
|
||||
.. method:: Pin.drive([drive])
|
||||
|
||||
Get or set the pin drive strength.
|
||||
|
||||
.. method:: Pin.irq(\*, trigger, priority=1, handler=None, wake=None)
|
||||
|
||||
Create a callback to be triggered when the input level at the pin changes.
|
||||
|
||||
- ``trigger`` configures the pin level which can generate an interrupt. Possible values are:
|
||||
|
||||
- ``Pin.IRQ_FALLING`` interrupt on falling edge.
|
||||
- ``Pin.IRQ_RISING`` interrupt on rising edge.
|
||||
- ``Pin.IRQ_LOW_LEVEL`` interrupt on low level.
|
||||
- ``Pin.IRQ_HIGH_LEVEL`` interrupt on high level.
|
||||
|
||||
The values can be *ORed* together, for instance mode=Pin.IRQ_FALLING | Pin.IRQ_RISING
|
||||
|
||||
- ``priority`` level of the interrupt. Can take values in the range 1-7.
|
||||
Higher values represent higher priorities.
|
||||
- ``handler`` is an optional function to be called when new characters arrive.
|
||||
- ``wakes`` selects the power mode in which this interrupt can wake up the
|
||||
board. Please note:
|
||||
|
||||
- If ``wake_from=machine.Sleep.ACTIVE`` any pin can wake the board.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, GP17`` or ``GP24`` can wake the board. Note that only 1
|
||||
of this pins can be enabled as a wake source at the same time, so, only
|
||||
the last enabled pin as a ``machine.Sleep.SUSPENDED`` wake source will have effect.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, ``GP17`` and ``GP24`` can wake the board. In this case all of the
|
||||
6 pins can be enabled as a ``machine.Sleep.HIBERNATE`` wake source at the same time.
|
||||
- Values can be ORed to make a pin generate interrupts in more than one power
|
||||
mode.
|
||||
|
||||
Returns a callback object.
|
||||
|
||||
.. only:: port_esp8266
|
||||
|
||||
.. method:: Pin.irq(\*, trigger, handler=None)
|
||||
|
||||
Create a callback to be triggered when the input level at the pin changes.
|
||||
|
||||
- ``trigger`` configures the pin level which can generate an interrupt. Possible values are:
|
||||
|
||||
- ``Pin.IRQ_FALLING`` interrupt on falling edge.
|
||||
- ``Pin.IRQ_RISING`` interrupt on rising edge.
|
||||
|
||||
The values can be OR'ed together to trigger on multiple events.
|
||||
|
||||
- ``handler`` is an optional function to be called when the interrupt triggers.
|
||||
|
||||
Returns a callback object.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
@ -239,7 +317,8 @@ not all constants are available on all ports.
|
||||
.. data:: Pin.PULL_UP
|
||||
Pin.PULL_DOWN
|
||||
|
||||
Selects the whether there is a pull up/down resistor.
|
||||
Selects whether there is a pull up/down resistor. Use the value
|
||||
``None`` for no pull.
|
||||
|
||||
.. data:: Pin.LOW_POWER
|
||||
Pin.MED_POWER
|
||||
|
@ -6,7 +6,7 @@ class SPI -- a Serial Peripheral Interface bus protocol (master side)
|
||||
SPI is a synchronous serial protocol that is driven by a master. At the
|
||||
physical level, a bus consists of 3 lines: SCK, MOSI, MISO. Multiple devices
|
||||
can share the same bus. Each device should have a separate, 4th signal,
|
||||
SS (Slave Select), to select a particualr device on a bus with which
|
||||
SS (Slave Select), to select a particular device on a bus with which
|
||||
communication takes place. Management of an SS signal should happen in
|
||||
user code (via machine.Pin class).
|
||||
|
||||
@ -51,12 +51,12 @@ Methods
|
||||
- ``bits`` is the width in bits of each transfer. Only 8 is guaranteed to be supported by all hardware.
|
||||
- ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``.
|
||||
- ``sck``, ``mosi``, ``miso`` are pins (machine.Pin) objects to use for bus signals. For most
|
||||
hardware SPI blocks (as selected by ``id`` parameter to the constructore), pins are fixed
|
||||
hardware SPI blocks (as selected by ``id`` parameter to the constructor), pins are fixed
|
||||
and cannot be changed. In some cases, hardware blocks allow 2-3 alternative pin sets for
|
||||
a hardware SPI block. Arbitrary pin assignments are possible only for a bitbanging SPI driver
|
||||
(``id`` = -1).
|
||||
- ``pins`` - WiPy port doesn't ``sck``, ``mosi``, ``miso`` arguments, and instead allows to
|
||||
specify them as a tuple of ``pins`` paramter.
|
||||
specify them as a tuple of ``pins`` parameter.
|
||||
|
||||
.. method:: SPI.deinit()
|
||||
|
||||
|
@ -31,7 +31,7 @@ A UART object acts like a stream object and reading and writing is done
|
||||
using the standard stream methods::
|
||||
|
||||
uart.read(10) # read 10 characters, returns a bytes object
|
||||
uart.readall() # read all available characters
|
||||
uart.read() # read all available characters
|
||||
uart.readline() # read a line
|
||||
uart.readinto(buf) # read and store into the given buffer
|
||||
uart.write('abc') # write the 3 characters
|
||||
@ -95,17 +95,12 @@ Methods
|
||||
|
||||
.. method:: UART.read([nbytes])
|
||||
|
||||
Read characters. If ``nbytes`` is specified then read at most that many bytes.
|
||||
Read characters. If ``nbytes`` is specified then read at most that many bytes,
|
||||
otherwise read as much data as possible.
|
||||
|
||||
Return value: a bytes object containing the bytes read in. Returns ``None``
|
||||
on timeout.
|
||||
|
||||
.. method:: UART.readall()
|
||||
|
||||
Read as much data as possible.
|
||||
|
||||
Return value: a bytes object or ``None`` on timeout.
|
||||
|
||||
.. method:: UART.readinto(buf[, nbytes])
|
||||
|
||||
Read bytes into the ``buf``. If ``nbytes`` is specified then read at most
|
||||
|
@ -46,3 +46,11 @@ Methods
|
||||
.. method:: Accel.z()
|
||||
|
||||
Get the z-axis value.
|
||||
|
||||
Hardware Note
|
||||
-------------
|
||||
|
||||
The accelerometer uses I2C bus 1 to communicate with the processor. Consequently
|
||||
when readings are being taken pins X9 and X10 should be unused (other than for
|
||||
I2C). Other devices using those pins, and which therefore cannot be used
|
||||
concurrently, are UART 1 and Timer 4 channels 1 and 2.
|
||||
|
@ -92,7 +92,7 @@ Methods
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
.. method:: I2C.init(mode, \*, addr=0x12, baudrate=400000, gencall=False)
|
||||
.. method:: I2C.init(mode, \*, addr=0x12, baudrate=400000, gencall=False, dma=False)
|
||||
|
||||
Initialise the I2C bus with the given parameters:
|
||||
|
||||
@ -100,6 +100,9 @@ Methods
|
||||
- ``addr`` is the 7-bit address (only sensible for a slave)
|
||||
- ``baudrate`` is the SCL clock rate (only sensible for a master)
|
||||
- ``gencall`` is whether to support general call mode
|
||||
- ``dma`` is whether to allow the use of DMA for the I2C transfers (note
|
||||
that DMA transfers have more precise timing but currently do not handle bus
|
||||
errors properly)
|
||||
|
||||
.. method:: I2C.is_ready(addr)
|
||||
|
||||
|
@ -27,7 +27,7 @@ A UART object acts like a stream object and reading and writing is done
|
||||
using the standard stream methods::
|
||||
|
||||
uart.read(10) # read 10 characters, returns a bytes object
|
||||
uart.readall() # read all available characters
|
||||
uart.read() # read all available characters
|
||||
uart.readline() # read a line
|
||||
uart.readinto(buf) # read and store into the given buffer
|
||||
uart.write('abc') # write the 3 characters
|
||||
@ -87,8 +87,8 @@ Methods
|
||||
- ``stop`` is the number of stop bits, 1 or 2.
|
||||
- ``flow`` sets the flow control type. Can be 0, ``UART.RTS``, ``UART.CTS``
|
||||
or ``UART.RTS | UART.CTS``.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the first character.
|
||||
- ``timeout_char`` is the timeout in milliseconds to wait between characters.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for writing/reading the first character.
|
||||
- ``timeout_char`` is the timeout in milliseconds to wait between characters while writing or reading.
|
||||
- ``read_buf_len`` is the character length of the read buffer (0 to disable).
|
||||
|
||||
This method will raise an exception if the baudrate could not be set within
|
||||
@ -111,17 +111,15 @@ Methods
|
||||
|
||||
Returns the number of bytes waiting (may be 0).
|
||||
|
||||
.. method:: UART.writechar(char)
|
||||
|
||||
Write a single character on the bus. ``char`` is an integer to write.
|
||||
Return value: ``None``. See note below if CTS flow control is used.
|
||||
|
||||
.. method:: UART.read([nbytes])
|
||||
|
||||
Read characters. If ``nbytes`` is specified then read at most that many bytes.
|
||||
If ``nbytes`` are available in the buffer, returns immediately, otherwise returns
|
||||
when sufficient characters arrive or the timeout elapses.
|
||||
|
||||
If ``nbytes`` is not given then the method reads as much data as possible. It
|
||||
returns after the timeout has elapsed.
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
*Note:* for 9 bit characters each character takes two bytes, ``nbytes`` must
|
||||
@ -130,12 +128,6 @@ Methods
|
||||
Return value: a bytes object containing the bytes read in. Returns ``None``
|
||||
on timeout.
|
||||
|
||||
.. method:: UART.readall()
|
||||
|
||||
Read as much data as possible. Returns after the timeout has elapsed.
|
||||
|
||||
Return value: a bytes object or ``None`` if timeout prevents any data being read.
|
||||
|
||||
.. method:: UART.readchar()
|
||||
|
||||
Receive a single character on the bus.
|
||||
@ -170,6 +162,13 @@ Methods
|
||||
Return value: number of bytes written. If a timeout occurs and no bytes
|
||||
were written returns ``None``.
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
.. method:: UART.writechar(char)
|
||||
|
||||
Write a single character on the bus. ``char`` is an integer to write.
|
||||
Return value: ``None``. See note below if CTS flow control is used.
|
||||
|
||||
.. method:: UART.sendbreak()
|
||||
|
||||
Send a break condition on the bus. This drives the bus low for a duration
|
||||
|
@ -44,16 +44,12 @@ Methods
|
||||
.. method:: USB_VCP.read([nbytes])
|
||||
|
||||
Read at most ``nbytes`` from the serial device and return them as a
|
||||
bytes object. If ``nbytes`` is not specified then the method acts as
|
||||
``readall()``. USB_VCP stream implicitly works in non-blocking mode,
|
||||
bytes object. If ``nbytes`` is not specified then the method reads
|
||||
all available bytes from the serial device.
|
||||
USB_VCP stream implicitly works in non-blocking mode,
|
||||
so if no pending data available, this method will return immediately
|
||||
with ``None`` value.
|
||||
|
||||
.. method:: USB_VCP.readall()
|
||||
|
||||
Read all available bytes from the serial device and return them as
|
||||
a bytes object, or ``None`` if no pending data available.
|
||||
|
||||
.. method:: USB_VCP.readinto(buf, [maxlen])
|
||||
|
||||
Read bytes from the serial device and store them into ``buf``, which
|
||||
|
@ -149,10 +149,18 @@ Methods
|
||||
|
||||
Set a timeout on blocking socket operations. The value argument can be a nonnegative floating
|
||||
point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations
|
||||
will raise a timeout exception if the timeout period value has elapsed before the operation has
|
||||
will raise an ``OSError`` exception if the timeout period value has elapsed before the operation has
|
||||
completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket
|
||||
is put in blocking mode.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
CPython raises a ``socket.timeout`` exception in case of timeout,
|
||||
which is an ``OSError`` subclass. MicroPython raises an OSError directly
|
||||
instead. If you use ``except OSError:`` to catch the exception,
|
||||
your code will work both in MicroPython and CPython.
|
||||
|
||||
.. method:: socket.setblocking(flag)
|
||||
|
||||
Set blocking or non-blocking mode of the socket: if flag is false, the socket is set to non-blocking,
|
||||
@ -178,14 +186,10 @@ Methods
|
||||
Closing the file object returned by makefile() WILL close the
|
||||
original socket as well.
|
||||
|
||||
.. method:: socket.read(size)
|
||||
.. method:: socket.read([size])
|
||||
|
||||
Read up to size bytes from the socket. Return a bytes object. If ``size`` is not given, it
|
||||
behaves just like ``socket.readall()``, see below.
|
||||
|
||||
.. method:: socket.readall()
|
||||
|
||||
Read all data available from the socket until ``EOF``. This function will not return until
|
||||
reads all data available from the socket until ``EOF``; as such the method will not return until
|
||||
the socket is closed.
|
||||
|
||||
.. method:: socket.readinto(buf[, nbytes])
|
||||
|
@ -37,7 +37,7 @@ Use the :mod:`time <utime>` module::
|
||||
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
|
||||
delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference
|
||||
|
||||
LEDs
|
||||
----
|
||||
@ -152,7 +152,7 @@ See :ref:`pyb.SPI <pyb.SPI>`. ::
|
||||
spi = SPI(1, SPI.MASTER, baudrate=200000, polarity=1, phase=0)
|
||||
spi.send('hello')
|
||||
spi.recv(5) # receive 5 bytes on the bus
|
||||
spi.send_recv('hello') # send a receive 5 bytes
|
||||
spi.send_recv('hello') # send and receive 5 bytes
|
||||
|
||||
I2C bus
|
||||
-------
|
||||
|
@ -132,7 +132,7 @@ The following enables any function or method to be timed by adding an
|
||||
def new_func(*args, **kwargs):
|
||||
t = time.ticks_us()
|
||||
result = f(*args, **kwargs)
|
||||
delta = time.ticks_diff(t, time.ticks_us())
|
||||
delta = time.ticks_diff(time.ticks_us(), t)
|
||||
print('Function {} Time = {:6.3f}ms'.format(myname, delta/1000))
|
||||
return result
|
||||
return new_func
|
||||
|
@ -102,7 +102,7 @@ See :ref:`machine.SPI <machine.SPI>`. ::
|
||||
spi.write('hello')
|
||||
spi.read(5) # receive 5 bytes on the bus
|
||||
rbuf = bytearray(5)
|
||||
spi.write_readinto('hello', rbuf) # send a receive 5 bytes
|
||||
spi.write_readinto('hello', rbuf) # send and receive 5 bytes
|
||||
|
||||
I2C bus
|
||||
-------
|
||||
|
@ -1,5 +1,6 @@
|
||||
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
|
||||
|
||||
from micropython import const
|
||||
import time
|
||||
import framebuf
|
||||
|
||||
@ -31,7 +32,7 @@ class SSD1306:
|
||||
self.external_vcc = external_vcc
|
||||
self.pages = self.height // 8
|
||||
self.buffer = bytearray(self.pages * self.width)
|
||||
self.framebuf = framebuf.FrameBuffer1(self.buffer, self.width, self.height)
|
||||
self.framebuf = framebuf.FrameBuffer(self.buffer, self.width, self.height, framebuf.MVLSB)
|
||||
self.poweron()
|
||||
self.init_display()
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""NRF24L01 driver for Micro Python
|
||||
"""
|
||||
|
||||
from micropython import const
|
||||
import pyb
|
||||
|
||||
# nRF24L01+ registers
|
||||
|
@ -43,7 +43,7 @@ def master():
|
||||
timeout = True
|
||||
|
||||
if timeout:
|
||||
print('failed, respones timed out')
|
||||
print('failed, response timed out')
|
||||
num_failures += 1
|
||||
|
||||
else:
|
||||
@ -57,7 +57,7 @@ def master():
|
||||
# delay then loop
|
||||
pyb.delay(250)
|
||||
|
||||
print('master finished sending; succeses=%d, failures=%d' % (num_successes, num_failures))
|
||||
print('master finished sending; successes=%d, failures=%d' % (num_successes, num_failures))
|
||||
|
||||
def slave():
|
||||
nrf = NRF24L01(SPI(2), Pin('Y5'), Pin('Y4'), payload_size=8)
|
||||
|
@ -93,6 +93,9 @@ class DS18X20(object):
|
||||
temp = temp_read - 0.25 + (count_per_c - count_remain) / count_per_c
|
||||
return temp
|
||||
elif rom0 == 0x28:
|
||||
return (temp_msb << 8 | temp_lsb) / 16
|
||||
temp = (temp_msb << 8 | temp_lsb) / 16
|
||||
if (temp_msb & 0xf8) == 0xf8: # for negative temperature
|
||||
temp -= 0x1000
|
||||
return temp
|
||||
else:
|
||||
assert False
|
||||
|
@ -60,7 +60,7 @@ class OneWire:
|
||||
|
||||
# cache a bunch of methods and attributes. This is necessary in _write_bit and
|
||||
# _read_bit to achieve the timing required by the OneWire protocol.
|
||||
self.cache = (pin.init, pin.value, pin.OUT_PP, pin.IN, pin.PULL_NONE)
|
||||
self.cache = (pin.init, pin.value, pin.OUT_PP, pin.IN, pin.PULL_UP)
|
||||
|
||||
pin.init(pin.IN, pin.PULL_UP)
|
||||
|
||||
|
@ -21,6 +21,7 @@ Example usage on ESP8266:
|
||||
|
||||
"""
|
||||
|
||||
from micropython import const
|
||||
import time
|
||||
|
||||
|
||||
@ -141,7 +142,7 @@ class SDCard:
|
||||
buf[5] = crc
|
||||
self.spi.write(buf)
|
||||
|
||||
# wait for the repsonse (response[7] == 0)
|
||||
# wait for the response (response[7] == 0)
|
||||
for i in range(_CMD_TIMEOUT):
|
||||
response = self.spi.read(1, 0xff)[0]
|
||||
if not (response & 0x80):
|
||||
|
@ -14,9 +14,7 @@ FROZEN_MPY_DIR = modules
|
||||
# include py core make definitions
|
||||
include ../py/py.mk
|
||||
|
||||
MPY_CROSS = ../mpy-cross/mpy-cross
|
||||
MPY_TOOL = ../tools/mpy-tool.py
|
||||
|
||||
FWBIN = $(BUILD)/firmware-combined.bin
|
||||
PORT ?= /dev/ttyACM0
|
||||
BAUD ?= 115200
|
||||
FLASH_MODE ?= qio
|
||||
@ -78,19 +76,18 @@ SRC_C = \
|
||||
espapa102.c \
|
||||
intr.c \
|
||||
modpyb.c \
|
||||
modpybpin.c \
|
||||
modpybpwm.c \
|
||||
modpybrtc.c \
|
||||
modpybadc.c \
|
||||
modpybuart.c \
|
||||
modmachinewdt.c \
|
||||
modpybspi.c \
|
||||
modpybhspi.c \
|
||||
modmachine.c \
|
||||
machine_pin.c \
|
||||
machine_pwm.c \
|
||||
machine_rtc.c \
|
||||
machine_adc.c \
|
||||
machine_uart.c \
|
||||
machine_wdt.c \
|
||||
machine_hspi.c \
|
||||
modesp.c \
|
||||
modnetwork.c \
|
||||
modutime.c \
|
||||
moduos.c \
|
||||
modmachine.c \
|
||||
modonewire.c \
|
||||
ets_alt_task.c \
|
||||
fatfs_port.c \
|
||||
@ -131,7 +128,6 @@ LIB_SRC_C = $(addprefix lib/,\
|
||||
netutils/netutils.c \
|
||||
timeutils/timeutils.c \
|
||||
utils/pyexec.c \
|
||||
utils/pyhelp.c \
|
||||
utils/interrupt_char.c \
|
||||
)
|
||||
|
||||
@ -148,9 +144,6 @@ DRIVERS_SRC_C = $(addprefix drivers/,\
|
||||
SRC_S = \
|
||||
gchelper.s \
|
||||
|
||||
FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py')
|
||||
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
|
||||
|
||||
OBJ =
|
||||
OBJ += $(PY_O)
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
||||
@ -159,9 +152,6 @@ OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
|
||||
ifneq ($(FROZEN_MPY_DIR),)
|
||||
OBJ += $(BUILD)/$(BUILD)/frozen_mpy.o
|
||||
endif
|
||||
#OBJ += $(BUILD)/pins_$(BOARD).o
|
||||
|
||||
# List of sources for qstr extraction
|
||||
@ -169,7 +159,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)/libaxtls.a $(BUILD)/firmware-combined.bin
|
||||
all: $(BUILD)/libaxtls.a $(FWBIN)
|
||||
|
||||
CONFVARS_FILE = $(BUILD)/confvars
|
||||
|
||||
@ -184,30 +174,23 @@ $(BUILD)/uart.o: $(CONFVARS_FILE)
|
||||
|
||||
FROZEN_EXTRA_DEPS = $(CONFVARS_FILE)
|
||||
|
||||
# to build .mpy files from .py files
|
||||
$(BUILD)/$(FROZEN_MPY_DIR)/%.mpy: $(FROZEN_MPY_DIR)/%.py
|
||||
@$(ECHO) "MPY $<"
|
||||
$(Q)$(MKDIR) -p $(dir $@)
|
||||
$(Q)$(MPY_CROSS) -o $@ -s $(^:$(FROZEN_MPY_DIR)/%=%) $^
|
||||
|
||||
# to build frozen_mpy.c from all .mpy files
|
||||
$(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h
|
||||
@$(ECHO) "Creating $@"
|
||||
$(Q)$(PYTHON) $(MPY_TOOL) -f -q $(BUILD)/genhdr/qstrdefs.preprocessed.h $(FROZEN_MPY_MPY_FILES) > $@
|
||||
|
||||
.PHONY: deploy
|
||||
|
||||
deploy: $(BUILD)/firmware-combined.bin
|
||||
$(ECHO) "Writing $< to the board"
|
||||
$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --verify --flash_size=$(FLASH_SIZE) --flash_mode=$(FLASH_MODE) 0 $<
|
||||
|
||||
erase:
|
||||
$(ECHO) "Erase flash"
|
||||
$(Q)esptool.py --port $(PORT) --baud $(BAUD) erase_flash
|
||||
|
||||
reset:
|
||||
echo -e "\r\nimport machine; machine.reset()\r\n" >$(PORT)
|
||||
|
||||
$(BUILD)/firmware-combined.bin: $(BUILD)/firmware.elf
|
||||
$(FWBIN): $(BUILD)/firmware.elf
|
||||
$(ECHO) "Create $@"
|
||||
$(Q)esptool.py elf2image $^
|
||||
$(Q)$(PYTHON) makeimg.py $(BUILD)/firmware.elf-0x00000.bin $(BUILD)/firmware.elf-0x0[1-f]000.bin $@
|
||||
$(Q)$(PYTHON) makeimg.py $(BUILD)/firmware.elf-0x00000.bin $(BUILD)/firmware.elf-0x[0-5][1-f]000.bin $@
|
||||
|
||||
$(BUILD)/firmware.elf: $(OBJ)
|
||||
$(ECHO) "LINK $@"
|
||||
@ -217,6 +200,10 @@ $(BUILD)/firmware.elf: $(OBJ)
|
||||
512k:
|
||||
$(MAKE) LDSCRIPT=esp8266_512k.ld CFLAGS_EXTRA='-DMP_CONFIGFILE="<mpconfigport_512k.h>"' MICROPY_FATFS=0 MICROPY_PY_BTREE=0
|
||||
|
||||
ota:
|
||||
rm -f $(BUILD)/firmware.elf $(BUILD)/firmware.elf*.bin
|
||||
$(MAKE) LDSCRIPT=esp8266_ota.ld FWBIN=$(BUILD)/firmware-ota.bin
|
||||
|
||||
#MAKE_PINS = boards/make-pins.py
|
||||
#BOARD_PINS = boards/$(BOARD)/pins.csv
|
||||
#AF_FILE = boards/stm32f4xx_af.csv
|
||||
|
@ -70,13 +70,14 @@ $ make deploy
|
||||
```
|
||||
This will use the `esptool.py` script to download the images. You must have
|
||||
your ESP module in the bootloader mode, and connected to a serial port on your PC.
|
||||
The default serial port is `/dev/ttyACM0`, flash mode is `qio` and flash size is `8m`.
|
||||
To specify other values, use, eg:
|
||||
The default serial port is `/dev/ttyACM0`, flash mode is `qio` and flash size is
|
||||
`detect` (auto-detect based on Flash ID). To specify other values, use, eg (note
|
||||
that flash size is in megabits):
|
||||
```bash
|
||||
$ make PORT=/dev/ttyUSB0 FLASH_MODE=qio FLASH_SIZE=8m deploy
|
||||
$ make PORT=/dev/ttyUSB0 FLASH_MODE=qio FLASH_SIZE=32m deploy
|
||||
```
|
||||
|
||||
The image produced is `firmware-combined.bin`, to be flashed at 0x00000.
|
||||
The image produced is `build/firmware-combined.bin`, to be flashed at 0x00000.
|
||||
|
||||
First start
|
||||
-----------
|
||||
|
@ -88,9 +88,11 @@ SECTIONS
|
||||
*py/builtin*.o*(.literal* .text*)
|
||||
*py/compile.o*(.literal* .text*)
|
||||
*py/emit*.o*(.literal* .text*)
|
||||
*py/persistentcode*.o*(.literal* .text*)
|
||||
*py/formatfloat.o*(.literal* .text*)
|
||||
*py/frozenmod.o*(.literal* .text*)
|
||||
*py/gc.o*(.literal* .text*)
|
||||
*py/reader*.o*(.literal* .text*)
|
||||
*py/lexer*.o*(.literal* .text*)
|
||||
*py/malloc*.o*(.literal* .text*)
|
||||
*py/map*.o*(.literal* .text*)
|
||||
@ -137,16 +139,16 @@ SECTIONS
|
||||
*lexerstr32.o(.literal* .text*)
|
||||
*utils.o(.literal* .text*)
|
||||
*modpyb.o(.literal*, .text*)
|
||||
*modpybpin.o(.literal*, .text*)
|
||||
*modpybpwm.o(.literal*, .text*)
|
||||
*modpybrtc.o(.literal*, .text*)
|
||||
*modpybadc.o(.literal*, .text*)
|
||||
*modpybuart.o(.literal*, .text*)
|
||||
*machine_pin.o(.literal*, .text*)
|
||||
*machine_pwm.o(.literal*, .text*)
|
||||
*machine_rtc.o(.literal*, .text*)
|
||||
*machine_adc.o(.literal*, .text*)
|
||||
*machine_uart.o(.literal*, .text*)
|
||||
*modpybi2c.o(.literal*, .text*)
|
||||
*modmachine.o(.literal*, .text*)
|
||||
*modmachinewdt.o(.literal*, .text*)
|
||||
*modpybspi.o(.literal*, .text*)
|
||||
*modpybhspi.o(.literal*, .text*)
|
||||
*machine_wdt.o(.literal*, .text*)
|
||||
*machine_spi.o(.literal*, .text*)
|
||||
*machine_hspi.o(.literal*, .text*)
|
||||
*hspi.o(.literal*, .text*)
|
||||
*modesp.o(.literal* .text*)
|
||||
*modnetwork.o(.literal* .text*)
|
||||
|
@ -88,9 +88,11 @@ SECTIONS
|
||||
*py/builtin*.o*(.literal* .text*)
|
||||
*py/compile.o*(.literal* .text*)
|
||||
*py/emit*.o*(.literal* .text*)
|
||||
*py/persistentcode*.o*(.literal* .text*)
|
||||
*py/formatfloat.o*(.literal* .text*)
|
||||
*py/frozenmod.o*(.literal* .text*)
|
||||
*py/gc.o*(.literal* .text*)
|
||||
*py/reader*.o*(.literal* .text*)
|
||||
*py/lexer*.o*(.literal* .text*)
|
||||
*py/malloc*.o*(.literal* .text*)
|
||||
*py/map*.o*(.literal* .text*)
|
||||
@ -137,16 +139,16 @@ SECTIONS
|
||||
*lexerstr32.o(.literal* .text*)
|
||||
*utils.o(.literal* .text*)
|
||||
*modpyb.o(.literal*, .text*)
|
||||
*modpybpin.o(.literal*, .text*)
|
||||
*modpybpwm.o(.literal*, .text*)
|
||||
*modpybrtc.o(.literal*, .text*)
|
||||
*modpybadc.o(.literal*, .text*)
|
||||
*modpybuart.o(.literal*, .text*)
|
||||
*machine_pin.o(.literal*, .text*)
|
||||
*machine_pwm.o(.literal*, .text*)
|
||||
*machine_rtc.o(.literal*, .text*)
|
||||
*machine_adc.o(.literal*, .text*)
|
||||
*machine_uart.o(.literal*, .text*)
|
||||
*modpybi2c.o(.literal*, .text*)
|
||||
*modmachine.o(.literal*, .text*)
|
||||
*modmachinewdt.o(.literal*, .text*)
|
||||
*modpybspi.o(.literal*, .text*)
|
||||
*modpybhspi.o(.literal*, .text*)
|
||||
*machine_wdt.o(.literal*, .text*)
|
||||
*machine_spi.o(.literal*, .text*)
|
||||
*machine_hspi.o(.literal*, .text*)
|
||||
*hspi.o(.literal*, .text*)
|
||||
*modesp.o(.literal* .text*)
|
||||
*modnetwork.o(.literal* .text*)
|
||||
|
306
esp8266/esp8266_ota.ld
Normal file
306
esp8266/esp8266_ota.ld
Normal file
@ -0,0 +1,306 @@
|
||||
/* GNU linker script for ESP8266 */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
dport0_0_seg : org = 0x3ff00000, len = 0x10
|
||||
dram0_0_seg : org = 0x3ffe8000, len = 0x14000
|
||||
iram1_0_seg : org = 0x40100000, len = 0x8000
|
||||
/* 0x3c000 is size of bootloader, 0x9000 is size of packed RAM segments */
|
||||
irom0_0_seg : org = 0x40200000 + 0x3c000 + 0x9000, len = 0x87000
|
||||
}
|
||||
|
||||
/* define the top of RAM */
|
||||
_heap_end = ORIGIN(dram0_0_seg) + LENGTH(dram0_0_seg);
|
||||
|
||||
PHDRS
|
||||
{
|
||||
dport0_0_phdr PT_LOAD;
|
||||
dram0_0_phdr PT_LOAD;
|
||||
dram0_0_bss_phdr PT_LOAD;
|
||||
iram1_0_phdr PT_LOAD;
|
||||
irom0_0_phdr PT_LOAD;
|
||||
}
|
||||
|
||||
ENTRY(firmware_start)
|
||||
EXTERN(_DebugExceptionVector)
|
||||
EXTERN(_DoubleExceptionVector)
|
||||
EXTERN(_KernelExceptionVector)
|
||||
EXTERN(_NMIExceptionVector)
|
||||
EXTERN(_UserExceptionVector)
|
||||
|
||||
PROVIDE(_memmap_vecbase_reset = 0x40000000);
|
||||
|
||||
/* Various memory-map dependent cache attribute settings: */
|
||||
_memmap_cacheattr_wb_base = 0x00000110;
|
||||
_memmap_cacheattr_wt_base = 0x00000110;
|
||||
_memmap_cacheattr_bp_base = 0x00000220;
|
||||
_memmap_cacheattr_unused_mask = 0xFFFFF00F;
|
||||
_memmap_cacheattr_wb_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wba_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wbna_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_wt_trapnull = 0x2222211F;
|
||||
_memmap_cacheattr_bp_trapnull = 0x2222222F;
|
||||
_memmap_cacheattr_wb_strict = 0xFFFFF11F;
|
||||
_memmap_cacheattr_wt_strict = 0xFFFFF11F;
|
||||
_memmap_cacheattr_bp_strict = 0xFFFFF22F;
|
||||
_memmap_cacheattr_wb_allvalid = 0x22222112;
|
||||
_memmap_cacheattr_wt_allvalid = 0x22222112;
|
||||
_memmap_cacheattr_bp_allvalid = 0x22222222;
|
||||
PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
.dport0.rodata : ALIGN(4)
|
||||
{
|
||||
_dport0_rodata_start = ABSOLUTE(.);
|
||||
*(.dport0.rodata)
|
||||
*(.dport.rodata)
|
||||
_dport0_rodata_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.dport0.literal : ALIGN(4)
|
||||
{
|
||||
_dport0_literal_start = ABSOLUTE(.);
|
||||
*(.dport0.literal)
|
||||
*(.dport.literal)
|
||||
_dport0_literal_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.dport0.data : ALIGN(4)
|
||||
{
|
||||
_dport0_data_start = ABSOLUTE(.);
|
||||
*(.dport0.data)
|
||||
*(.dport.data)
|
||||
_dport0_data_end = ABSOLUTE(.);
|
||||
} >dport0_0_seg :dport0_0_phdr
|
||||
|
||||
.irom0.text : ALIGN(4)
|
||||
{
|
||||
_irom0_text_start = ABSOLUTE(.);
|
||||
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
|
||||
|
||||
/* we put some specific text in this section */
|
||||
|
||||
*py/argcheck.o*(.literal* .text*)
|
||||
*py/asm*.o*(.literal* .text*)
|
||||
*py/bc.o*(.literal* .text*)
|
||||
*py/binary.o*(.literal* .text*)
|
||||
*py/builtin*.o*(.literal* .text*)
|
||||
*py/compile.o*(.literal* .text*)
|
||||
*py/emit*.o*(.literal* .text*)
|
||||
*py/persistentcode*.o*(.literal* .text*)
|
||||
*py/formatfloat.o*(.literal* .text*)
|
||||
*py/frozenmod.o*(.literal* .text*)
|
||||
*py/gc.o*(.literal* .text*)
|
||||
*py/reader*.o*(.literal* .text*)
|
||||
*py/lexer*.o*(.literal* .text*)
|
||||
*py/malloc*.o*(.literal* .text*)
|
||||
*py/map*.o*(.literal* .text*)
|
||||
*py/mod*.o*(.literal* .text*)
|
||||
*py/mpprint.o*(.literal* .text*)
|
||||
*py/mpstate.o*(.literal* .text*)
|
||||
*py/mpz.o*(.literal* .text*)
|
||||
*py/native*.o*(.literal* .text*)
|
||||
*py/nlr*.o*(.literal* .text*)
|
||||
*py/obj*.o*(.literal* .text*)
|
||||
*py/opmethods.o*(.literal* .text*)
|
||||
*py/parse*.o*(.literal* .text*)
|
||||
*py/qstr.o*(.literal* .text*)
|
||||
*py/repl.o*(.literal* .text*)
|
||||
*py/runtime.o*(.literal* .text*)
|
||||
*py/scope.o*(.literal* .text*)
|
||||
*py/sequence.o*(.literal* .text*)
|
||||
*py/showbc.o*(.literal* .text*)
|
||||
*py/smallint.o*(.literal* .text*)
|
||||
*py/stackctrl.o*(.literal* .text*)
|
||||
*py/stream.o*(.literal* .text*)
|
||||
*py/unicode.o*(.literal* .text*)
|
||||
*py/vm.o*(.literal* .text*)
|
||||
*py/vstr.o*(.literal* .text*)
|
||||
*py/warning.o*(.literal* .text*)
|
||||
|
||||
*extmod/*.o*(.literal* .text*)
|
||||
|
||||
*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*)
|
||||
*lib/timeutils/*.o*(.literal*, .text*)
|
||||
*lib/utils/*.o*(.literal*, .text*)
|
||||
|
||||
*stmhal/pybstdio.o(.literal*, .text*)
|
||||
|
||||
build/main.o(.literal* .text*)
|
||||
*gccollect.o(.literal* .text*)
|
||||
*gchelper.o(.literal* .text*)
|
||||
*help.o(.literal* .text*)
|
||||
*lexerstr32.o(.literal* .text*)
|
||||
*utils.o(.literal* .text*)
|
||||
*modpyb.o(.literal*, .text*)
|
||||
*machine_pin.o(.literal*, .text*)
|
||||
*machine_pwm.o(.literal*, .text*)
|
||||
*machine_rtc.o(.literal*, .text*)
|
||||
*machine_adc.o(.literal*, .text*)
|
||||
*machine_uart.o(.literal*, .text*)
|
||||
*modpybi2c.o(.literal*, .text*)
|
||||
*modmachine.o(.literal*, .text*)
|
||||
*machine_wdt.o(.literal*, .text*)
|
||||
*machine_spi.o(.literal*, .text*)
|
||||
*machine_hspi.o(.literal*, .text*)
|
||||
*hspi.o(.literal*, .text*)
|
||||
*modesp.o(.literal* .text*)
|
||||
*modnetwork.o(.literal* .text*)
|
||||
*moduos.o(.literal* .text*)
|
||||
*modutime.o(.literal* .text*)
|
||||
*modlwip.o(.literal* .text*)
|
||||
*modsocket.o(.literal* .text*)
|
||||
*modonewire.o(.literal* .text*)
|
||||
|
||||
/* we put as much rodata as possible in this section */
|
||||
/* note that only rodata accessed as a machine word is allowed here */
|
||||
*py/qstr.o(.rodata.const_pool)
|
||||
*.o(.rodata.mp_type_*) /* catches type: mp_obj_type_t */
|
||||
*.o(.rodata.*_locals_dict*) /* catches types: mp_obj_dict_t, mp_map_elem_t */
|
||||
*.o(.rodata.mp_module_*) /* catches types: mp_obj_module_t, mp_obj_dict_t, mp_map_elem_t */
|
||||
*/frozen.o(.rodata.mp_frozen_sizes) /* frozen modules */
|
||||
*/frozen.o(.rodata.mp_frozen_content) /* frozen modules */
|
||||
|
||||
/* for -mforce-l32 */
|
||||
build/*.o(.rodata*)
|
||||
|
||||
_irom0_text_end = ABSOLUTE(.);
|
||||
} >irom0_0_seg :irom0_0_phdr
|
||||
|
||||
.text : ALIGN(4)
|
||||
{
|
||||
_stext = .;
|
||||
_text_start = ABSOLUTE(.);
|
||||
*(.UserEnter.text)
|
||||
. = ALIGN(16);
|
||||
*(.DebugExceptionVector.text)
|
||||
. = ALIGN(16);
|
||||
*(.NMIExceptionVector.text)
|
||||
. = ALIGN(16);
|
||||
*(.KernelExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN(16);
|
||||
*(.UserExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN(16);
|
||||
*(.DoubleExceptionVector.text)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
LONG(0)
|
||||
. = ALIGN (16);
|
||||
*(.entry.text)
|
||||
*(.init.literal)
|
||||
*(.init)
|
||||
*(.literal .text .literal.* .text.* .iram0.literal .iram0.text .iram0.text.*.literal .iram0.text.*)
|
||||
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} >iram1_0_seg :iram1_0_phdr
|
||||
|
||||
.lit4 : ALIGN(4)
|
||||
{
|
||||
_lit4_start = ABSOLUTE(.);
|
||||
*(*.lit4)
|
||||
*(.lit4.*)
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
} >iram1_0_seg :iram1_0_phdr
|
||||
|
||||
.data : ALIGN(4)
|
||||
{
|
||||
_data_start = ABSOLUTE(.);
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d.*)
|
||||
*(.data1)
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.gnu.linkonce.s.*)
|
||||
*(.sdata2)
|
||||
*(.sdata2.*)
|
||||
*(.gnu.linkonce.s2.*)
|
||||
*(.jcr)
|
||||
_data_end = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_phdr
|
||||
|
||||
.rodata : ALIGN(4)
|
||||
{
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
*(.sdk.version)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
__XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
|
||||
*(.xt_except_table)
|
||||
*(.gcc_except_table)
|
||||
*(.gnu.linkonce.e.*)
|
||||
*(.gnu.version_r)
|
||||
*(.eh_frame)
|
||||
/* C++ constructor and destructor tables, properly ordered: */
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
/* C++ exception handlers table: */
|
||||
__XT_EXCEPTION_DESCS__ = ABSOLUTE(.);
|
||||
*(.xt_except_desc)
|
||||
*(.gnu.linkonce.h.*)
|
||||
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
|
||||
*(.xt_except_desc_end)
|
||||
*(.dynamic)
|
||||
*(.gnu.version_d)
|
||||
. = ALIGN(4); /* this table MUST be 4-byte aligned */
|
||||
_bss_table_start = ABSOLUTE(.);
|
||||
LONG(_bss_start)
|
||||
LONG(_bss_end)
|
||||
_bss_table_end = ABSOLUTE(.);
|
||||
_rodata_end = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_phdr
|
||||
|
||||
.bss ALIGN(8) (NOLOAD) : ALIGN(4)
|
||||
{
|
||||
. = ALIGN (8);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.gnu.linkonce.sb.*)
|
||||
*(.scommon)
|
||||
*(.sbss2)
|
||||
*(.sbss2.*)
|
||||
*(.gnu.linkonce.sb2.*)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
. = ALIGN (8);
|
||||
_bss_end = ABSOLUTE(.);
|
||||
_heap_start = ABSOLUTE(.);
|
||||
} >dram0_0_seg :dram0_0_bss_phdr
|
||||
}
|
||||
|
||||
/* get ROM code address */
|
||||
INCLUDE "eagle.rom.addr.v6.ld"
|
@ -31,9 +31,6 @@
|
||||
#include "user_interface.h"
|
||||
#include "extmod/misc.h"
|
||||
|
||||
uint32_t SPIRead(uint32_t offset, void *buf, uint32_t len);
|
||||
uint32_t SPIWrite(uint32_t offset, const void *buf, uint32_t len);
|
||||
uint32_t SPIEraseSector(int sector);
|
||||
NORETURN void call_user_start(void);
|
||||
void ets_printf(const char *fmt, ...);
|
||||
extern char flashchip;
|
||||
|
@ -75,9 +75,11 @@ void ets_event_poll(void);
|
||||
// C-level pin HAL
|
||||
#include "etshal.h"
|
||||
#include "gpio.h"
|
||||
#include "esp8266/modpyb.h"
|
||||
#include "esp8266/modmachine.h"
|
||||
#define MP_HAL_PIN_FMT "%u"
|
||||
#define mp_hal_pin_obj_t uint32_t
|
||||
#define mp_hal_get_pin_obj(o) mp_obj_get_pin(o)
|
||||
#define mp_hal_pin_name(p) (p)
|
||||
void mp_hal_pin_input(mp_hal_pin_obj_t pin);
|
||||
void mp_hal_pin_output(mp_hal_pin_obj_t pin);
|
||||
void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin);
|
||||
|
@ -33,7 +33,7 @@ void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32
|
||||
#ifdef NEO_KHZ400
|
||||
if(is800KHz) {
|
||||
#endif
|
||||
time0 = fcpu / 2500000; // 0.4us
|
||||
time0 = fcpu / 2857143; // 0.35us
|
||||
time1 = fcpu / 1250000; // 0.8us
|
||||
period = fcpu / 800000; // 1.25us per bit
|
||||
#ifdef NEO_KHZ400
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
#include "etshal.h"
|
||||
#include "user_interface.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
#include "esponewire.h"
|
||||
|
||||
#define TIMING_RESET1 (0)
|
||||
|
@ -24,7 +24,9 @@ extern void ets_wdt_disable(void);
|
||||
extern void wdt_feed(void);
|
||||
|
||||
// Opaque structure
|
||||
typedef char MD5_CTX[64];
|
||||
#ifndef MD5_CTX
|
||||
typedef char MD5_CTX[88];
|
||||
#endif
|
||||
|
||||
void MD5Init(MD5_CTX *context);
|
||||
void MD5Update(MD5_CTX *context, const void *data, unsigned int len);
|
||||
@ -36,4 +38,8 @@ void *pvPortZalloc(unsigned sz, const char *fname, int line);
|
||||
void *pvPortRealloc(void *p, unsigned sz, const char *fname, int line);
|
||||
void vPortFree(void *p, const char *fname, int line);
|
||||
|
||||
uint32_t SPIRead(uint32_t offset, void *buf, uint32_t len);
|
||||
uint32_t SPIWrite(uint32_t offset, const void *buf, uint32_t len);
|
||||
uint32_t SPIEraseSector(int sector);
|
||||
|
||||
#endif // _INCLUDED_ETSHAL_H_
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "py/obj.h"
|
||||
#include "lib/fatfs/ff.h"
|
||||
#include "timeutils.h"
|
||||
#include "modpybrtc.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
DWORD get_fattime(void) {
|
||||
|
||||
|
@ -46,6 +46,11 @@ void gc_collect(void) {
|
||||
// trace the stack, including the registers (since they live on the stack in this function)
|
||||
gc_collect_root((void**)sp, (STACK_END - sp) / sizeof(uint32_t));
|
||||
|
||||
#if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA
|
||||
// trace any native code because it can contain pointers to the heap
|
||||
esp_native_code_gc_collect();
|
||||
#endif
|
||||
|
||||
// end the GC
|
||||
gc_collect_end();
|
||||
}
|
||||
|
@ -38,3 +38,4 @@ extern uint32_t _heap_start;
|
||||
extern uint32_t _heap_end;
|
||||
|
||||
void gc_collect(void);
|
||||
void esp_native_code_gc_collect(void);
|
||||
|
@ -24,11 +24,9 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "py/builtin.h"
|
||||
|
||||
#include "lib/utils/pyhelp.h"
|
||||
|
||||
STATIC const char *help_text =
|
||||
const char *esp_help_text =
|
||||
"Welcome to MicroPython!\n"
|
||||
"\n"
|
||||
"For online docs please visit http://docs.micropython.org/en/latest/esp8266/ .\n"
|
||||
@ -54,17 +52,3 @@ STATIC const char *help_text =
|
||||
"\n"
|
||||
"For further help on a specific object, type help(obj)\n"
|
||||
;
|
||||
|
||||
STATIC mp_obj_t builtin_help(uint n_args, const mp_obj_t *args) {
|
||||
if (n_args == 0) {
|
||||
// print a general help message
|
||||
printf("%s", help_text);
|
||||
|
||||
} else {
|
||||
// try to print something sensible about the given object
|
||||
pyhelp_print_obj(args[0]);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj, 0, 1, builtin_help);
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "etshal.h"
|
||||
#include "ets_alt_task.h"
|
||||
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
// this is in a separate file so it can go in iRAM
|
||||
void pin_intr_handler_iram(void *arg) {
|
||||
|
@ -35,10 +35,11 @@ typedef struct _mp_lexer_str32_buf_t {
|
||||
uint8_t byte_off;
|
||||
} mp_lexer_str32_buf_t;
|
||||
|
||||
STATIC mp_uint_t str32_buf_next_byte(mp_lexer_str32_buf_t *sb) {
|
||||
STATIC mp_uint_t str32_buf_next_byte(void *sb_in) {
|
||||
mp_lexer_str32_buf_t *sb = (mp_lexer_str32_buf_t*)sb_in;
|
||||
byte c = sb->val & 0xff;
|
||||
if (c == 0) {
|
||||
return MP_LEXER_EOF;
|
||||
return MP_READER_EOF;
|
||||
}
|
||||
|
||||
if (++sb->byte_off > 3) {
|
||||
@ -51,7 +52,8 @@ STATIC mp_uint_t str32_buf_next_byte(mp_lexer_str32_buf_t *sb) {
|
||||
return c;
|
||||
}
|
||||
|
||||
STATIC void str32_buf_free(mp_lexer_str32_buf_t *sb) {
|
||||
STATIC void str32_buf_free(void *sb_in) {
|
||||
mp_lexer_str32_buf_t *sb = (mp_lexer_str32_buf_t*)sb_in;
|
||||
m_del_obj(mp_lexer_str32_buf_t, sb);
|
||||
}
|
||||
|
||||
@ -63,7 +65,8 @@ mp_lexer_t *mp_lexer_new_from_str32(qstr src_name, const char *str, mp_uint_t le
|
||||
sb->byte_off = (uint32_t)str & 3;
|
||||
sb->src_cur = (uint32_t*)(str - sb->byte_off);
|
||||
sb->val = *sb->src_cur++ >> sb->byte_off * 8;
|
||||
return mp_lexer_new(src_name, sb, (mp_lexer_stream_next_byte_t)str32_buf_next_byte, (mp_lexer_stream_close_t)str32_buf_free);
|
||||
mp_reader_t reader = {sb, str32_buf_next_byte, str32_buf_free};
|
||||
return mp_lexer_new(src_name, reader);
|
||||
}
|
||||
|
||||
#endif // MICROPY_ENABLE_COMPILER
|
||||
|
@ -42,7 +42,7 @@ typedef struct _pyb_adc_obj_t {
|
||||
STATIC pyb_adc_obj_t pyb_adc_vdd3 = {{&pyb_adc_type}, true};
|
||||
STATIC pyb_adc_obj_t pyb_adc_adc = {{&pyb_adc_type}, false};
|
||||
|
||||
STATIC mp_obj_t pyb_adc_make_new(const mp_obj_type_t *type_in, mp_uint_t n_args, mp_uint_t n_kw,
|
||||
STATIC mp_obj_t pyb_adc_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw,
|
||||
const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, 1, false);
|
||||
|
@ -36,21 +36,17 @@
|
||||
#include "py/stream.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/machine_spi.h"
|
||||
|
||||
#include "modmachine.h"
|
||||
#include "hspi.h"
|
||||
|
||||
mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args,
|
||||
size_t n_kw, const mp_obj_t *args);
|
||||
|
||||
typedef struct _pyb_hspi_obj_t {
|
||||
typedef struct _machine_hspi_obj_t {
|
||||
mp_obj_base_t base;
|
||||
uint32_t baudrate;
|
||||
uint8_t polarity;
|
||||
uint8_t phase;
|
||||
} pyb_hspi_obj_t;
|
||||
} machine_hspi_obj_t;
|
||||
|
||||
|
||||
STATIC void hspi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
|
||||
STATIC void machine_hspi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
|
||||
(void)self_in;
|
||||
|
||||
if (dest == NULL) {
|
||||
@ -93,16 +89,17 @@ STATIC void hspi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src
|
||||
/******************************************************************************/
|
||||
// MicroPython bindings for HSPI
|
||||
|
||||
STATIC void pyb_hspi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
pyb_hspi_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
STATIC void machine_hspi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_hspi_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "HSPI(id=1, baudrate=%u, polarity=%u, phase=%u)",
|
||||
self->baudrate, self->polarity, self->phase);
|
||||
}
|
||||
|
||||
STATIC void pyb_hspi_init_helper(pyb_hspi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase };
|
||||
STATIC void machine_hspi_init(mp_obj_base_t *self_in, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
machine_hspi_obj_t *self = (machine_hspi_obj_t*)self_in;
|
||||
|
||||
enum { ARG_baudrate, ARG_polarity, ARG_phase };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} },
|
||||
@ -150,63 +147,35 @@ STATIC void pyb_hspi_init_helper(pyb_hspi_obj_t *self, size_t n_args, const mp_o
|
||||
spi_mode(HSPI, self->phase, self->polarity);
|
||||
}
|
||||
|
||||
mp_obj_t pyb_hspi_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, 0, 1, true);
|
||||
mp_int_t id = -1;
|
||||
if (n_args > 0) {
|
||||
id = mp_obj_get_int(args[0]);
|
||||
}
|
||||
|
||||
if (id == -1) {
|
||||
// Multiplex to bitbanging SPI
|
||||
if (n_args > 0) {
|
||||
args++;
|
||||
}
|
||||
return pyb_spi_make_new(type, 0, n_kw, args);
|
||||
}
|
||||
|
||||
if (id != 1) {
|
||||
mp_obj_t machine_hspi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
// args[0] holds the id of the peripheral
|
||||
if (args[0] != MP_OBJ_NEW_SMALL_INT(1)) {
|
||||
// FlashROM is on SPI0, so far we don't support its usage
|
||||
mp_raise_ValueError("");
|
||||
}
|
||||
|
||||
pyb_hspi_obj_t *self = m_new_obj(pyb_hspi_obj_t);
|
||||
self->base.type = &pyb_hspi_type;
|
||||
machine_hspi_obj_t *self = m_new_obj(machine_hspi_obj_t);
|
||||
self->base.type = &machine_hspi_type;
|
||||
// set defaults
|
||||
self->baudrate = 80000000L;
|
||||
self->polarity = 0;
|
||||
self->phase = 0;
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
pyb_hspi_init_helper(self, n_args, args, &kw_args);
|
||||
machine_hspi_init((mp_obj_base_t*)self, n_args - 1, args + 1, &kw_args);
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_hspi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
pyb_hspi_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_hspi_init_obj, 1, pyb_hspi_init);
|
||||
|
||||
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(&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 const mp_machine_spi_p_t machine_hspi_p = {
|
||||
.init = machine_hspi_init,
|
||||
.transfer = machine_hspi_transfer,
|
||||
};
|
||||
|
||||
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 = {
|
||||
const mp_obj_type_t machine_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,
|
||||
.print = machine_hspi_print,
|
||||
.make_new = mp_machine_spi_make_new, // delegate to master constructor
|
||||
.protocol = &machine_hspi_p,
|
||||
.locals_dict = (mp_obj_dict_t*)&mp_machine_spi_locals_dict,
|
||||
};
|
@ -37,7 +37,7 @@
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/mphal.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
#define GET_TRIGGER(phys_port) \
|
||||
GPIO_PIN_INT_TYPE_GET(GPIO_REG_READ(GPIO_PIN_ADDR(phys_port)))
|
||||
@ -276,7 +276,7 @@ STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, mp_uint_t n_args, c
|
||||
}
|
||||
|
||||
// constructor(id, ...)
|
||||
STATIC mp_obj_t pyb_pin_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t pyb_pin_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, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
|
||||
// get the wanted pin object
|
||||
@ -300,7 +300,7 @@ STATIC mp_obj_t pyb_pin_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp
|
||||
}
|
||||
|
||||
// fast method for getting/setting pin value
|
||||
STATIC mp_obj_t pyb_pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t pyb_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
pyb_pin_obj_t *self = self_in;
|
||||
if (n_args == 0) {
|
@ -31,7 +31,7 @@
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
typedef struct _pyb_pwm_obj_t {
|
||||
mp_obj_base_t base;
|
@ -32,7 +32,7 @@
|
||||
#include "py/runtime.h"
|
||||
#include "timeutils.h"
|
||||
#include "user_interface.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
typedef struct _pyb_rtc_obj_t {
|
||||
mp_obj_base_t base;
|
||||
@ -78,7 +78,7 @@ void mp_hal_rtc_init(void) {
|
||||
pyb_rtc_alarm0_expiry = 0;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 0, 0, false);
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
// UartDev is defined and initialized in rom code.
|
||||
extern UartDevice UartDev;
|
||||
@ -197,7 +197,6 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) },
|
||||
|
||||
{ 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_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
|
@ -41,7 +41,7 @@ typedef struct _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) {
|
||||
STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
|
||||
mp_int_t id = 0;
|
@ -39,7 +39,7 @@
|
||||
#include "gccollect.h"
|
||||
#include "user_interface.h"
|
||||
|
||||
STATIC char heap[28 * 1024];
|
||||
STATIC char heap[36 * 1024];
|
||||
|
||||
STATIC void mp_reset(void) {
|
||||
mp_stack_set_top((void*)0x40000000);
|
||||
@ -52,12 +52,12 @@ STATIC void mp_reset(void) {
|
||||
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib));
|
||||
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_));
|
||||
mp_obj_list_init(mp_sys_argv, 0);
|
||||
#if MICROPY_VFS_FAT
|
||||
memset(MP_STATE_PORT(fs_user_mount), 0, sizeof(MP_STATE_PORT(fs_user_mount)));
|
||||
#endif
|
||||
MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
|
||||
MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
|
||||
MP_STATE_PORT(dupterm_arr_obj) = MP_OBJ_NULL;
|
||||
#if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA
|
||||
extern void esp_native_code_init(void);
|
||||
esp_native_code_init();
|
||||
#endif
|
||||
pin_init0();
|
||||
readline_init0();
|
||||
dupterm_task_init();
|
||||
@ -109,17 +109,13 @@ void user_init(void) {
|
||||
system_init_done_cb(init_done);
|
||||
}
|
||||
|
||||
mp_lexer_t *fat_vfs_lexer_new_from_file(const char *filename);
|
||||
mp_import_stat_t fat_vfs_import_stat(const char *path);
|
||||
|
||||
#if !MICROPY_VFS_FAT
|
||||
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
|
||||
#if MICROPY_VFS_FAT
|
||||
return fat_vfs_lexer_new_from_file(filename);
|
||||
#else
|
||||
(void)filename;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_import_stat_t mp_import_stat(const char *path) {
|
||||
#if MICROPY_VFS_FAT
|
||||
|
139
esp8266/modesp.c
139
esp8266/modesp.c
@ -45,8 +45,7 @@
|
||||
#include "mem.h"
|
||||
#include "espneopixel.h"
|
||||
#include "espapa102.h"
|
||||
#include "modpyb.h"
|
||||
#include "modpybrtc.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
#define MODESP_ESPCONN (0)
|
||||
|
||||
@ -629,17 +628,35 @@ STATIC mp_obj_t esp_flash_size(void) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size);
|
||||
|
||||
// If there's just 1 loadable segment at the start of flash,
|
||||
// we assume there's a yaota8266 bootloader.
|
||||
#define IS_OTA_FIRMWARE() ((*(uint32_t*)0x40200000 & 0xff00) == 0x100)
|
||||
|
||||
STATIC mp_obj_t esp_flash_user_start(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(0x90000);
|
||||
if (IS_OTA_FIRMWARE()) {
|
||||
return MP_OBJ_NEW_SMALL_INT(0x3c000 + 0x90000);
|
||||
} else {
|
||||
return MP_OBJ_NEW_SMALL_INT(0x90000);
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_user_start_obj, esp_flash_user_start);
|
||||
|
||||
STATIC mp_obj_t esp_check_fw(void) {
|
||||
MD5_CTX ctx;
|
||||
uint32_t *sz_p = (uint32_t*)0x40208ffc;
|
||||
printf("size: %d\n", *sz_p);
|
||||
char *fw_start = (char*)0x40200000;
|
||||
if (IS_OTA_FIRMWARE()) {
|
||||
// Skip yaota8266 bootloader
|
||||
fw_start += 0x3c000;
|
||||
}
|
||||
|
||||
uint32_t size = *(uint32_t*)(fw_start + 0x8ffc);
|
||||
printf("size: %d\n", size);
|
||||
if (size > 1024 * 1024) {
|
||||
printf("Invalid size\n");
|
||||
return mp_const_false;
|
||||
}
|
||||
MD5Init(&ctx);
|
||||
MD5Update(&ctx, (char*)0x40200004, *sz_p - 4);
|
||||
MD5Update(&ctx, fw_start + 4, size - 4);
|
||||
unsigned char digest[16];
|
||||
MD5Final(digest, &ctx);
|
||||
printf("md5: ");
|
||||
@ -647,7 +664,7 @@ STATIC mp_obj_t esp_check_fw(void) {
|
||||
printf("%02x", digest[i]);
|
||||
}
|
||||
printf("\n");
|
||||
return mp_obj_new_bool(memcmp(digest, (void*)(0x40200000 + *sz_p), sizeof(digest)) == 0);
|
||||
return mp_obj_new_bool(memcmp(digest, fw_start + size, sizeof(digest)) == 0);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_check_fw_obj, esp_check_fw);
|
||||
|
||||
@ -700,6 +717,111 @@ STATIC mp_obj_t esp_esf_free_bufs(mp_obj_t idx_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_esf_free_bufs_obj, esp_esf_free_bufs);
|
||||
|
||||
#if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA
|
||||
|
||||
// We provide here a way of committing executable data to a region from
|
||||
// which it can be executed by the CPU. There are 2 such writable regions:
|
||||
// - iram1, which may have some space left at the end of it
|
||||
// - memory-mapped flash rom
|
||||
//
|
||||
// By default the iram1 region (the space at the end of it) is used. The
|
||||
// user can select iram1 or a section of flash by calling the
|
||||
// esp.set_native_code_location() function; see below. If flash is selected
|
||||
// then it is erased as needed.
|
||||
|
||||
#include "gccollect.h"
|
||||
|
||||
#define IRAM1_END (0x40108000)
|
||||
#define FLASH_START (0x40200000)
|
||||
#define FLASH_END (0x40300000)
|
||||
#define FLASH_SEC_SIZE (4096)
|
||||
|
||||
#define ESP_NATIVE_CODE_IRAM1 (0)
|
||||
#define ESP_NATIVE_CODE_FLASH (1)
|
||||
|
||||
extern uint32_t _lit4_end;
|
||||
STATIC uint32_t esp_native_code_location;
|
||||
STATIC uint32_t esp_native_code_start;
|
||||
STATIC uint32_t esp_native_code_end;
|
||||
STATIC uint32_t esp_native_code_cur;
|
||||
STATIC uint32_t esp_native_code_erased;
|
||||
|
||||
void esp_native_code_init(void) {
|
||||
esp_native_code_location = ESP_NATIVE_CODE_IRAM1;
|
||||
esp_native_code_start = (uint32_t)&_lit4_end;
|
||||
esp_native_code_end = IRAM1_END;
|
||||
esp_native_code_cur = esp_native_code_start;
|
||||
esp_native_code_erased = 0;
|
||||
}
|
||||
|
||||
void esp_native_code_gc_collect(void) {
|
||||
void *src;
|
||||
if (esp_native_code_location == ESP_NATIVE_CODE_IRAM1) {
|
||||
src = (void*)esp_native_code_start;
|
||||
} else {
|
||||
src = (void*)(FLASH_START + esp_native_code_start);
|
||||
}
|
||||
gc_collect_root(src, (esp_native_code_end - esp_native_code_start) / sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void *esp_native_code_commit(void *buf, size_t len) {
|
||||
//printf("COMMIT(buf=%p, len=%u, start=%08x, cur=%08x, end=%08x, erased=%08x)\n", buf, len, esp_native_code_start, esp_native_code_cur, esp_native_code_end, esp_native_code_erased);
|
||||
|
||||
len = (len + 3) & ~3;
|
||||
if (esp_native_code_cur + len > esp_native_code_end) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError,
|
||||
"memory allocation failed, allocating %u bytes for native code", (uint)len));
|
||||
}
|
||||
|
||||
void *dest;
|
||||
if (esp_native_code_location == ESP_NATIVE_CODE_IRAM1) {
|
||||
dest = (void*)esp_native_code_cur;
|
||||
memcpy(dest, buf, len);
|
||||
} else {
|
||||
SpiFlashOpResult res;
|
||||
while (esp_native_code_erased < esp_native_code_cur + len) {
|
||||
res = spi_flash_erase_sector(esp_native_code_erased / FLASH_SEC_SIZE);
|
||||
if (res != SPI_FLASH_RESULT_OK) {
|
||||
break;
|
||||
}
|
||||
esp_native_code_erased += FLASH_SEC_SIZE;
|
||||
}
|
||||
if (res == SPI_FLASH_RESULT_OK) {
|
||||
res = spi_flash_write(esp_native_code_cur, buf, len);
|
||||
}
|
||||
if (res != SPI_FLASH_RESULT_OK) {
|
||||
mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO);
|
||||
}
|
||||
dest = (void*)(FLASH_START + esp_native_code_cur);
|
||||
}
|
||||
|
||||
esp_native_code_cur += len;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t esp_set_native_code_location(mp_obj_t start_in, mp_obj_t len_in) {
|
||||
if (start_in == mp_const_none && len_in == mp_const_none) {
|
||||
// use end of iram1 region
|
||||
esp_native_code_init();
|
||||
} else {
|
||||
// use flash; input params are byte offsets from start of flash
|
||||
esp_native_code_location = ESP_NATIVE_CODE_FLASH;
|
||||
esp_native_code_start = mp_obj_get_int(start_in);
|
||||
esp_native_code_end = esp_native_code_start + mp_obj_get_int(len_in);
|
||||
esp_native_code_cur = esp_native_code_start;
|
||||
esp_native_code_erased = esp_native_code_start;
|
||||
// memory-mapped flash is limited in extents to 1MByte
|
||||
if (esp_native_code_end > FLASH_END - FLASH_START) {
|
||||
mp_raise_ValueError("flash location must be below 1MByte");
|
||||
}
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_set_native_code_location_obj, esp_set_native_code_location);
|
||||
|
||||
#endif
|
||||
|
||||
STATIC const mp_map_elem_t esp_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_esp) },
|
||||
|
||||
@ -730,6 +852,9 @@ STATIC const mp_map_elem_t esp_module_globals_table[] = {
|
||||
{ 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 },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_esf_free_bufs), (mp_obj_t)&esp_esf_free_bufs_obj },
|
||||
#if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_native_code_location), (mp_obj_t)&esp_set_native_code_location_obj },
|
||||
#endif
|
||||
|
||||
#if MODESP_INCLUDE_CONSTANTS
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP_NONE),
|
||||
|
@ -33,8 +33,7 @@
|
||||
#include "extmod/machine_mem.h"
|
||||
#include "extmod/machine_pulse.h"
|
||||
#include "extmod/machine_i2c.h"
|
||||
#include "modpyb.h"
|
||||
#include "modpybrtc.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
#include "xtirq.h"
|
||||
#include "os_type.h"
|
||||
@ -148,7 +147,7 @@ STATIC void esp_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_
|
||||
mp_printf(print, "Timer(%p)", &self->timer);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t esp_timer_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t esp_timer_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);
|
||||
esp_timer_obj_t *tim = m_new_obj(esp_timer_obj_t);
|
||||
tim->base.type = &esp_timer_type;
|
||||
@ -256,7 +255,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_hspi_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hspi_type) },
|
||||
|
||||
// wake abilities
|
||||
{ MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(MACHINE_WAKE_DEEPSLEEP) },
|
||||
|
@ -9,9 +9,7 @@ extern const mp_obj_type_t pyb_adc_type;
|
||||
extern const mp_obj_type_t pyb_rtc_type;
|
||||
extern const mp_obj_type_t pyb_uart_type;
|
||||
extern const mp_obj_type_t pyb_i2c_type;
|
||||
extern const mp_obj_type_t pyb_spi_type;
|
||||
extern const mp_obj_type_t pyb_hspi_type;
|
||||
extern const mp_obj_type_t machine_spi_type;
|
||||
extern const mp_obj_type_t machine_hspi_type;
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj);
|
||||
|
||||
@ -33,4 +31,11 @@ pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in);
|
||||
int pin_get(uint pin);
|
||||
void pin_set(uint pin, int value);
|
||||
|
||||
extern uint32_t pyb_rtc_alarm0_wake;
|
||||
extern uint64_t pyb_rtc_alarm0_expiry;
|
||||
|
||||
void pyb_rtc_set_us_since_2000(uint64_t nowus);
|
||||
uint64_t pyb_rtc_get_us_since_2000();
|
||||
void rtc_prepare_deepsleep(uint64_t sleep_us);
|
||||
|
||||
#endif // __MICROPY_INCLUDED_ESP8266_MODPYB_H__
|
@ -100,17 +100,23 @@ STATIC mp_obj_t esp_connect(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
mp_uint_t len;
|
||||
const char *p;
|
||||
|
||||
p = mp_obj_str_get_data(args[1], &len);
|
||||
memcpy(config.ssid, p, len);
|
||||
p = mp_obj_str_get_data(args[2], &len);
|
||||
memcpy(config.password, p, len);
|
||||
if (n_args > 1) {
|
||||
p = mp_obj_str_get_data(args[1], &len);
|
||||
memcpy(config.ssid, p, len);
|
||||
if (n_args > 2) {
|
||||
p = mp_obj_str_get_data(args[2], &len);
|
||||
} else {
|
||||
p = "";
|
||||
}
|
||||
memcpy(config.password, p, len);
|
||||
|
||||
error_check(wifi_station_set_config(&config), "Cannot set STA config");
|
||||
error_check(wifi_station_set_config(&config), "Cannot set STA config");
|
||||
}
|
||||
error_check(wifi_station_connect(), "Cannot connect to AP");
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_connect_obj, 3, 7, esp_connect);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_connect_obj, 1, 7, esp_connect);
|
||||
|
||||
STATIC mp_obj_t esp_disconnect(mp_obj_t self_in) {
|
||||
require_if(self_in, STATION_IF);
|
||||
@ -336,6 +342,14 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
|
||||
cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value);
|
||||
break;
|
||||
}
|
||||
case QS(MP_QSTR_dhcp_hostname): {
|
||||
req_if = STATION_IF;
|
||||
if (self->if_id == STATION_IF) {
|
||||
const char *s = mp_obj_str_get_str(kwargs->table[i].value);
|
||||
wifi_station_set_hostname((char*)s);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto unknown;
|
||||
}
|
||||
@ -389,6 +403,12 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
|
||||
req_if = SOFTAP_IF;
|
||||
val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel);
|
||||
break;
|
||||
case QS(MP_QSTR_dhcp_hostname): {
|
||||
req_if = STATION_IF;
|
||||
char* s = wifi_station_get_hostname();
|
||||
val = mp_obj_new_str(s, strlen(s), false);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto unknown;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/mphal.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
#include "esponewire.h"
|
||||
|
||||
STATIC mp_obj_t onewire_timings(mp_obj_t timings_in) {
|
||||
|
@ -28,12 +28,12 @@
|
||||
|
||||
#include "py/gc.h"
|
||||
#include "gccollect.h"
|
||||
#include "modpyb.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
// The pyb module no longer exists since all functionality now appears
|
||||
// elsewhere, in more standard places (eg time, machine modules). The
|
||||
// only remaining function is pyb.info() which has been moved to the
|
||||
// esp module, pending deletion/renaming/moving elsewher.
|
||||
// esp module, pending deletion/renaming/moving elsewhere.
|
||||
|
||||
STATIC mp_obj_t pyb_info(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
// print info about memory
|
||||
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 Josef Gajdusek
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
extern uint32_t pyb_rtc_alarm0_wake;
|
||||
extern uint64_t pyb_rtc_alarm0_expiry;
|
||||
|
||||
void pyb_rtc_set_us_since_2000(uint64_t nowus);
|
||||
|
||||
uint64_t pyb_rtc_get_us_since_2000();
|
||||
|
||||
void rtc_prepare_deepsleep(uint64_t sleep_us);
|
@ -1,142 +0,0 @@
|
||||
/*
|
||||
* 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 <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/machine_spi.h"
|
||||
|
||||
/******************************************************************************/
|
||||
// MicroPython bindings for SPI
|
||||
|
||||
STATIC uint32_t baudrate_from_delay_half(uint32_t delay_half) {
|
||||
return 500000 / delay_half;
|
||||
}
|
||||
|
||||
STATIC uint32_t baudrate_to_delay_half(uint32_t baudrate) {
|
||||
uint32_t delay_half = 500000 / baudrate;
|
||||
// round delay_half up so that: actual_baudrate <= requested_baudrate
|
||||
if (500000 % baudrate != 0) {
|
||||
delay_half += 1;
|
||||
}
|
||||
return delay_half;
|
||||
}
|
||||
|
||||
STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
mp_machine_soft_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "SPI(baudrate=%u, polarity=%u, phase=%u, sck=%u, mosi=%u, miso=%u)",
|
||||
baudrate_from_delay_half(self->delay_half),
|
||||
self->polarity, self->phase, self->sck, self->mosi, self->miso);
|
||||
}
|
||||
|
||||
STATIC void pyb_spi_init_helper(mp_machine_soft_spi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_baudrate, ARG_polarity, ARG_phase, ARG_sck, ARG_mosi, ARG_miso };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_sck, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_mosi, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_miso, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
};
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
if (args[ARG_baudrate].u_int != -1) {
|
||||
self->delay_half = baudrate_to_delay_half(args[ARG_baudrate].u_int);
|
||||
}
|
||||
if (args[ARG_polarity].u_int != -1) {
|
||||
self->polarity = args[ARG_polarity].u_int;
|
||||
}
|
||||
if (args[ARG_phase].u_int != -1) {
|
||||
self->phase = args[ARG_phase].u_int;
|
||||
}
|
||||
if (args[ARG_sck].u_obj != MP_OBJ_NULL) {
|
||||
self->sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj);
|
||||
}
|
||||
if (args[ARG_mosi].u_obj != MP_OBJ_NULL) {
|
||||
self->mosi = mp_hal_get_pin_obj(args[ARG_mosi].u_obj);
|
||||
}
|
||||
if (args[ARG_miso].u_obj != MP_OBJ_NULL) {
|
||||
self->miso = mp_hal_get_pin_obj(args[ARG_miso].u_obj);
|
||||
}
|
||||
|
||||
// configure pins
|
||||
mp_hal_pin_write(self->sck, self->polarity);
|
||||
mp_hal_pin_output(self->sck);
|
||||
mp_hal_pin_output(self->mosi);
|
||||
mp_hal_pin_input(self->miso);
|
||||
}
|
||||
|
||||
mp_obj_t pyb_spi_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, 0, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
mp_machine_soft_spi_obj_t *self = m_new_obj(mp_machine_soft_spi_obj_t);
|
||||
self->base.type = &pyb_spi_type;
|
||||
// set defaults
|
||||
self->delay_half = baudrate_to_delay_half(500000);
|
||||
self->polarity = 0;
|
||||
self->phase = 0;
|
||||
self->sck = 14;
|
||||
self->mosi = 13;
|
||||
self->miso = 12;
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
pyb_spi_init_helper(self, n_args, args, &kw_args);
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_spi_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
pyb_spi_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_init_obj, 1, pyb_spi_init);
|
||||
|
||||
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(&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_machine_soft_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,
|
||||
};
|
@ -1,6 +1,8 @@
|
||||
# DS18x20 temperature sensor driver for MicroPython.
|
||||
# MIT license; Copyright (c) 2016 Damien P. George
|
||||
|
||||
from micropython import const
|
||||
|
||||
_CONVERT = const(0x44)
|
||||
_RD_SCRATCH = const(0xbe)
|
||||
_WR_SCRATCH = const(0x4e)
|
||||
@ -43,4 +45,7 @@ class DS18X20:
|
||||
t = buf[0] >> 1
|
||||
return t - 0.25 + (buf[7] - buf[6]) / buf[7]
|
||||
else:
|
||||
return (buf[1] << 8 | buf[0]) / 16
|
||||
t = buf[1] << 8 | buf[0]
|
||||
if t & 0x8000: # sign bit set
|
||||
t = -((t ^ 0xffff) + 1)
|
||||
return t / 16
|
||||
|
@ -3,8 +3,9 @@ import esp
|
||||
class FlashBdev:
|
||||
|
||||
SEC_SIZE = 4096
|
||||
START_SEC = esp.flash_user_start() // SEC_SIZE
|
||||
NUM_BLK = 0x6b
|
||||
RESERVED_SECS = 0
|
||||
START_SEC = esp.flash_user_start() // SEC_SIZE + RESERVED_SECS
|
||||
NUM_BLK = 0x6b - RESERVED_SECS
|
||||
|
||||
def __init__(self, blocks=NUM_BLK):
|
||||
self.blocks = blocks
|
||||
@ -26,40 +27,6 @@ class FlashBdev:
|
||||
if op == 5: # BP_IOCTL_SEC_SIZE
|
||||
return self.SEC_SIZE
|
||||
|
||||
def set_bl_flash_size(real_size):
|
||||
if real_size == 256*1024:
|
||||
code = 1
|
||||
elif real_size == 512*1024:
|
||||
code = 0
|
||||
elif real_size == 1024*1024:
|
||||
code = 2
|
||||
elif real_size == 2048*1024:
|
||||
code = 3
|
||||
elif real_size == 4096*1024:
|
||||
code = 4
|
||||
else:
|
||||
code = 2
|
||||
buf = bytearray(4096)
|
||||
esp.flash_read(0, buf)
|
||||
buf[3] = (buf[3] & 0xf) | (code << 4)
|
||||
esp.flash_erase(0)
|
||||
esp.flash_write(0, buf)
|
||||
|
||||
# If bootloader size ID doesn't correspond to real Flash size,
|
||||
# fix bootloader value and reboot.
|
||||
size = esp.flash_id() >> 16
|
||||
# Check that it looks like realistic power of 2 for flash sizes
|
||||
# commonly used with esp8266
|
||||
if 22 >= size >= 18:
|
||||
size = 1 << size
|
||||
if size != esp.flash_size():
|
||||
import machine
|
||||
import time
|
||||
print("Bootloader Flash size appear to have been set incorrectly, trying to fix")
|
||||
set_bl_flash_size(size)
|
||||
machine.reset()
|
||||
while 1: time.sleep(1)
|
||||
|
||||
size = esp.flash_size()
|
||||
if size < 1024*1024:
|
||||
bdev = None
|
||||
|
@ -1,6 +1,7 @@
|
||||
# 1-Wire driver for MicroPython on ESP8266
|
||||
# MIT license; Copyright (c) 2016 Damien P. George
|
||||
|
||||
from micropython import const
|
||||
import _onewire as _ow
|
||||
|
||||
class OneWireError(Exception):
|
||||
|
1
esp8266/modules/upip.py
Symbolic link
1
esp8266/modules/upip.py
Symbolic link
@ -0,0 +1 @@
|
||||
../../tools/upip.py
|
1
esp8266/modules/upip_utarfile.py
Symbolic link
1
esp8266/modules/upip_utarfile.py
Symbolic link
@ -0,0 +1 @@
|
||||
../../tools/upip_utarfile.py
|
@ -59,18 +59,16 @@ def start(port=8266, password=None):
|
||||
stop()
|
||||
if password is None:
|
||||
try:
|
||||
import port_config
|
||||
_webrepl.password(port_config.WEBREPL_PASS)
|
||||
import webrepl_cfg
|
||||
_webrepl.password(webrepl_cfg.PASS)
|
||||
setup_conn(port, accept_conn)
|
||||
print("Started webrepl in normal mode")
|
||||
except:
|
||||
import webrepl_setup
|
||||
setup_conn(port, webrepl_setup.handle_conn)
|
||||
print("Started webrepl in setup mode")
|
||||
print("WebREPL is not configured, run 'import webrepl_setup'")
|
||||
else:
|
||||
_webrepl.password(password)
|
||||
setup_conn(port, accept_conn)
|
||||
print("Started webrepl in normal mode")
|
||||
print("Started webrepl in manual override mode")
|
||||
|
||||
|
||||
def start_foreground(port=8266):
|
||||
|
@ -1,83 +1,111 @@
|
||||
import sys
|
||||
import socket
|
||||
import time
|
||||
#import uos as os
|
||||
import os
|
||||
import machine
|
||||
|
||||
from websocket import *
|
||||
import websocket_helper
|
||||
RC = "./boot.py"
|
||||
CONFIG = "./webrepl_cfg.py"
|
||||
|
||||
|
||||
def setup_server():
|
||||
s = socket.socket()
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
ai = socket.getaddrinfo("0.0.0.0", 8266)
|
||||
addr = ai[0][4]
|
||||
|
||||
s.bind(addr)
|
||||
s.listen(1)
|
||||
return s
|
||||
|
||||
def getpass(stream, prompt):
|
||||
stream.write(prompt)
|
||||
passwd = b""
|
||||
def input_choice(prompt, choices):
|
||||
while 1:
|
||||
c = stream.read(1)
|
||||
if c in (b"\r", b"\n"):
|
||||
stream.write("\r\n")
|
||||
return passwd
|
||||
passwd += c
|
||||
stream.write("*")
|
||||
resp = input(prompt)
|
||||
if resp in choices:
|
||||
return resp
|
||||
|
||||
def handle_conn(listen_sock):
|
||||
cl, remote_addr = listen_sock.accept()
|
||||
|
||||
print("""
|
||||
|
||||
First-time WebREPL connection has been received. WebREPL initial setup
|
||||
will now start over this connection. During setup, UART REPL will be
|
||||
non-responsive. After setup finishes, the board will be rebooted. In
|
||||
case of error during setup, current session will continue.
|
||||
|
||||
If you receive this message unexpectedly, it may mean that your WebREPL
|
||||
connection is being hacked (power off board if unsure).
|
||||
""")
|
||||
|
||||
websocket_helper.server_handshake(cl)
|
||||
ws = websocket(cl)
|
||||
|
||||
ws.write("""\
|
||||
Welcome to MicroPython WebREPL!\r
|
||||
\r
|
||||
This is the first time you connect to WebREPL, so please set a password\r
|
||||
to use for the following WebREPL sessions. Once you enter the password\r
|
||||
twice, your board will reboot with WebREPL running in active mode. On\r
|
||||
some boards, you may need to press reset button or reconnect power.\r
|
||||
\r
|
||||
""")
|
||||
def getpass(prompt):
|
||||
return input(prompt)
|
||||
|
||||
def input_pass():
|
||||
while 1:
|
||||
passwd1 = getpass(ws, "New password: ")
|
||||
passwd1 = getpass("New password: ")
|
||||
if len(passwd1) < 4:
|
||||
ws.write("Password too short\r\n")
|
||||
print("Password too short")
|
||||
continue
|
||||
elif len(passwd1) > 9:
|
||||
ws.write("Password too long\r\n")
|
||||
print("Password too long")
|
||||
continue
|
||||
passwd2 = getpass(ws, "Confirm password: ")
|
||||
passwd2 = getpass("Confirm password: ")
|
||||
if passwd1 == passwd2:
|
||||
break
|
||||
ws.write("Passwords do not match\r\n")
|
||||
|
||||
with open("port_config.py", "w") as f:
|
||||
f.write("WEBREPL_PASS = %r\n" % passwd1.decode("ascii"))
|
||||
|
||||
ws.write("Password successfully set, restarting...\r\n")
|
||||
cl.close()
|
||||
time.sleep(2)
|
||||
import machine
|
||||
machine.reset()
|
||||
return passwd1
|
||||
print("Passwords do not match")
|
||||
|
||||
|
||||
def test():
|
||||
s = setup_server()
|
||||
handle_conn(s)
|
||||
def exists(fname):
|
||||
try:
|
||||
with open(fname):
|
||||
pass
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
def copy_stream(s_in, s_out):
|
||||
buf = bytearray(64)
|
||||
while 1:
|
||||
sz = s_in.readinto(buf)
|
||||
s_out.write(buf, sz)
|
||||
|
||||
|
||||
def get_daemon_status():
|
||||
with open(RC) as f:
|
||||
for l in f:
|
||||
if "webrepl" in l:
|
||||
if l.startswith("#"):
|
||||
return False
|
||||
return True
|
||||
return None
|
||||
|
||||
def add_daemon():
|
||||
with open(RC) as old_f, open(RC + ".tmp", "w") as new_f:
|
||||
new_f.write("import webrepl\nwebrepl.start()\n")
|
||||
copy_stream(old_f, new_f)
|
||||
|
||||
def change_daemon(action):
|
||||
LINES = ("import webrepl", "webrepl.start()")
|
||||
with open(RC) as old_f, open(RC + ".tmp", "w") as new_f:
|
||||
for l in old_f:
|
||||
for patt in LINES:
|
||||
if patt in l:
|
||||
if action and l.startswith("#"):
|
||||
l = l[1:]
|
||||
elif not action and not l.startswith("#"):
|
||||
l = "#" + l
|
||||
new_f.write(l)
|
||||
# FatFs rename() is not POSIX compliant, will raise OSError if
|
||||
# dest file exists.
|
||||
os.remove(RC)
|
||||
os.rename(RC + ".tmp", RC)
|
||||
|
||||
|
||||
def main():
|
||||
status = get_daemon_status()
|
||||
|
||||
print("WebREPL daemon auto-start status:", "enabled" if status else "disabled")
|
||||
print("\nWould you like to (E)nable or (D)isable it running on boot?")
|
||||
print("(Empty line to quit)")
|
||||
resp = input("> ").upper()
|
||||
|
||||
if resp == "E":
|
||||
if exists(CONFIG):
|
||||
resp2 = input_choice("Would you like to change WebREPL password? (y/n) ", ("y", "n", ""))
|
||||
else:
|
||||
print("To enable WebREPL, you must set password for it")
|
||||
resp2 = "y"
|
||||
|
||||
if resp2 == "y":
|
||||
passwd = input_pass()
|
||||
with open(CONFIG, "w") as f:
|
||||
f.write("PASS = %r\n" % passwd)
|
||||
|
||||
|
||||
if resp not in ("D", "E") or (resp == "D" and not status) or (resp == "E" and status):
|
||||
print("No further action required")
|
||||
sys.exit()
|
||||
|
||||
change_daemon(resp == "E")
|
||||
|
||||
print("Changes will be activated after reboot")
|
||||
resp = input_choice("Would you like to reboot now? (y/n) ", ("y", "n", ""))
|
||||
if resp == "y":
|
||||
machine.reset()
|
||||
|
||||
main()
|
||||
|
@ -34,8 +34,7 @@
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/smallint.h"
|
||||
#include "modpyb.h"
|
||||
#include "modpybrtc.h"
|
||||
#include "modmachine.h"
|
||||
#include "timeutils.h"
|
||||
#include "user_interface.h"
|
||||
#include "extmod/utime_mphal.h"
|
||||
|
@ -10,15 +10,16 @@
|
||||
#define MICROPY_ALLOC_PARSE_RESULT_INC (8)
|
||||
#define MICROPY_ALLOC_PARSE_CHUNK_INIT (64)
|
||||
#define MICROPY_PERSISTENT_CODE_LOAD (1)
|
||||
#define MICROPY_EMIT_X64 (0)
|
||||
#define MICROPY_EMIT_THUMB (0)
|
||||
#define MICROPY_EMIT_INLINE_THUMB (0)
|
||||
#define MICROPY_EMIT_XTENSA (1)
|
||||
#define MICROPY_EMIT_INLINE_XTENSA (1)
|
||||
#define MICROPY_MEM_STATS (0)
|
||||
#define MICROPY_DEBUG_PRINTERS (1)
|
||||
#define MICROPY_DEBUG_PRINTER_DEST mp_debug_print
|
||||
#define MICROPY_READER_FATFS (MICROPY_VFS_FAT)
|
||||
#define MICROPY_ENABLE_GC (1)
|
||||
#define MICROPY_STACK_CHECK (1)
|
||||
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
|
||||
#define MICROPY_KBD_EXCEPTION (1)
|
||||
#define MICROPY_REPL_EVENT_DRIVEN (0)
|
||||
#define MICROPY_REPL_AUTO_INDENT (1)
|
||||
#define MICROPY_HELPER_REPL (1)
|
||||
@ -37,6 +38,8 @@
|
||||
#define MICROPY_PY_BUILTINS_SLICE (1)
|
||||
#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1)
|
||||
#define MICROPY_PY_BUILTINS_PROPERTY (1)
|
||||
#define MICROPY_PY_BUILTINS_HELP (1)
|
||||
#define MICROPY_PY_BUILTINS_HELP_TEXT esp_help_text
|
||||
#define MICROPY_PY___FILE__ (0)
|
||||
#define MICROPY_PY_GC (1)
|
||||
#define MICROPY_PY_ARRAY (1)
|
||||
@ -59,9 +62,11 @@
|
||||
#define MICROPY_PY_UHASHLIB (1)
|
||||
#define MICROPY_PY_UHASHLIB_SHA1 (MICROPY_PY_USSL && MICROPY_SSL_AXTLS)
|
||||
#define MICROPY_PY_UHEAPQ (1)
|
||||
#define MICROPY_PY_UTIMEQ (1)
|
||||
#define MICROPY_PY_UJSON (1)
|
||||
#define MICROPY_PY_URANDOM (1)
|
||||
#define MICROPY_PY_URE (1)
|
||||
#define MICROPY_PY_USELECT (1)
|
||||
#define MICROPY_PY_UTIME_MP_HAL (1)
|
||||
#define MICROPY_PY_UZLIB (1)
|
||||
#define MICROPY_PY_LWIP (1)
|
||||
@ -69,6 +74,7 @@
|
||||
#define MICROPY_PY_MACHINE_PULSE (1)
|
||||
#define MICROPY_PY_MACHINE_I2C (1)
|
||||
#define MICROPY_PY_MACHINE_SPI (1)
|
||||
#define MICROPY_PY_MACHINE_SPI_MAKE_NEW machine_hspi_make_new
|
||||
#define MICROPY_PY_WEBSOCKET (1)
|
||||
#define MICROPY_PY_WEBREPL (1)
|
||||
#define MICROPY_PY_WEBREPL_DELAY (20)
|
||||
@ -128,13 +134,14 @@ typedef uint32_t sys_prot_t; // for modlwip
|
||||
#include <sys/types.h>
|
||||
|
||||
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
|
||||
void *esp_native_code_commit(void*, size_t);
|
||||
#define MP_PLAT_COMMIT_EXEC(buf, len) esp_native_code_commit(buf, len)
|
||||
|
||||
#define mp_type_fileio fatfs_type_fileio
|
||||
#define mp_type_textio fatfs_type_textio
|
||||
|
||||
// extra built in names to add to the global namespace
|
||||
#define MICROPY_PORT_BUILTINS \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_help), (mp_obj_t)&mp_builtin_help_obj }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_input), (mp_obj_t)&mp_builtin_input_obj }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
|
||||
|
||||
@ -163,13 +170,13 @@ extern const struct _mp_obj_module_t onewire_module;
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&uos_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_errno), (mp_obj_t)&mp_module_uerrno }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_select), (mp_obj_t)&mp_module_uselect }, \
|
||||
|
||||
#define MP_STATE_PORT MP_STATE_VM
|
||||
|
||||
#define MICROPY_PORT_ROOT_POINTERS \
|
||||
const char *readline_hist[8]; \
|
||||
vstr_t *repl_line; \
|
||||
mp_obj_t mp_kbd_exception; \
|
||||
mp_obj_t pin_irq_handler[16]; \
|
||||
|
||||
// We need to provide a declaration/definition of alloca()
|
||||
|
@ -1,5 +1,10 @@
|
||||
#include <mpconfigport.h>
|
||||
|
||||
#undef MICROPY_EMIT_XTENSA
|
||||
#define MICROPY_EMIT_XTENSA (0)
|
||||
#undef MICROPY_EMIT_INLINE_XTENSA
|
||||
#define MICROPY_EMIT_INLINE_XTENSA (0)
|
||||
|
||||
#undef MICROPY_FSUSERMOUNT
|
||||
#define MICROPY_FSUSERMOUNT (0)
|
||||
#undef MICROPY_VFS_FAT
|
||||
@ -17,3 +22,6 @@
|
||||
#define MICROPY_PY_BUILTINS_SLICE_ATTRS (0)
|
||||
#undef MICROPY_PY_ALL_SPECIAL_METHODS
|
||||
#define MICROPY_PY_ALL_SPECIAL_METHODS (0)
|
||||
|
||||
#undef MICROPY_PY_FRAMEBUF
|
||||
#define MICROPY_PY_FRAMEBUF (0)
|
||||
|
@ -24,11 +24,12 @@ def fs_corrupted():
|
||||
import time
|
||||
while 1:
|
||||
print("""\
|
||||
FAT filesystem appears to be corrupted. If you had important data there, you
|
||||
may want to make a flash snapshot to try to recover it. Otherwise, perform
|
||||
factory reprogramming of MicroPython firmware (completely erase flash, followed
|
||||
by firmware programming).
|
||||
""")
|
||||
The FAT filesystem starting at sector %d with size %d sectors appears to
|
||||
be corrupted. If you had important data there, you may want to make a flash
|
||||
snapshot to try to recover it. Otherwise, perform factory reprogramming
|
||||
of MicroPython firmware (completely erase flash, followed by firmware
|
||||
programming).
|
||||
""" % (bdev.START_SEC, bdev.blocks))
|
||||
time.sleep(3)
|
||||
|
||||
def setup():
|
||||
|
@ -24,8 +24,8 @@ def main():
|
||||
print("STA ifconfig:", network.WLAN(network.STA_IF).ifconfig())
|
||||
print("AP ifconfig:", network.WLAN(network.AP_IF).ifconfig())
|
||||
print("Free WiFi driver buffers of type:")
|
||||
for i in range(5):
|
||||
print("%d: %d" % (i, esp.esf_free_bufs(i)))
|
||||
for i, comm in enumerate(("1,2 TX", "4 Mngmt TX(len: 0x41-0x100)", "5 Mngmt TX (len: 0-0x40)", "7", "8 RX")):
|
||||
print("%d: %d (%s)" % (i, esp.esf_free_bufs(i), comm))
|
||||
print("lwIP PCBs:")
|
||||
lwip.print_pcbs()
|
||||
|
||||
|
@ -5,7 +5,7 @@ import pyb
|
||||
accel = pyb.Accel() # create object of accelerometer
|
||||
blue = pyb.LED(4) # create object of blue LED
|
||||
|
||||
log = open('1:/log.csv', 'w') # open file to write data - 1:/ ist the SD-card, 0:/ the internal memory
|
||||
log = open('/sd/log.csv', 'w') # open file to write data - /sd/ is the SD-card, /flash/ the internal memory
|
||||
blue.on() # turn on blue LED
|
||||
|
||||
for i in range(100): # do 100 times (if the board is connected via USB, you can't write longer because the PC tries to open the filesystem which messes up your file.)
|
||||
|
@ -33,6 +33,7 @@
|
||||
#define MICROPY_COMP_CONST (0)
|
||||
#define MICROPY_MEM_STATS (0)
|
||||
#define MICROPY_DEBUG_PRINTERS (0)
|
||||
#define MICROPY_READER_POSIX (1)
|
||||
#define MICROPY_HELPER_REPL (1)
|
||||
#define MICROPY_HELPER_LEXER_UNIX (1)
|
||||
#define MICROPY_ENABLE_SOURCE_LINE (0)
|
||||
|
126
examples/hwapi/README.md
Normal file
126
examples/hwapi/README.md
Normal file
@ -0,0 +1,126 @@
|
||||
This directory shows the best practices for using MicroPython hardware API
|
||||
(`machine` module). `machine` module strives to provide consistent API
|
||||
across various boards, with the aim to enable writing portable applications,
|
||||
which would work from a board to board, from a system to another systems.
|
||||
This is inherently a hard problem, because hardware is different from one
|
||||
board type to another, and even from examplar of board to another. For
|
||||
example, if your app requires an external LED, one user may connect it
|
||||
to one GPIO pin, while another user may find it much more convinient to
|
||||
use another pin. This of course applies to relays, buzzers, sensors, etc.
|
||||
|
||||
With complications above in mind, it's still possible to write portable
|
||||
applications by using "low[est] denominator" subset of hardware API and
|
||||
following simple rules outlined below. The applications won't be able
|
||||
to rely on advanced hardware capabilities of a particular board and
|
||||
will be limited to generic capabilities, but it's still possible to
|
||||
write many useful applications in such a way, with the obvious benefit of
|
||||
"write once - run everywhere" approach (only configuration for a particular
|
||||
board is required).
|
||||
|
||||
The key to this approach is splitting your application into (at least)
|
||||
2 parts:
|
||||
|
||||
* main application logic
|
||||
* hardware configuration
|
||||
|
||||
The key point is that hardware configuration should be a separate file
|
||||
(module in Python terms). A good name would be `hwconfig.py`, and that's
|
||||
how we'll call it from now on. Another key point is that main application
|
||||
should never instantiate (construct) hardware objects directly. Instead,
|
||||
they should be defined in `hwconfig.py`, and main application should
|
||||
import and reference hardware objects via this module. The simplest
|
||||
application of this idea would look like:
|
||||
|
||||
`hwconfig.py`:
|
||||
|
||||
from machine import Pin
|
||||
|
||||
LED = Pin("A3", Pin.OUT)
|
||||
|
||||
`app.py`:
|
||||
|
||||
from hwconfig import *
|
||||
import utime
|
||||
|
||||
while True:
|
||||
LED.value(1)
|
||||
utime.sleep_ms(500)
|
||||
LED.value(0)
|
||||
utime.sleep_ms(500)
|
||||
|
||||
|
||||
To deploy this application to a particular board, a user will need:
|
||||
|
||||
1. Edit `hwconfig.py` to adjust Pin and other hardware peripheral
|
||||
parameters and locations.
|
||||
2. Actually deploy `hwconfig.py` and `app.py` to a board (e.g. copy to
|
||||
board's filesystem, or build new firmware with these modules frozen
|
||||
into it).
|
||||
|
||||
Note that there's no need to edit the main application code! (Which may
|
||||
be complex, while `hwconfig.py` should usually remain short enough, and
|
||||
focused solely on hardware configuration).
|
||||
|
||||
An obvious improvement to this approach is the following. There're few
|
||||
well-known boards which run MicroPython, and most of them include an
|
||||
onboard LED. So, to help users of these boards to do configuration
|
||||
quickly (that's especially important for novice users, for who may
|
||||
be stumped by the need to reach out to a board reference to find LED
|
||||
pin assignments), `hwconfig.py` your application ships may include
|
||||
commented out sections with working configurations for different
|
||||
boards. The step 1 above then will be:
|
||||
|
||||
1. Look thru `hwconfig.py` to find a section which either exactly
|
||||
matches your board, or the closest to it. Uncomment, and if any
|
||||
adjustments required, apply them.
|
||||
|
||||
It's important to keep in mind that adjustments may be always required,
|
||||
and that there may be users whose configuration doesn't match any of
|
||||
the available. So, always include a section or instructions for them.
|
||||
Consider for example that even on a supported board, user may want to
|
||||
blink not an on-board LED, but the one they connected externally.
|
||||
MicroPython's Hardware API offers portability not just among "supported"
|
||||
boards, but to any board at all, so make sure users can enjoy it.
|
||||
|
||||
There's next step of improvement to make. While having one `hwconfig.py`
|
||||
with many sections would work for smaller projects with few hardware
|
||||
objects, it may become more cumbersome to maintain both on programmer's
|
||||
and user's sides for larger projects. Then instead of single
|
||||
`hwconfig.py` file, you can provide few "template" ones for well-known
|
||||
boards:
|
||||
|
||||
* `hwconfig_pyboard.py`
|
||||
* `hwconfig_wipy.py`
|
||||
* `hwconfig_esp8266.py`
|
||||
* etc.
|
||||
|
||||
Then step 1 above will be:
|
||||
|
||||
1. Look thru available `hwconfig_*.py` files and find one which matches
|
||||
your board the best, then rename to `hwconfig.py` and make adjustments,
|
||||
if any.
|
||||
|
||||
Again, please keep in mind that there may be users whose hardware will be
|
||||
completely unlike you heard of. Give them some helpful hints too, perhaps
|
||||
provide `hwconfig_custom.py` with some instructions.
|
||||
|
||||
That's where we stop with improvements to the "separate file for hardware
|
||||
configuration" idea, as it is already pretty flexible and viable. An
|
||||
application in this directory shows it in practice, using slightly less
|
||||
trivial example than just a blinking LED: `soft_pwm.py` implements a
|
||||
software PWM (pulse width modulation) to produce an LED fade-in/fade-out
|
||||
effect - without any dependence on hardware PWM availability.
|
||||
|
||||
Note that improvements to board configuration handling may continue further.
|
||||
For example, one may invent a "configuration manager" helper module which will
|
||||
try to detect current board (among well-known ones), and load appropriate
|
||||
`hwconfig_*.py` - this assumes that a user would lazily deploy them all
|
||||
(or that application will be automatically installed, e.g. using MicroPython's
|
||||
`upip` package manager). The key point in this case remains the same as
|
||||
elaborated above - always assume there can, and will be a custom configuration,
|
||||
and it should be well supported. So, any automatic detection should be
|
||||
overridable by a user, and instructions how to do so are among the most
|
||||
important you may provide for your application.
|
||||
|
||||
By following these best practices, you will use MicroPython at its full
|
||||
potential, and let users enjoy it too. Good luck!
|
9
examples/hwapi/button_led.py
Normal file
9
examples/hwapi/button_led.py
Normal file
@ -0,0 +1,9 @@
|
||||
import utime
|
||||
from hwconfig import LED, BUTTON
|
||||
|
||||
# Light LED when (and while) a BUTTON is pressed
|
||||
|
||||
while 1:
|
||||
LED.value(BUTTON.value())
|
||||
# Don't burn CPU
|
||||
utime.sleep_ms(10)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user