Commit e30d98a1 authored by Damien George's avatar Damien George
Browse files

leon: Add leon-ex-minimal example.

parent 3d5fd11d
# This file is part of the MicroPython port to LEON platforms
# Copyright (c) 2015-2016 George Robotics Limited
#
# Provided to the European Space Agency as part of the project "Porting of
# MicroPython to LEON platforms", contract number 4000114080/15/NL/FE/as.
#
# This Makefile builds an example of a minimal LEON port.
# the location of the MIcroPython LEON support code
LEON_COMMON = leon-common
LEON_COMMON_FROM_HERE = ../$(LEON_COMMON)
include ../py/mkenv.mk
# qstr definitions (must come before including py.mk)
QSTR_DEFS = $(LEON_COMMON_FROM_HERE)/qstrdefsport.h
# include py core make definitions
include ../py/py.mk
# the toolchain needs two things:
# - the sparc-rtems compiler: (TOOL_BASE)
# - the precompiled RTEMS (RTEMS_BASE)
TOOL_BASE = /home/notroot/Download/rtems-4.8/bin
RTEMS_BASE = /home/notroot/Download/rtems-4.8/sparc-rtems/leon2
CROSS_COMPILE = $(TOOL_BASE)/sparc-rtems-
LD = $(CROSS_COMPILE)gcc
OBJDUMP = $(CROSS_COMPILE)objdump
# RTEMS lib needs
GCCSPECS = -B$(RTEMS_BASE)/lib/ -specs bsp_specs -qrtems
INC =
INC += -I. -I.. -I$(BUILD) -I$(LEON_COMMON_FROM_HERE)
INC += -I$(RTEMS_BASE)/lib/include
CFLAGS =
CFLAGS += $(GCCSPECS)
CFLAGS += $(INC) -Wall -Werror -ansi -std=gnu99 $(COPT) -mcpu=v8
# Use this to optimise the static hash tables
CFLAGS += -no-integrated-cpp -B$(shell pwd)/../tools
# Debugging/Optimization
ifeq ($(DEBUG), 1)
CFLAGS += -O0 -ggdb
else
CFLAGS += -Os -DNDEBUG
endif
LDFLAGS =
LDFLAGS += $(GCCSPECS)
LDFLAGS += -L$(RTEMS_BASE)/lib
LIBS = -lm
SRC_C = \
main.c \
lib/libc/string0.c \
$(LEON_COMMON)/mputil.c \
$(LEON_COMMON)/mpvmmanage.c \
$(LEON_COMMON)/mphalport.c \
$(LEON_COMMON)/modtime.c \
$(LEON_COMMON)/modrtems.c \
$(LEON_COMMON)/modrtemstask.c \
$(LEON_COMMON)/modrtemsqueue.c \
$(LEON_COMMON)/modrtemstimer.c \
SRC_S = \
$(LEON_COMMON)/gchelper.s \
# these are the example Python scripts to compile
SRC_PY = ex1.py ex2.py
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o) $(SRC_S:.s=.o))
all: $(BUILD)/firmware.elf $(BUILD)/firmware.srec $(BUILD)/firmware.tab
run: $(BUILD)/firmware.srec $(BUILD)/firmware.tab
$(Q)cat cmd.txt | leon2-emu
$(BUILD)/firmware.elf: $(OBJ)
$(ECHO) "LINK $@"
$(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
$(Q)$(SIZE) $@
$(BUILD)/firmware.srec: $(BUILD)/firmware.elf
$(ECHO) "SREC $@"
$(Q)$(OBJCOPY) -O srec $< $@
$(BUILD)/firmware.tab: $(BUILD)/firmware.elf
$(ECHO) "TAB $@"
$(Q)$(OBJDUMP) --syms $< > $@
main.c: $(BUILD)/scripts.h
$(BUILD)/%.mpy: %.py
$(ECHO) "PY $<"
$(Q)../leon-compiler/micropython -o $@ $<
$(BUILD)/scripts.h: $(addprefix $(BUILD)/, $(SRC_PY:.py=.mpy))
$(ECHO) "MPY $@"
$(Q)../tools/mpytool.py tohdr $^ > $@
include ../py/mkrules.mk
load /srec "build/firmware.srec"
load /symtab "build/firmware.tab"
set pc=0x40000000
set i6=0x41000000
set o6=0x40FFFE80
step 5000000
# Example script #1
import micropython
import time
import rtems
class MovingAverage:
def __init__(self, n):
self.values = [0] * n
def add_value(self, value):
for i in range(len(self.values) - 1):
self.values[i + 1] = self.values[i]
self.values[0] = value
def get_average(self):
total = 0
for i in range(len(self.values)):
total += self.values[i]
return total / len(self.values)
class Sensor:
def __init__(self, name, source):
self.name = name
self.source = source
self.filter = MovingAverage(5)
def sample(self):
self.filter.add_value(self.source())
return self.filter.get_average()
class Indicator:
def __init__(self, name):
self.name = name
self.state = False
def toggle(self):
self.state = not self.state
def create():
# this is not very random!
def random(state=[1234]):
state[0] = (0x31a9 * state[0] + 0xce34) & 0xffff
return state[0]
sensors = {
"random1":Sensor("random1", lambda: random() % 100),
"random2":Sensor("random2", lambda: random() % 100),
}
indicators = {
"indicator1":Indicator("indicator1"),
"indicator2":Indicator("indicator2"),
}
return sensors, indicators
def loop(sensors, indicators):
for i in range(10):
s1 = sensors["random1"].sample()
s2 = sensors["random2"].sample()
if s1 + s2 > 50:
indicators["indicator1"].toggle()
else:
indicators["indicator2"].toggle()
print('iter', i, 'time', time.time(), int(s1), int(s2),
indicators["indicator1"].state, indicators["indicator2"].state)
time.sleep(0.5)
def main():
sensors, indicators = create()
micropython.heap_lock()
print('MicroPython script 1')
print('RTEMS script id:', rtems.script_id())
loop(sensors, indicators)
main()
# Example script #2
import micropython
import time
import math
import rtems
def main():
tod = 6 * [0]
micropython.heap_lock()
print('MicroPython script 2')
print('RTEMS script id:', rtems.script_id())
time.localtime_into(tod)
print('datetime:', tod)
for i in range(1, 10):
print('sin(pi / ', i, ') = ', round(math.sin(math.pi / i), 4), sep='')
main()
/*
* This file is part of the MicroPython port to LEON platforms
* Copyright (c) 2015-2016 George Robotics Limited
*
* Provided to the European Space Agency as part of the project "Porting of
* MicroPython to LEON platforms", contract number 4000114080/15/NL/FE/as.
*/
#include <stdio.h>
#include <rtems.h>
#include <bsp.h>
#define CONFIGURE_INIT
#define CONFIGURE_INIT_TASK_ENTRY_POINT Init
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_MAXIMUM_TASKS (4)
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_EXTRA_TASK_STACKS (3 * RTEMS_MINIMUM_STACK_SIZE)
rtems_task Init(rtems_task_argument argument);
rtems_task mp_manager_task(rtems_task_argument unused);
rtems_task mp_worker_task(rtems_task_argument unused);
#include <rtems/confdefs.h>
#define MICROPY_RTEMS_TASK_ATTRIBUTES (RTEMS_APPLICATION_TASK | RTEMS_FLOATING_POINT)
#define MICROPY_RTEMS_STACK_SIZE (RTEMS_MINIMUM_STACK_SIZE * 2)
#define MICROPY_RTEMS_HEAP_SIZE (16 * 1024)
#ifndef MICROPY_RTEMS_NUM_TASKS
#define MICROPY_RTEMS_NUM_TASKS (1)
#endif
/******************************************************************************/
// RTEMS initialisation task
// this task runs at highest priority and is non-preemptive
rtems_task Init(rtems_task_argument ignored) {
// set the time
rtems_time_of_day time;
time.year = 2016;
time.month = 1;
time.day = 1;
time.hour = 0;
time.minute = 0;
time.second = 0;
time.ticks = 0;
rtems_clock_set(&time);
// initialise the message queue subsystem
_Message_queue_Manager_initialization(4);
// initialise the timer subsystem
_Timer_Manager_initialization(2);
// start the manager task to do the rest of the work
rtems_name task_name = rtems_build_name('M', 'P', 'M', 'A');
rtems_id task_id;
rtems_status_code status;
status = rtems_task_create(
task_name, 1, RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES,
MICROPY_RTEMS_TASK_ATTRIBUTES, &task_id
);
status = rtems_task_start(task_id, mp_manager_task, 0);
rtems_task_delete(RTEMS_SELF);
}
/******************************************************************************/
// MicroPython manager task
#include "py/mphal.h"
// this function is used as a hook to set a breakpoint to terminate emu
void emu_terminate(void) {
printf("emu_terminate\n");
}
rtems_task mp_manager_task(rtems_task_argument ignored) {
printf("\nMicroPython manager task started\n");
rtems_name task_name[MICROPY_RTEMS_NUM_TASKS];
rtems_id task_id[MICROPY_RTEMS_NUM_TASKS];
// spawn all worker tasks
for (int i = 0; i < MICROPY_RTEMS_NUM_TASKS; ++i) {
rtems_status_code status;
task_name[i] = rtems_build_name('M', 'P', '0', '0' + i);
status = rtems_task_create(
task_name[i], 1, MICROPY_RTEMS_STACK_SIZE, RTEMS_DEFAULT_MODES,
MICROPY_RTEMS_TASK_ATTRIBUTES, &task_id[i]
);
status = rtems_task_start(task_id[i], mp_worker_task, i);
}
// wait for termination
for (;;) {
rtems_task_wake_after(100);
}
}
/******************************************************************************/
// MicroPython worker task
#include "py/runtime.h"
#include "py/gc.h"
#include "py/stackctrl.h"
#include "mputil.h"
// include the precompiled bytecode (generated by external tools)
#include "build/scripts.h"
static mp_state_ctx_t mp_state_ctx[MICROPY_RTEMS_NUM_TASKS];
static byte mp_heap[MICROPY_RTEMS_NUM_TASKS * MICROPY_RTEMS_HEAP_SIZE];
rtems_task mp_worker_task(rtems_task_argument task_index) {
// set the MicroPython context for this task
_Thread_Executing->Start.numeric_argument = (uint32_t)&mp_state_ctx[task_index];
// get a pointer to the heap for this task
byte *heap_start = &mp_heap[task_index * MICROPY_RTEMS_HEAP_SIZE];
// loop and execute all the scripts
for (int script_num = 0; script_num < mpy_script_num; ++script_num) {
// initialise the stack limit checking
mp_stack_ctrl_init();
mp_stack_set_limit(MICROPY_RTEMS_STACK_SIZE - 2048);
// initialise the heap
gc_init(heap_start, heap_start + MICROPY_RTEMS_HEAP_SIZE);
// initialise the MicroPython runtime
mp_init();
// execute the bytecode
uint32_t retval = mp_exec_mpy(mpy_script_data[script_num], mpy_script_len[script_num]);
// check the return value
if (retval != 0) {
mp_printf(&mp_plat_print, "retval = %u\n", (uint)retval);
}
// deinitialise the MicroPython runtime
mp_deinit();
}
// terminate emulator
emu_terminate();
rtems_task_delete(RTEMS_SELF);
}
/*
* This file is part of the MicroPython port to LEON platforms
* Copyright (c) 2015-2016 George Robotics Limited
*
* Provided to the European Space Agency as part of the project "Porting of
* MicroPython to LEON platforms", contract number 4000114080/15/NL/FE/as.
*/
// options to control how MicroPython is built
#define MICROPY_NLR_SETJMP (1)
#define MICROPY_ALLOC_PATH_MAX (128)
#define MICROPY_PERSISTENT_CODE_LOAD (1)
#define MICROPY_EMIT_X64 (0)
#define MICROPY_EMIT_THUMB (0)
#define MICROPY_EMIT_INLINE_THUMB (0)
#define MICROPY_ENABLE_COMPILER (0)
#define MICROPY_COMP_MODULE_CONST (0)
#define MICROPY_COMP_CONST (0)
#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1)
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1)
#define MICROPY_MEM_STATS (0)
#define MICROPY_DEBUG_PRINTERS (0)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_ENABLE_IMMORTAL_GC (1)
#define MICROPY_ENABLE_FINALISER (0)
#define MICROPY_STACK_CHECK (1)
#define MICROPY_REPL_EVENT_DRIVEN (0)
#define MICROPY_HELPER_REPL (0)
#define MICROPY_HELPER_LEXER_UNIX (0)
#define MICROPY_ENABLE_SOURCE_LINE (1)
#define MICROPY_ENABLE_DOC_STRING (0)
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL)
#define MICROPY_OPT_COMPUTED_GOTO (1)
#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0)
#define MICROPY_MODULE_WEAK_LINKS (0)
#define MICROPY_MODULE_FROZEN (0)
#define MICROPY_CPYTHON_COMPAT (0)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
#define MICROPY_PY_FUNCTION_ATTRS (1)
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1)
#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
#define MICROPY_PY_BUILTINS_ENUMERATE (1)
#define MICROPY_PY_BUILTINS_FROZENSET (1)
#define MICROPY_PY_BUILTINS_REVERSED (1)
#define MICROPY_PY_BUILTINS_SET (1)
#define MICROPY_PY_BUILTINS_SLICE (1)
#define MICROPY_PY_BUILTINS_PROPERTY (1)
#define MICROPY_PY___FILE__ (1)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
#define MICROPY_PY_SYS_EXIT (1)
#define MICROPY_PY_SYS_MAXSIZE (1)
#define MICROPY_PY_SYS_MODULES (0)
#define MICROPY_PY_SYS_STDFILES (0)
#define MICROPY_PY_SYS_STDIO_BUFFER (1)
#define MICROPY_PY_SYS_PLATFORM "leon2"
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
#define MICROPY_PY_GC (1)
#define MICROPY_PY_ARRAY (1)
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
#define MICROPY_PY_ATTRTUPLE (1)
#define MICROPY_PY_COLLECTIONS (1)
#define MICROPY_PY_MATH (1)
#define MICROPY_PY_CMATH (0)
#define MICROPY_PY_UJSON (0)
#define MICROPY_PY_UBINASCII (0)
#define MICROPY_PY_IO (0)
#define MICROPY_PY_STRUCT (1)
#define MICROPY_PY_SYS (1)
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256)
// builtin modules
extern const struct _mp_obj_module_t mp_module_time;
extern const struct _mp_obj_module_t mp_module_rtems;
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_module_time) }, \
{ MP_ROM_QSTR(MP_QSTR_rtems), MP_ROM_PTR(&mp_module_rtems) }, \
// definitions specific to SPARC
#define MP_ENDIANNESS_BIG (1)
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)p)
#define MICROPY_SPARC_NUM_REG_WINDOWS (8)
#include <stdint.h>
#if 0
// configuration for 32-bit object word size
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_A)
#define BYTES_PER_WORD (4)
#define UINT_FMT "%u"
#define INT_FMT "%d"
typedef int mp_int_t;
typedef unsigned mp_uint_t;
#else
// configuration for 64-bit NaN boxing
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_D)
#define BYTES_PER_WORD (8)
typedef int64_t mp_int_t;
typedef uint64_t mp_uint_t;
#define UINT_FMT "%llu"
#define INT_FMT "%lld"
#endif
typedef void *machine_ptr_t; // must be of pointer size
typedef const void *machine_const_ptr_t; // must be of pointer size
typedef long mp_off_t;
// We need to provide a declaration/definition of alloca()
#include <alloca.h>
// INFINITY is not defined by toolchain
#ifndef INFINITY
#define INFINITY (__builtin_inff())
#endif
// We define our own state accessor macros
#include <rtems.h>
#define MP_STATE_PTR ((mp_state_ctx_t*)_Thread_Executing->Start.numeric_argument)
#define MP_STATE_CTX(x) (MP_STATE_PTR->x)
#define MP_STATE_VM(x) (MP_STATE_PTR->vm.x)
#define MP_STATE_MEM(x) (MP_STATE_PTR->mem.x)
#define MP_STATE_PORT MP_STATE_VM
// Hook for the VM
#define MICROPY_VM_HOOK_COUNT (1)
#define MICROPY_VM_HOOK_INIT uint vm_hook_count = MICROPY_VM_HOOK_COUNT;
#define MICROPY_VM_HOOK_LOOP \
if (--vm_hook_count == 0) { \
vm_hook_count = MICROPY_VM_HOOK_COUNT; \
MARK_EXC_IP_SELECTIVE(); \
extern void mp_vm_hook(const mp_code_state *code_state); \
mp_vm_hook(code_state); \
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment