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.
examples/micropython: initial micropython example application
- Loading branch information
Showing
6 changed files
with
223 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)) |