forked from RIOT-OS/RIOT
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request RIOT-OS#2968 from kaspar030/micropython
pkg: micropython: initial commit
- Loading branch information
Showing
11 changed files
with
406 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# name of your application | ||
APPLICATION = micropython | ||
|
||
# If no BOARD is found in the environment, use this default: | ||
BOARD ?= native | ||
|
||
# This has to be the absolute path to the RIOT base directory: | ||
RIOTBASE ?= $(CURDIR)/../.. | ||
|
||
# select MicroPython package | ||
USEPKG += micropython | ||
|
||
# include boot.py as header | ||
BLOBS += boot.py | ||
|
||
# configure MicroPython's heap size | ||
MP_RIOT_HEAPSIZE ?= 8192U | ||
|
||
# MicroPython needs a larger stack | ||
CFLAGS += '-DTHREAD_STACKSIZE_MAIN=THREAD_STACKSIZE_DEFAULT*4' | ||
|
||
# use miniterm (instead of the default pyterm) in order to support control | ||
# characters (CTRL-D ...) | ||
RIOT_TERMINAL ?= miniterm | ||
|
||
# enable modmachine support for peripherals if available | ||
FEATURES_OPTIONAL += periph_adc | ||
FEATURES_OPTIONAL += periph_spi | ||
|
||
include $(RIOTBASE)/Makefile.include |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
BOARD_INSUFFICIENT_MEMORY := \ | ||
blackpill \ | ||
bluepill \ | ||
calliope-mini \ | ||
i-nucleo-lrwan1 \ | ||
microbit \ | ||
nrf51dongle \ | ||
nucleo-f030r8 \ | ||
nucleo-f031k6 \ | ||
nucleo-f042k6 \ | ||
nucleo-f070rb \ | ||
nucleo-f072rb \ | ||
nucleo-f302r8 \ | ||
nucleo-f303k8 \ | ||
nucleo-f334r8 \ | ||
nucleo-l031k6 \ | ||
nucleo-l053r8 \ | ||
opencm904 \ | ||
saml10-xpro \ | ||
saml11-xpro \ | ||
stm32f0discovery \ | ||
spark-core \ | ||
stm32f030f4-demo \ | ||
stm32l0538-disco \ | ||
# |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Overview | ||
|
||
WARNING: RIOT's MicroPython port is currently quite incomplete! | ||
|
||
This application provides an example on how to use MicroPython with RIOT. | ||
Please see the documentation of pkg/micropython. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
print("boot.py: MicroPython says hello!") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
* Copyright (C) 2019 Kaspar Schleiser <kaspar@schleiser.de> | ||
* | ||
* This file is subject to the terms and conditions of the GNU Lesser | ||
* General Public License v2.1. See the file LICENSE in the top level | ||
* directory for more details. | ||
*/ | ||
|
||
/** | ||
* @ingroup examples | ||
* @{ | ||
* | ||
* @file | ||
* @brief micropython example application | ||
* | ||
* @author Kaspar Schleiser <kaspar@schleiser.de> | ||
* | ||
* @} | ||
*/ | ||
|
||
#include <stdio.h> | ||
|
||
#include "thread.h" | ||
|
||
#include "micropython.h" | ||
#include "py/stackctrl.h" | ||
#include "lib/utils/pyexec.h" | ||
|
||
#include "blob/boot.py.h" | ||
|
||
static char mp_heap[MP_RIOT_HEAPSIZE]; | ||
|
||
int main(void) | ||
{ | ||
int coldboot = 1; | ||
|
||
/* let MicroPython know the top of this thread's stack */ | ||
uint32_t stack_dummy; | ||
mp_stack_set_top((char*)&stack_dummy); | ||
|
||
/* Make MicroPython's stack limit somewhat smaller than actual stack limit */ | ||
mp_stack_set_limit(THREAD_STACKSIZE_MAIN - MP_STACK_SAFEAREA); | ||
|
||
while (1) { | ||
/* configure MicroPython's heap */ | ||
mp_riot_init(mp_heap, sizeof(mp_heap)); | ||
|
||
/* execute boot.py | ||
* | ||
* MicroPython's test suite gets confused by extra output, so only do | ||
* this the first time after the node boots up, not on following soft | ||
* reboots. | ||
*/ | ||
if (coldboot) { | ||
puts("-- Executing boot.py"); | ||
mp_do_str((const char *)boot_py, boot_py_len); | ||
puts("-- boot.py exited. Starting REPL.."); | ||
coldboot = 0; | ||
} | ||
|
||
/* loop over REPL input */ | ||
while (1) { | ||
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { | ||
if (pyexec_raw_repl() != 0) { | ||
break; | ||
} | ||
} else { | ||
if (pyexec_friendly_repl() != 0) { | ||
break; | ||
} | ||
} | ||
} | ||
puts("soft reboot"); | ||
} | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import sys | ||
from testrunner import run | ||
|
||
|
||
def testfunc(child): | ||
def get_time(): | ||
child.sendline('utime.time()') | ||
child.readline() | ||
res = int(child.readline().rstrip()) | ||
child.expect_exact('>>>') | ||
return res | ||
|
||
child.expect_exact('boot.py: MicroPython says hello!') | ||
child.expect_exact('>>>') | ||
|
||
child.sendline('print("echo this! " * 4)') | ||
child.expect_exact('echo this! echo this! echo this! echo this!') | ||
child.expect_exact('>>>') | ||
|
||
# test riot.thread_getpid() | ||
child.sendline('import riot') | ||
child.sendline('print(riot.thread_getpid())') | ||
child.expect_exact('2') | ||
child.expect_exact('>>>') | ||
|
||
# | ||
# test xtimer integration | ||
# | ||
|
||
child.sendline('import utime') | ||
child.expect_exact('>>>') | ||
|
||
# testing timing over serial using the REPL is very inaccurate, thus | ||
# we allow a *large* overshoot (100 by default). | ||
def test_sleep(t, slack=100): | ||
before = get_time() | ||
child.sendline('utime.sleep_ms(%s)' % t) | ||
child.expect_exact('>>>') | ||
duration = get_time() - before | ||
print("test_sleep(%s, %s): slept %sms" % (t, slack, duration)) | ||
assert duration > t and duration < (t + slack) | ||
return duration | ||
|
||
# get overhead from sleeping 0ms, add 10 percent | ||
slack = int(test_sleep(0, 1000) * 1.1) | ||
|
||
test_sleep(50, slack) | ||
test_sleep(250, slack) | ||
test_sleep(500, slack) | ||
|
||
# test setting timers | ||
child.sendline('import xtimer') | ||
child.expect_exact('>>>') | ||
child.sendline('a = 0') | ||
child.expect_exact('>>>') | ||
|
||
child.sendline('def inc_a(): global a; a+=1') | ||
child.expect_exact('...') | ||
child.sendline('') | ||
child.expect_exact('>>>') | ||
|
||
child.sendline('t = xtimer.xtimer(inc_a)') | ||
child.expect_exact('>>>') | ||
|
||
before = get_time() | ||
|
||
child.sendline('t.set(500000)') | ||
child.expect_exact('>>>') | ||
|
||
child.sendline('while a==0: pass') | ||
child.expect_exact('...') | ||
child.sendline('') | ||
child.expect_exact('>>>') | ||
|
||
duration = get_time() - before | ||
assert duration > 500 | ||
|
||
print("[TEST PASSED]") | ||
|
||
|
||
if __name__ == "__main__": | ||
sys.exit(run(testfunc)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
PKG_NAME=micropython | ||
PKG_URL=https://github.com/kaspar030/micropython | ||
PKG_VERSION=5c45688d431a4d0f626d86478ad490cfb6d8ac30 | ||
PKG_LICENSE=MIT | ||
|
||
CFLAGS += -Wno-implicit-fallthrough -Wno-unused-parameter -Wno-error | ||
|
||
.PHONY: all | ||
|
||
all: | ||
@mkdir -p $(PKG_BUILDDIR)/tmp | ||
BUILD=$(PKG_BUILDDIR) "$(MAKE)" -C $(PKG_BUILDDIR)/ports/riot | ||
|
||
include $(RIOTBASE)/pkg/pkg.mk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
USEMODULE += xtimer | ||
USEMODULE += stdin | ||
|
||
# MicroPython doesn't compile for <32bit platforms | ||
FEATURES_BLACKLIST += arch_8bit arch_16bit | ||
|
||
# This port currently requires ISR_STACKSIZE and thread_isr_stack_start | ||
FEATURES_BLACKLIST += arch_arm7 arch_esp32 arch_esp8266 arch_riscv | ||
|
||
# The port currently doesn't compile for mips | ||
FEATURES_BLACKLIST += arch_mips32r2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# configuration | ||
MP_RIOT_HEAPSIZE ?= 16384U | ||
|
||
CFLAGS += -DMP_RIOT_HEAPSIZE=$(MP_RIOT_HEAPSIZE) | ||
|
||
# include paths | ||
INCLUDES += -I$(RIOTBASE)/pkg/micropython/include | ||
INCLUDES += -I$(PKGDIRBASE)/micropython | ||
INCLUDES += -I$(PKGDIRBASE)/micropython/ports/riot | ||
|
||
# The port currently doesn't build with llvm | ||
TOOLCHAINS_BLACKLIST += llvm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/** | ||
* @defgroup pkg_micropython MicroPython RIOT port | ||
* @ingroup pkg | ||
* @brief MicroPython - Python for microcontrollers | ||
* | ||
* # MicroPython RIOT package | ||
* | ||
* "MicroPython is a lean and efficient implementation of the Python 3 | ||
* programming language that includes a small subset of the Python standard | ||
* library and is optimised to run on microcontrollers and in constrained | ||
* environments." | ||
* | ||
* @see https://micropython.org | ||
* | ||
* ## Status | ||
* | ||
* MicroPython on RIOT has to be considered experimental. While the basic | ||
* interpreter works fairly well on native and Cortex-M, it has not seen much | ||
* testing. | ||
* | ||
* ## Configuration options | ||
* | ||
* Use the following environment variables in the application Makefile | ||
* or from the command line to configure MicroPython: | ||
* | ||
* MP_RIOT_HEAPSIZE: heap size for MicroPython, in bytes. Defaults to 16KiB. | ||
* | ||
* Example on the command line: | ||
* ``` | ||
* MP_RIOT_HEAPSIZE=2048 make -C examples/micropython | ||
* ``` | ||
* | ||
* ## Implementation details | ||
* | ||
* The RIOT port of MicroPython currently resides in a fork at | ||
* https://github.com/kaspar030/micropython (in branch add_riot_port). It is | ||
* based on Micropython's "ports/minimal" with some extra modules enabled. | ||
* It re-uses the gc_collect code from ports/unix, which has special support | ||
* for i386 and Cortex-M. On other platforms, it uses setjmp() to collect | ||
* registers. | ||
* | ||
* ## MicroPython's test suite | ||
* | ||
* It is possible to run MicroPython's test suite for testing this port. | ||
* | ||
* Steps: | ||
* | ||
* 1. make -Cexamples/micropython flash | ||
* 2. cd examples/micropython/bin/pkg/${BOARD}/micropython | ||
* 3. git apply ports/riot/slow_uart_writes.patch | ||
* 4. cd tests | ||
* 5. ./run-tests --target pyboard --device ${PORT} | ||
* | ||
* ## MicroPython modules | ||
* | ||
* Currently, the port enables only a subset of the available MycroPython | ||
* modules. See "ports/riot/mpconfigport.h" for details. | ||
* | ||
* For now, the utime module has RIOT specific code and should work as expected. | ||
* | ||
* ## RIOT specific modules | ||
* | ||
* Currently, these are implemented: | ||
* | ||
* ### thread_getpid() | ||
* | ||
* >>> import riot | ||
* >>> print(riot.thread_getpid()) | ||
|
||
* ### xtimer | ||
* | ||
* >>> import xtimer | ||
* >>> | ||
* >>> a = 0 | ||
* >>> def inc_a(): | ||
* >>> global a | ||
* >>> a += 1 | ||
* >>> | ||
* >>> t = xtimer.xtimer(inc_a) | ||
* >>> t.set(100000) | ||
* >>> print(a) | ||
* | ||
* ## How to use | ||
* | ||
* See examples/micropython for example code. | ||
* | ||
*/ |
Oops, something went wrong.