Commits

Anonymous committed 3193868

#179 builds and tests pass; check-in on branch

Comments (0)

Files changed (26)

 pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
 PYCSCOPE := $(call pathsearch,pycscope.py)
 
-# The value of UART_BAUD must match that found in src/tools/ipm.py
-# and the F_CPU (below) must be set to match the target device's core frequency
-# for the interactive interaface to work.
-UART_BAUD = 19200UL
-
 VPATH := . src/vm src/lib docs/src
 
-# Build configuration
-TARGET := DESKTOP
-HEAP_SIZE = 0x2000
+# Default target
+PLATFORM ?= desktop
 
-# Changes for an embedded target
-ifeq ($(TARGET), AVR)
-	# TARGET_MCU should equal avr-gcc option "-mmcu" possible values.
-	TARGET_MCU := atmega103
-	HEAP_SIZE = 0x0D00
-	F_CPU = 4000000UL
-else
-ifeq ($(TARGET), AT91SAM7)
-	# TARGET_MCU should equal arm-elf-gcc option "-mcpu" possible values.
-	TARGET_MCU := arm7tdmi
-	HEAP_SIZE = 0x3000
-endif
-endif
-
-# Export config to child makefiles
-export TARGET HEAP_SIZE TARGET_MCU
 
 .PHONY: all vm ipm html indent TAGS dist check clean
 
-all : vm
+all :
+	$(MAKE) -C src/platform/$(PLATFORM)
 
-vm :
-	$(MAKE) -C src/vm
-
-ipm : all
-	$(MAKE) -C src/sample/ipm-desktop
+ipm :
+	$(MAKE) -C src/platform/desktop
 	cd src/tools && ./ipm.py -d
 
 html : docs/src/*.txt
 
 # Removes all files created during default make
 clean :
-	$(MAKE) -C src/vm clean
+	$(MAKE) -C src/platform/$(PLATFORM) clean
 
 # Removes files made by make check
 check-clean :
 
 # Removes files made by ipm
 ipm-clean :
-	$(MAKE) -C src/sample/ipm-desktop clean
+	$(MAKE) -C src/sample/desktop-ipm clean
+

src/platform/at91sam7s-ek/Makefile

 # Hey Emacs, this is a -*- makefile -*-
 #
-# WinARM template makefile 
-# by Martin Thomas, Kaiserslautern, Germany 
+# WinARM template makefile
+# by Martin Thomas, Kaiserslautern, Germany
 # <eversmith@heizung-thomas.de>
 #
 # based on the WinAVR makefile written by Eric B. Weddington, J�rg Wunsch, et al.
 #
 
 # PyMite Configuration
+PLATFORM := $(notdir $(CURDIR))
+PM_LIB_ROOT = pmvm.$(PLATFORM)
+PM_LIB_FN = lib$(PM_LIB_ROOT).a
+PM_LIB_PATH = ../../vm/$(PM_LIB_FN)
+PM_USR_SOURCES = main.py
+PM_HEAP_SIZE = 0x3000
 PMIMGCREATOR := ../../tools/pmImgCreator.py
+PM_UART_BAUD = 19200
 
 FLASH_TOOL = SAM7UTILS
 #FLASH_TOOL = UVISION
 
 ## Create ROM-Image (final)
 RUN_MODE=ROM_RUN
-## Create RAM-Image (debugging) 
+## Create RAM-Image (debugging)
 ##( not used: example does not fit in AT91SAM7S64 RAM )
 #RUN_MODE=RAM_RUN
 
 #VECTOR_LOCATION=VECTORS_IN_RAM
 
 # Target file name (without extension).
-TARGET = sample
+TARGET = main
 
 # List C source files here. (C dependencies are automatically generated.)
 # use file-extension c for "c-only"-files
-SRC = 
+SRC = $(TARGET).c plat.c $(TARGET)_nat.c $(TARGET)_img.c
 
 # List C source files here which must be compiled in ARM-Mode.
 # use file-extension c for "c-only"-files
-SRCARM = $(TARGET).c Cstartup_SAM7.c 
+SRCARM = Cstartup_SAM7.c
 
 # List C++ source files here.
 # use file-extension cpp for C++-files (use extension .cpp)
-CPPSRC = 
+CPPSRC =
 
 # List C++ source files here which must be compiled in ARM-Mode.
 # use file-extension cpp for C++-files (use extension .cpp)
 #CPPSRCARM = $(TARGET).cpp
-CPPSRCARM = 
+CPPSRCARM =
 
 # List Assembler source files here.
 # Make them always end in a capital .S.  Files ending in a lowercase .s
 # Even though the DOS/Win* filesystem matches both .s and .S the same,
 # it will preserve the spelling of the filenames, and gcc itself does
 # care about how the name is spelled on its command-line.
-ASRC = 
+ASRC =
 
 # List Assembler source files here which must be assembled in ARM-Mode..
 ASRCARM  = Cstartup.S
 #FORMAT = ihex
 FORMAT = binary
 
-# Optimization level, can be [0, 1, 2, 3, s]. 
+# Optimization level, can be [0, 1, 2, 3, s].
 # 0 = turn off optimization. s = optimize for size.
 # (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
 OPT = s
 # Debugging format.
 # Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
 # AVR (extended) COFF requires stabs, plus an avr-objcopy run.
-DEBUG = stabs
-#DEBUG = dwarf-2
+DEBUG_FMT = stabs
 
 # List any extra directories to look for include files here.
 #     Each directory must be seperated by a space.
-EXTRAINCDIRS = 
+EXTRAINCDIRS = ../../vm
 
 # List any extra directories to look for library files here.
 #     Each directory must be seperated by a space.
 EXTRA_LIBDIRS = ../../vm
 
 ## Using the Atmel AT91_lib produces warning with
-## the default warning-levels. 
+## the default warning-levels.
 ## yes - disable these warnings; no - keep default settings
 AT91LIBNOWARN = yes
 #AT91LIBNOWARN = no
 # gnu99 - c99 plus GCC extensions
 CSTANDARD = -std=gnu99
 
-# Place -D or -U options for C here
-CDEFS =  -D$(RUN_MODE) -DTARGET_ARM
+# Place -D or -U options here
+CDEFS =  -D$(RUN_MODE)
+# PyMite CDEFS
+CDEFS += -DHEAP_SIZE=$(PM_HEAP_SIZE) -DUART_BAUD=$(PM_UART_BAUD)
+ifeq ($(DEBUG),true)
+	CDEFS += -g -g$(DEBUG_FMT) -D__DEBUG__=1
+endif
 
 # Place -I options here
-CINCS = -I../../vm
+CINCS =
 
 # Place -D or -U options for ASM here
 ADEFS =  -D$(RUN_MODE)
 
 ifeq ($(USE_THUMB_MODE),YES)
 THUMB    = -mthumb
-THUMB_IW = -mthumb-interwork
-else 
-THUMB    = 
-THUMB_IW = 
+#THUMB_IW = -mthumb-interwork
+THUMB_IW =
+else
+THUMB    =
+THUMB_IW =
 endif
 
 #  -g*:          generate debugging information
 #    -adhlns...: create assembler listing
 #
 # Flags for C and C++ (arm-elf-gcc/arm-elf-g++)
-CFLAGS = -g$(DEBUG)
-CFLAGS += $(CDEFS) $(CINCS)
+CFLAGS = $(CDEFS) $(CINCS)
 CFLAGS += -O$(OPT)
-CFLAGS += -Wall -Wcast-align -Wimplicit 
+CFLAGS += -Wall -Wcast-align -Wimplicit
 CFLAGS += -Wpointer-arith -Wswitch
 CFLAGS += -Wredundant-decls -Wreturn-type -Wshadow -Wunused
-CFLAGS += -Wa,-adhlns=$(subst $(suffix $<),.lst,$<) 
+CFLAGS += -Wa,-adhlns=$(subst $(suffix $<),.lst,$<)
 CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
 #### CFLAGS += -ffunction-sections -fdata-sections
 
 # flags only for C
-CONLYFLAGS += -Wnested-externs 
+CONLYFLAGS += -Wnested-externs
 CONLYFLAGS += $(CSTANDARD)
 
 ifneq ($(AT91LIBNOWARN),yes)
 #AT91-lib warnings with:
 CFLAGS += -Wcast-qual
-CONLYFLAGS += -Wmissing-prototypes 
+CONLYFLAGS += -Wmissing-prototypes
 CONLYFLAGS += -Wstrict-prototypes
 CONLYFLAGS += -Wmissing-declarations
 endif
 
 # flags only for C++ (arm-elf-g++)
 # CPPFLAGS = -fno-rtti -fno-exceptions
-CPPFLAGS = 
+CPPFLAGS =
 
 # Assembler flags.
 #  -Wa,...:    tell GCC to pass this to the assembler.
 #  -ahlns:     create listing
-#  -g$(DEBUG): have the assembler create line number information
-ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:.S=.lst),--g$(DEBUG)
+#  -g$(DEBUG_FMT): have the assembler create line number information
+ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:.S=.lst),--g$(DEBUG_FMT)
 
 
 #Additional libraries.
 
 # Extra libraries
 #    Each library-name must be seperated by a space.
-#    To add libxyz.a, libabc.a and libefsl.a: 
+#    To add libxyz.a, libabc.a and libefsl.a:
 #    EXTRA_LIBS = xyz abc efsl
 #EXTRA_LIBS = efsl
-EXTRA_LIBS = pmvm
+EXTRA_LIBS = $(PM_LIB_ROOT)
 
 #Support for newlibc-lpc (file: libnewlibc-lpc.a)
 #NEWLIBLPC = -lnewlib-lpc
 LDFLAGS += -Wl,-Map=$(TARGET).map,--cref
 LDFLAGS += -lc
 LDFLAGS += $(NEWLIBLPC) $(MATH_LIB)
-LDFLAGS += -lc -lgcc 
+LDFLAGS += -lc -lgcc
 LDFLAGS += $(CPLUSPLUS_LIB)
 LDFLAGS += $(patsubst %,-L%,$(EXTRA_LIBDIRS))
 LDFLAGS += $(patsubst %,-l%,$(EXTRA_LIBS))
 # Set Linker-Script Depending On Selected Memory and Controller
 ifeq ($(RUN_MODE),RAM_RUN)
 LDFLAGS +=-T$(SUBMDL)-RAM.ld
-else 
+else
 LDFLAGS +=-T$(SUBMDL)-ROM.ld
 endif
 
 
 # ---------------------------------------------------------------------------
-# Flash-Programming support using lpc21isp by Martin Maurer 
+# Flash-Programming support using lpc21isp by Martin Maurer
 # only for Philips LPC and Analog ADuC ARMs
 #
 # Settings and variables:
 OBJCOPY = arm-elf-objcopy
 OBJDUMP = arm-elf-objdump
 SIZE = arm-elf-size
+AR = arm-elf-ar
 NM = arm-elf-nm
 REMOVE = rm -f
 COPY = cp
 
+
 # Define Messages
 # English
 MSG_ERRORS_NONE = Errors: none
 MSG_BEGIN = "-------- begin (mode: $(RUN_MODE)) --------"
 MSG_END = --------  end  --------
-MSG_SIZE_BEFORE = Size before: 
+MSG_SIZE_BEFORE = Size before:
 MSG_SIZE_AFTER = Size after:
 MSG_FLASH = Creating load file for Flash:
 MSG_EXTENDED_LISTING = Creating Extended Listing:
 # Define all object files.
 COBJ      = $(SRC:.c=.o)
 AOBJ      = $(ASRC:.S=.o)
-COBJARM   = $(SRCARM:.c=.o) $(TARGET)_img.o $(TARGET)_nat.o
+COBJARM   = $(SRCARM:.c=.o)
 AOBJARM   = $(ASRCARM:.S=.o)
-CPPOBJ    = $(CPPSRC:.cpp=.o) 
+CPPOBJ    = $(CPPSRC:.cpp=.o)
 CPPOBJARM = $(CPPSRCARM:.cpp=.o)
 
 # Define all listing files.
 
 # Compiler flags to generate dependency files.
 ### GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,.dep/$(@F).d
-GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d
+#GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d
 
 # Combine all necessary flags and optional flags.
 # Add target processor to flags.
-ALL_CFLAGS  = -mcpu=$(MCU) $(THUMB_IW) -I. $(CFLAGS) $(GENDEPFLAGS)
-ALL_ASFLAGS = -mcpu=$(MCU) $(THUMB_IW) -I. -x assembler-with-cpp $(ASFLAGS)
+ALL_CFLAGS  = -mcpu=$(MCU) $(THUMB) $(THUMB_IW) -I. $(CFLAGS) $(GENDEPFLAGS)
+ALL_ASFLAGS = -mcpu=$(MCU) $(THUMB) $(THUMB_IW) -I. -x assembler-with-cpp $(ASFLAGS)
 
 
 # Default target.
-all: begin gccversion sizebefore build sizeafter finished end
+all: begin gccversion pmvm sizebefore build sizeafter finished end
 
 ifeq ($(FORMAT),ihex)
-build: elf hex lss sym
+build: elf hex bin lss sym
 hex: $(TARGET).hex
 IMGEXT=hex
-else 
+else
 ifeq ($(FORMAT),binary)
 build: elf bin lss sym
 bin: $(TARGET).bin
 IMGEXT=bin
-else 
+else
 $(error "$(MSG_FORMATERROR) $(FORMAT)")
 endif
 endif
 
 elf: $(TARGET).elf
-lss: $(TARGET).lss 
+lss: $(TARGET).lss
 sym: $(TARGET).sym
 
+# PyMite: Build the VM archive if it doesn't exist
+pmvm : $(PM_LIB_PATH)
+
+$(PM_LIB_PATH) :
+	make -C ../../vm
+
 # Eye candy.
 begin:
 	@echo
 
 
 # Display compiler version information.
-gccversion : 
+gccversion :
 	@$(CC) --version
 
 
 # Program the device.
 ifeq ($(FLASH_TOOL),UVISION)
-# Program the device with Keil's uVision (needs configured uVision-Workspace). 
+# Program the device with Keil's uVision (needs configured uVision-Workspace).
 program: $(TARGET).$(IMGEXT)
 	@echo
 	@echo "Programming with uVision"
 	@echo
 	@echo $(MSG_FLASH) $@
 	$(OBJCOPY) -O $(FORMAT) $< $@
-	
+
 # Create final output file (.bin) from ELF output file.
 %.bin: %.elf
 	@echo
 %.elf:  $(AOBJARM) $(AOBJ) $(COBJARM) $(COBJ) $(CPPOBJ) $(CPPOBJARM)
 	@echo
 	@echo $(MSG_LINKING) $@
-#	$(CC) $(THUMB) $(AOBJARM) $(AOBJ) $(COBJARM) $(COBJ) $(CPPOBJ) $(CPPOBJARM) --output $@ $(LDFLAGS)
 	$(CC) $(THUMB) $(ALL_CFLAGS) $(AOBJARM) $(AOBJ) $(COBJARM) $(COBJ) $(CPPOBJ) $(CPPOBJARM) --output $@ $(LDFLAGS)
-#	$(CPP) $(THUMB) $(ALL_CFLAGS) $(AOBJARM) $(AOBJ) $(COBJARM) $(COBJ) $(CPPOBJ) $(CPPOBJARM) --output $@ $(LDFLAGS)
 
 # Compile: create object files from C source files. ARM/Thumb
 $(COBJ) : %.o : %.c
 	@echo
 	@echo $(MSG_COMPILING) $<
-	$(CC) -c $(THUMB) $(ALL_CFLAGS) $(CONLYFLAGS) $< -o $@ 
+	$(CC) -c $(THUMB) $(ALL_CFLAGS) $(CONLYFLAGS) $< -o $@
 
 # Compile: create object files from C source files. ARM-only
 $(COBJARM) : %.o : %.c
 	@echo
 	@echo $(MSG_COMPILING_ARM) $<
-	$(CC) -c $(ALL_CFLAGS) $(CONLYFLAGS) $< -o $@ 
+	$(CC) -c $(ALL_CFLAGS) $(CONLYFLAGS) $< -o $@
 
 # Compile: create object files from C++ source files. ARM/Thumb
 $(CPPOBJ) : %.o : %.cpp
 	@echo
 	@echo $(MSG_COMPILINGCPP) $<
-	$(CPP) -c $(THUMB) $(ALL_CFLAGS) $(CPPFLAGS) $< -o $@ 
+	$(CPP) -c $(THUMB) $(ALL_CFLAGS) $(CPPFLAGS) $< -o $@
 
 # Compile: create `object files from C++ source files. ARM-only
 $(CPPOBJARM) : %.o : %.cpp
 	@echo
 	@echo $(MSG_COMPILINGCPP_ARM) $<
-	$(CPP) -c $(ALL_CFLAGS) $(CPPFLAGS) $< -o $@ 
+	$(CPP) -c $(ALL_CFLAGS) $(CPPFLAGS) $< -o $@
 
 
 # Compile: create assembler files from C source files. ARM/Thumb
 	$(CC) -c $(ALL_ASFLAGS) $< -o $@
 
 
-# PyMite: The native fxn table and bytecode image are generated from python source
-$(TARGET)_nat.c $(TARGET)_img.c: $(TARGET).py
-	$(PMIMGCREATOR) -c -u -o $(TARGET)_img.c --native-file=$(TARGET)_nat.c $(TARGET).py
-
+# PyMite: Generate native code and module images from the python source
+$(TARGET)_nat.c $(TARGET)_img.c : $(PM_USR_SOURCES)
+	$(PMIMGCREATOR) -c -u -o $(TARGET)_img.c --native-file=$(TARGET)_nat.c $(PM_USR_SOURCES)
 
 
 # Target: clean project.
 
 
 clean_list :
+	$(MAKE) -C ../../vm clean
 	@echo
 	@echo $(MSG_CLEANING)
-	$(REMOVE) ../Common_WinARM/$(TARGET).hex
 	$(REMOVE) $(TARGET).hex
 	$(REMOVE) $(TARGET).bin
 	$(REMOVE) $(TARGET).obj
 	$(REMOVE) $(SRC:.c=.d)
 	$(REMOVE) $(SRCARM:.c=.s)
 	$(REMOVE) $(SRCARM:.c=.d)
-	$(REMOVE) $(CPPSRC:.cpp=.s) 
+	$(REMOVE) $(CPPSRC:.cpp=.s)
 	$(REMOVE) $(CPPSRC:.cpp=.d)
-	$(REMOVE) $(CPPSRCARM:.cpp=.s) 
+	$(REMOVE) $(CPPSRCARM:.cpp=.s)
 	$(REMOVE) $(CPPSRCARM:.cpp=.d)
-	$(REMOVE) .dep/*
+#	$(REMOVE) .dep/*
+	$(REMOVE) $(TARGET)_img.c
+	$(REMOVE) $(TARGET)_nat.c
 
 
 # Include the dependency files.
 
 # Listing of phony targets.
 .PHONY : all begin finish end sizebefore sizeafter gccversion \
-build elf hex bin lss sym clean clean_list program
+build elf hex bin lss sym clean clean_list program pmvm
 
+
+export CC OBJCOPY NM CFLAGS ALL_CFLAGS AR IPM PM_HEAP_SIZE PM_LIB_FN

src/platform/at91sam7s-ek/main.c

+/*
+ * PyMite - A flyweight Python interpreter for 8-bit and larger microcontrollers.
+ * Copyright 2002 Dean Hall.  All rights reserved.
+ * PyMite is offered through one of two licenses: commercial or open-source.
+ * See the LICENSE file at the root of this package for licensing details.
+ */
+
+
+#include "Board.h"
+#include "pm.h"
+
+
+extern unsigned char usrlib_img[];
+
+
+int
+main(void)
+{
+    PmReturn_t retval;
+
+    /* Init PyMite */
+    retval = pm_init(MEMSPACE_PROG, usrlib_img);
+
+    /* Configure PIOA for LEDs and clear them */
+    AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, LED_MASK);
+    AT91F_PIO_SetOutput(AT91C_BASE_PIOA, LED_MASK);
+
+    PM_RETURN_IF_ERROR(retval);
+
+    /* Run the sample program */
+    retval = pm_run((uint8_t *)"main");
+
+    /* Report results via LEDs */
+    if (retval == PM_RET_OK)
+    {
+        AT91F_PIO_SetOutput(AT91C_BASE_PIOA, LED_MASK);
+        AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, 0x03);
+    }
+    else
+    {
+        AT91F_PIO_SetOutput(AT91C_BASE_PIOA, LED_MASK);
+        AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, 0x04);
+    }
+    return (int)retval;
+}

src/platform/at91sam7s-ek/main.py

+#
+# PyMite - A flyweight Python interpreter for 8-bit and larger microcontrollers.
+# Copyright 2002 Dean Hall.  All rights reserved.
+# PyMite is offered through one of two licenses: commercial or open-source.
+# See the LICENSE file at the root of this package for licensing details.
+#
+
+#
+# Sample program for ARM target (Atmel AT91SAM7S64 chip on a AT91SAM7S-EK board)
+#
+"""__NATIVE__
+#include "Board.h"
+"""
+
+
+def get_buttons():
+    """__NATIVE__
+    PmReturn_t retval = PM_RET_OK;
+    uint32_t val = 0;
+    pPmObj_t pint;
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 0)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Collect the button input as bits in an int */
+    if ((AT91F_PIO_GetInput(AT91C_BASE_PIOA) & SW1_MASK) == 0)
+    {
+        val |= 0x01;
+    }
+    if ((AT91F_PIO_GetInput(AT91C_BASE_PIOA) & SW2_MASK) == 0)
+    {
+        val |= 0x02;
+    }
+    if ((AT91F_PIO_GetInput(AT91C_BASE_PIOA) & SW3_MASK) == 0)
+    {
+        val |= 0x04;
+    }
+    if ((AT91F_PIO_GetInput(AT91C_BASE_PIOA) & SW4_MASK) == 0)
+    {
+        val |= 0x08;
+    }
+
+    retval = int_new(val, &pint);
+    NATIVE_SET_TOS(pint);
+
+    return retval;
+    """
+    pass
+
+
+def set_leds(n):
+    """__NATIVE__
+    pPmObj_t pn;
+    int32_t n;
+    PmReturn_t retval;
+
+    /* If wrong number of args, raise TypeError */
+    if (NATIVE_GET_NUM_ARGS() != 1)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* If arg is not an int, raise TypeError */
+    pn = NATIVE_GET_LOCAL(0);
+    if (OBJ_GET_TYPE(pn) != OBJ_TYPE_INT)
+    {
+        PM_RAISE(retval, PM_RET_EX_TYPE);
+        return retval;
+    }
+
+    /* Get int value from the arg */
+    n = ((pPmInt_t)pn)->val;
+
+    /* Clear all and set the desired LEDs (active low) */
+    AT91F_PIO_SetOutput(AT91C_BASE_PIOA, LED_MASK);
+    AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, n);
+    NATIVE_SET_TOS(PM_NONE);
+    return PM_RET_OK;
+    """
+    pass
+
+
+import ipm
+ipm.ipm(globals())
+
+
+# :mode=c:

src/platform/at91sam7s-ek/plat.c

 /** PyMite platform-specific routines for ARM7 target */
 
 
-#include "../pm.h"
+#include "pm.h"
 
 #include "AT91SAM7S64.h"
 #include "lib_AT91SAM7S64.h"
+#include "Board.h"
 
 
 #define RTTC_INTERRUPT_LEVEL 0
     AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, (1 << AT91C_ID_PIOA)
                                                 | (1 << AT91C_ID_US0));
 
+    /* Configure PIOA for LEDs and clear them */
+    AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, LED_MASK);
+    AT91F_PIO_SetOutput(AT91C_BASE_PIOA, LED_MASK);
+
     /* Configure PIT interrupt */
     AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
                           AT91C_ID_SYS,

src/platform/at91sam7s-ek/sample.c

-/*
- * PyMite - A flyweight Python interpreter for 8-bit and larger microcontrollers.
- * Copyright 2002 Dean Hall.  All rights reserved.
- * PyMite is offered through one of two licenses: commercial or open-source.
- * See the LICENSE file at the root of this package for licensing details.
- */
-
-
-#include "Board.h"
-#include "pm.h"
-
-
-extern unsigned char usrlib_img[];
-
-
-int
-main(void)
-{
-    PmReturn_t retval;
-
-    /* Init PyMite */
-    retval = pm_init(MEMSPACE_PROG, usrlib_img);
-
-    /* Configure PIOA for LEDs and clear them */
-    AT91F_PIO_CfgOutput(AT91C_BASE_PIOA, LED_MASK);
-    AT91F_PIO_SetOutput(AT91C_BASE_PIOA, LED_MASK);
-
-    PM_RETURN_IF_ERROR(retval);
-
-    /* Run the sample program */
-    retval = pm_run((uint8_t *)"sample");
-
-    /* Report results via LEDs */
-    if (retval == PM_RET_OK)
-    {
-        AT91F_PIO_SetOutput(AT91C_BASE_PIOA, LED_MASK);
-        AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, 0x03);
-    }
-    else
-    {
-        AT91F_PIO_SetOutput(AT91C_BASE_PIOA, LED_MASK);
-        AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, 0x04);
-    }
-    return (int)retval;
-}

src/platform/at91sam7s-ek/sample.py

-#
-# PyMite - A flyweight Python interpreter for 8-bit and larger microcontrollers.
-# Copyright 2002 Dean Hall.  All rights reserved.
-# PyMite is offered through one of two licenses: commercial or open-source.
-# See the LICENSE file at the root of this package for licensing details.
-#
-
-#
-# Sample program for ARM target (Atmel AT91SAM7S64 chip on a AT91SAM7S-EK board)
-#
-"""__NATIVE__
-#include "Board.h"
-"""
-
-
-def get_buttons():
-    """__NATIVE__
-    PmReturn_t retval = PM_RET_OK;
-    uint32_t val = 0;
-    pPmObj_t pint;
-
-    /* If wrong number of args, raise TypeError */
-    if (NATIVE_GET_NUM_ARGS() != 0)
-    {
-        PM_RAISE(retval, PM_RET_EX_TYPE);
-        return retval;
-    }
-
-    /* Collect the button input as bits in an int */
-    if ((AT91F_PIO_GetInput(AT91C_BASE_PIOA) & SW1_MASK) == 0)
-    {
-        val |= 0x01;
-    }
-    if ((AT91F_PIO_GetInput(AT91C_BASE_PIOA) & SW2_MASK) == 0)
-    {
-        val |= 0x02;
-    }
-    if ((AT91F_PIO_GetInput(AT91C_BASE_PIOA) & SW3_MASK) == 0)
-    {
-        val |= 0x04;
-    }
-    if ((AT91F_PIO_GetInput(AT91C_BASE_PIOA) & SW4_MASK) == 0)
-    {
-        val |= 0x08;
-    }
-
-    retval = int_new(val, &pint);
-    NATIVE_SET_TOS(pint);
-
-    return retval;
-    """
-    pass
-
-
-def set_leds(n):
-    """__NATIVE__
-    pPmObj_t pn;
-    int32_t n;
-    PmReturn_t retval;
-
-    /* If wrong number of args, raise TypeError */
-    if (NATIVE_GET_NUM_ARGS() != 1)
-    {
-        PM_RAISE(retval, PM_RET_EX_TYPE);
-        return retval;
-    }
-
-    /* If arg is not an int, raise TypeError */
-    pn = NATIVE_GET_LOCAL(0);
-    if (OBJ_GET_TYPE(pn) != OBJ_TYPE_INT)
-    {
-        PM_RAISE(retval, PM_RET_EX_TYPE);
-        return retval;
-    }
-
-    /* Get int value from the arg */
-    n = ((pPmInt_t)pn)->val;
-
-    /* Clear all and set the desired LEDs (active low) */
-    AT91F_PIO_SetOutput(AT91C_BASE_PIOA, LED_MASK);
-    AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, n);
-    NATIVE_SET_TOS(PM_NONE);
-    return PM_RET_OK;
-    """
-    pass
-
-
-import ipm
-ipm.ipm(globals())
-
-
-# :mode=c:

src/platform/avr/Makefile

 
 
 # PyMite Configuration
-LIBNATIVE_SOURCES =
+PLATFORM := $(notdir $(CURDIR))
+PM_LIB_ROOT = pmvm.$(PLATFORM)
+PM_LIB_FN = lib$(PM_LIB_ROOT).a
+PM_LIB_PATH = ../../vm/$(PM_LIB_FN)
+PM_USR_SOURCES = main.py ../../lib/avr.py
+PM_HEAP_SIZE = 0x0D00
 PMIMGCREATOR := ../../tools/pmImgCreator.py
-PM_HEAP_SIZE = 0x0D00
 
 
-# MCU name
+# Platform Configuration
 MCU = atmega103
 F_CPU = 4000000UL
+UART_BAUD = 19200UL
+
 
 # Output format. (can be srec, ihex, binary)
 FORMAT = ihex
 
 # Target file name (without extension).
-TARGET = sample
+TARGET = main
 
 
 # List C source files here. (C dependencies are automatically generated.)
-SRC = $(TARGET).c
+SRC = $(TARGET).c plat.c $(TARGET)_nat.c $(TARGET)_img.c
 
 
 # List Assembler source files here.
 # Debugging format.
 # Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
 # AVR (extended) COFF requires stabs, plus an avr-objcopy run.
-DEBUG = stabs
+DEBUG_FMT = stabs
 
 # List any extra directories to look for include files here.
 #     Each directory must be seperated by a space.
 CSTANDARD = -std=gnu99
 
 # Place -D or -U options here
-CDEFS = -D F_CPU=$(F_CPU) -D HEAP_SIZE=$(PM_HEAP_SIZE) -D TARGET_AVR
+CDEFS = -DF_CPU=$(F_CPU) -DUART_BAUD=$(UART_BAUD)
+# PyMite CDEFS
+CDEFS += -DHEAP_SIZE=$(PM_HEAP_SIZE) 
+ifeq ($(DEBUG),true)
+	CDEFS += -g -g$(DEBUG_FMT) -D__DEBUG__=1
+endif
 
 # Place -I options here
 CINCS = -I../../vm
 #  -Wall...:     warning level
 #  -Wa,...:      tell GCC to pass this to the assembler.
 #    -adhlns...: create assembler listing
-CFLAGS = -g$(DEBUG)
-CFLAGS += $(CDEFS) $(CINCS)
+CFLAGS = $(CDEFS) $(CINCS)
 CFLAGS += -O$(OPT)
 CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
 CFLAGS += -Wall -Wstrict-prototypes -Werror
-CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
 CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
 CFLAGS += $(CSTANDARD)
 
 
-
 # Assembler flags.
 #  -Wa,...:   tell GCC to pass this to the assembler.
 #  -ahlms:    create listing
 LDFLAGS += $(EXTMEMOPTS)
 LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
 # PyMite
-LDFLAGS += -L../../vm -lpmvm -L.
+LDFLAGS += -L../../vm -l$(PM_LIB_ROOT) -L.
 
 
 
 OBJCOPY = avr-objcopy
 OBJDUMP = avr-objdump
 SIZE = avr-size
+AR = avr-ar
 NM = avr-nm
 AVRDUDE = avrdude
 REMOVE = rm -f
 MSG_COMPILING = Compiling:
 MSG_ASSEMBLING = Assembling:
 MSG_CLEANING = Cleaning project:
-MSG_PMVM = Building PyMite VM archive
-
 
 
 # Define all object files.
-OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) $(TARGET)_img.o $(TARGET)_nat.o
+OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
 
 # Define all listing files.
 LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
 
 
 # Default target.
-all: pmvm begin gccversion sizebefore build sizeafter finished end
+all: begin gccversion sizebefore pmvm build sizeafter finished end
 
 build: elf hex eep lss sym
 
 sym: $(TARGET).sym
 
 
-#
-# Build the PyMite VM archive if it doesn't exist
-#
-pmvm:
-	@echo $(MSG_PMVM)
-	make -C ../../vm TARGET=AVR HEAP_SIZE=$(PM_HEAP_SIZE)
+# PyMite: Build the VM archive if it doesn't exist
+pmvm : $(PM_LIB_PATH)
+
+$(PM_LIB_PATH) : ../../vm/*.c ../../vm/*.h
+	make -C ../../vm
 
 
 # Eye candy.
 	$(CC) -c $(ALL_ASFLAGS) $< -o $@
 
 # PyMite: The native fxn table and bytecode image are generated from python source
-$(TARGET)_nat.c $(TARGET)_img.c: $(TARGET).py
-	$(PMIMGCREATOR) -c -u --memspace=flash -o $(TARGET)_img.c --native-file=$(TARGET)_nat.c $(TARGET).py $(LIBNATIVE_SOURCES)
+$(TARGET)_nat.c $(TARGET)_img.c: $(PM_USR_SOURCES)
+	$(PMIMGCREATOR) -c -u --memspace=flash -o $(TARGET)_img.c --native-file=$(TARGET)_nat.c $(PM_USR_SOURCES)
 
 
 # Target: clean project.
 
 # Listing of phony targets.
 .PHONY : all begin finish end sizebefore sizeafter gccversion \
-build elf hex eep lss sym coff extcoff \
-clean clean_list program
+build elf hex eep lss sym coff extcoff clean clean_list program pmvm
+
+
+export CC OBJCOPY NM CFLAGS ALL_CFLAGS AR IPM PM_HEAP_SIZE PM_LIB_FN

src/platform/avr/main.c

+/*
+ * PyMite - A flyweight Python interpreter for 8-bit and larger microcontrollers.
+ * Copyright 2002 Dean Hall.  All rights reserved.
+ * PyMite is offered through one of two licenses: commercial or open-source.
+ * See the LICENSE file at the root of this package for licensing details.
+ */
+
+/** Sample PyMite application */
+
+
+#include "pm.h"
+
+
+extern unsigned char usrlib_img[];
+
+
+int main(void)
+{
+    PmReturn_t retval;
+
+    retval = pm_init(MEMSPACE_PROG, usrlib_img);
+    PM_RETURN_IF_ERROR(retval);
+
+    retval = pm_run((uint8_t *)"main");
+    return (int)retval;
+}

src/platform/avr/main.py

+#
+# PyMite - A flyweight Python interpreter for 8-bit and larger microcontrollers.
+# Copyright 2002 Dean Hall.  All rights reserved.
+# PyMite is offered through one of two licenses: commercial or open-source.
+# See the LICENSE file at the root of this package for licensing details.
+#
+
+#
+# This is a sample application that calls functions in the AVR module.
+#
+
+"""__NATIVE__
+#include <avr/io.h>
+"""
+
+
+print "Hello world."
+
+
+#
+# Initialize the AVR's port A pin direction
+#
+def init():
+    """__NATIVE__
+    /* Set port A pins as all outputs */
+    DDRA = 0xFF;
+    NATIVE_SET_TOS(PM_NONE);
+
+    return PM_RET_OK;
+    """
+    pass
+
+init()
+import avr
+avr.portA(0xaa)
+
+
+print "Expect a NameError (0xEA) after this."
+foo()

src/platform/avr/plat.c

 #include <avr/pgmspace.h>
 #include <avr/eeprom.h>
 
-#include "../pm.h"
+#include "pm.h"
 
 
 /**

src/platform/avr/sample.c

-/*
- * PyMite - A flyweight Python interpreter for 8-bit and larger microcontrollers.
- * Copyright 2002 Dean Hall.  All rights reserved.
- * PyMite is offered through one of two licenses: commercial or open-source.
- * See the LICENSE file at the root of this package for licensing details.
- */
-
-/** Sample PyMite application */
-
-
-#include "pm.h"
-
-
-extern unsigned char usrlib_img[];
-
-
-int main(void)
-{
-    PmReturn_t retval;
-
-    retval = pm_init(MEMSPACE_PROG, usrlib_img);
-    PM_RETURN_IF_ERROR(retval);
-
-    retval = pm_run((uint8_t *)"sample");
-    return (int)retval;
-}

src/platform/avr/sample.py

-#
-# PyMite - A flyweight Python interpreter for 8-bit and larger microcontrollers.
-# Copyright 2002 Dean Hall.  All rights reserved.
-# PyMite is offered through one of two licenses: commercial or open-source.
-# See the LICENSE file at the root of this package for licensing details.
-#
-
-#
-# This is a sample application that calls functions in the AVR module.
-#
-
-"""__NATIVE__
-#include <avr/io.h>
-"""
-
-
-print "Hello world."
-
-
-#
-# Initialize the AVR's port A pin direction
-#
-def init():
-    """__NATIVE__
-    /* Set port A pins as all outputs */
-    DDRA = 0xFF;
-    NATIVE_SET_TOS(PM_NONE);
-
-    return PM_RET_OK;
-    """
-    pass
-
-init()
-import avr
-avr.portA(0xaa)
-
-
-print "Expect a NameError (0xEA) after this."
-foo()

src/platform/desktop/Makefile

-SHELL = /bin/sh
+# PyMite Configuration
+PLATFORM := $(notdir $(CURDIR))
+PM_LIB_ROOT = pmvm.$(PLATFORM)
+PM_LIB_FN = lib$(PM_LIB_ROOT).a
+PM_LIB_PATH = ../../vm/$(PM_LIB_FN)
+PM_USR_SOURCES = main.py
+PM_HEAP_SIZE = 0x2000
+PMIMGCREATOR := ../../tools/pmImgCreator.py
 
-TARGET ?= DESKTOP
-HEAP_SIZE ?= 0xF000
+TARGET = main
+SOURCES = $(TARGET).c plat.c $(TARGET)_nat.c $(TARGET)_img.c
+OBJS = $(SOURCES:.c=.o)
 
-PMIMGCREATOR := ../../tools/pmImgCreator.py
-VM_LIB := ../../vm/libpmvm.a
-CDEFS = -DHEAP_SIZE=$(HEAP_SIZE) -DTARGET_$(TARGET) -D__DEBUG__=1
-CFLAGS = -g -ggdb -Os -Wall -gstabs -Wstrict-prototypes -Werror -ansi $(CDEFS)
-CFLAGS += -I../../vm
-SOURCES = main.c
-PY_SOURCES = main.py
-EXECS = $(SOURCES:.c=.out)
-IMG_SOURCES = $(subst .py,_img.c, $(PY_SOURCES))
-NAT_SOURCES = $(subst .py,_nat.c, $(PY_SOURCES))
+CDEFS = -DHEAP_SIZE=$(PM_HEAP_SIZE)
+ifeq ($(DEBUG),true)
+	CDEFS += -g -ggdb -D__DEBUG__=1
+endif
+CFLAGS = -Os -Wall -gstabs -Wstrict-prototypes -Werror -ansi -I../../vm $(CDEFS)
 
-# Build an executable from the C sources
 %.out : %*_nat.c %*_img.c %.c
 	$(CC) $(CFLAGS) -o $@ $*_nat.c $*_img.c $*.c ../../vm/libpmvm.a
 
-# The module images and native code are generated from python source
-%*_nat.c %*_img.c : %.py
-	$(PMIMGCREATOR) -c -u -o $*_img.c --native-file=$*_nat.c $*.py $(PMSTDLIB_SOURCES)
+.PHONY: all clean
 
-.PHONY: all vm clean
+export CFLAGS IPM HEAP_SIZE PM_LIB_FN
 
-# Default action is to build main; run main if target is desktop
-all : vm $(EXECS)
+all : $(TARGET).out
 
-vm : $(VM_LIB)
-	make -C ../../vm
+$(PM_LIB_PATH) : ../../vm/*.c ../../vm/*.h
+	make -C ../../vm IPM=true
 
-# Removes files made by default make
+$(TARGET).out : $(OBJS) $(PM_LIB_PATH)
+	$(CC) -o $@ $(OBJS) $(PM_LIB_PATH)
+
+# Generate native code and module images from the python source
+$(TARGET)_nat.c $(TARGET)_img.c: $(PM_USR_SOURCES)
+	$(PMIMGCREATOR) -c -u -o $(TARGET)_img.c --native-file=$(TARGET)_nat.c $(PM_USR_SOURCES)
+
 clean :
-	$(RM) $(EXECS)
-	$(RM) $(IMG_SOURCES)
-	$(RM) $(NAT_SOURCES)
+	$(MAKE) -C ../../vm clean
+	$(RM) $(OBJS) $(TARGET)_img.* $(TARGET)_nat.*

src/platform/desktop/plat.c

 #include <unistd.h>
 #include <signal.h>
 #include <string.h>
-#include "../pm.h"
+
+#include "pm.h"
 
 
 void plat_sigalrm_handler(int signal);

src/platform/mmb103/Makefile

 
 
 # PyMite Configuration
-LIBNATIVE_SOURCES = mmb.py
-#LIBNATIVE_SOURCES =
+PLATFORM := $(notdir $(CURDIR))
+PM_LIB_ROOT = pmvm.$(PLATFORM)
+PM_LIB_FN = lib$(PM_LIB_ROOT).a
+PM_LIB_PATH = ../../vm/$(PM_LIB_FN)
+PM_USR_SOURCES = main.py mmb.py
+PM_HEAP_SIZE = 0x0D00
 PMIMGCREATOR := ../../tools/pmImgCreator.py
-PM_HEAP_SIZE = 0x0D00
 
 
-# MCU name
+# Platform Configuration
 MCU = atmega103
 F_CPU = 4000000UL
+UART_BAUD = 19200UL
+
 
 # Output format. (can be srec, ihex, binary)
 FORMAT = ihex
 
 
 # List C source files here. (C dependencies are automatically generated.)
-SRC = $(TARGET).c
+SRC = $(TARGET).c plat.c $(TARGET)_nat.c $(TARGET)_img.c
 
 
 # List Assembler source files here.
 # Debugging format.
 # Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
 # AVR (extended) COFF requires stabs, plus an avr-objcopy run.
-DEBUG = stabs
+DEBUG_FMT = stabs
 
 # List any extra directories to look for include files here.
 #     Each directory must be seperated by a space.
-EXTRAINCDIRS =
+EXTRAINCDIRS = ../../vm
 
 
 # Compiler flag to set the C Standard level.
 CSTANDARD = -std=gnu99
 
 # Place -D or -U options here
-CDEFS = -D F_CPU=$(F_CPU) -D HEAP_SIZE=$(PM_HEAP_SIZE) -D TARGET_AVR
+CDEFS = -DF_CPU=$(F_CPU) -DUART_BAUD=$(UART_BAUD)
+# PyMite CDEFS
+CDEFS += -DHEAP_SIZE=$(PM_HEAP_SIZE) 
+ifeq ($(DEBUG),true)
+	CDEFS += -g -g$(DEBUG_FMT) -D__DEBUG__=1
+endif
 
 # Place -I options here
-CINCS = -I../../vm
+CINCS =
 
 
 # Compiler flags.
 #  -Wall...:     warning level
 #  -Wa,...:      tell GCC to pass this to the assembler.
 #    -adhlns...: create assembler listing
-CFLAGS = -g$(DEBUG)
-CFLAGS += $(CDEFS) $(CINCS)
+CFLAGS = $(CDEFS) $(CINCS)
 CFLAGS += -O$(OPT)
 CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
 CFLAGS += -Wall -Wstrict-prototypes -Werror
-CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
+CFLAGS += -Wa,-adhlns=$(subst $(suffix $<),.lst,$<)
 CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
 CFLAGS += $(CSTANDARD)
-
+# PyMite CFLAGS
+#CFLAGS += -ansi # Removed because it causes a build error
 
 
 # Assembler flags.
 LDFLAGS += $(EXTMEMOPTS)
 LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
 # PyMite
-LDFLAGS += -L../../vm -lpmvm -L. -lmmb103
+LDFLAGS += -L../../vm -l$(PM_LIB_ROOT) -L. -lmmb103
 
 
 
 OBJCOPY = avr-objcopy
 OBJDUMP = avr-objdump
 SIZE = avr-size
+AR = avr-ar
 NM = avr-nm
 AVRDUDE = avrdude
 REMOVE = rm -f
 COPY = cp
 
 
-
-
 # Define Messages
 # English
 MSG_ERRORS_NONE = Errors: none
 MSG_COMPILING = Compiling:
 MSG_ASSEMBLING = Assembling:
 MSG_CLEANING = Cleaning project:
-MSG_PMVM = Building PyMite VM archive
-
 
 
 # Define all object files.
-OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) $(TARGET)_img.o $(TARGET)_nat.o
+OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
 
 # Define all listing files.
 LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
 ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
 
 
-
-
-
 # Default target.
-all: pmvm begin gccversion sizebefore build sizeafter finished end
+all: begin gccversion pmvm sizebefore build sizeafter finished end
 
 build: elf hex eep lss sym
 
 sym: $(TARGET).sym
 
 
-#
-# Build the PyMite VM archive if it doesn't exist
-#
-pmvm:
-	@echo $(MSG_PMVM)
-	make -C ../../vm TARGET=AVR HEAP_SIZE=$(PM_HEAP_SIZE)
+# PyMite: Build the VM archive if it doesn't exist
+pmvm : $(PM_LIB_PATH)
 
+$(PM_LIB_PATH) :
+	make -C ../../vm
 
 # Eye candy.
 # AVR Studio 3.x does not check make's exit code but relies on
 	@if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
 
 
-
 # Display compiler version information.
 gccversion :
 	@$(CC) --version
 
 
-
 # Program the device.
 program: $(TARGET).hex $(TARGET).eep
 	$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
 	$(CC) -c $(ALL_ASFLAGS) $< -o $@
 
 # PyMite: The native fxn table and bytecode image are generated from python source
-$(TARGET)_nat.c $(TARGET)_img.c: $(TARGET).py
-	$(PMIMGCREATOR) -c -u --memspace=flash -o $(TARGET)_img.c --native-file=$(TARGET)_nat.c $(TARGET).py $(LIBNATIVE_SOURCES)
+$(TARGET)_nat.c $(TARGET)_img.c: $(PM_USR_SOURCES)
+	$(PMIMGCREATOR) -c -u --memspace=flash -o $(TARGET)_img.c --native-file=$(TARGET)_nat.c $(PM_USR_SOURCES)
 
 
 # Target: clean project.
 
 # Listing of phony targets.
 .PHONY : all begin finish end sizebefore sizeafter gccversion \
-build elf hex eep lss sym coff extcoff \
-clean clean_list program
+build elf hex eep lss sym coff extcoff clean clean_list program pmvm
+
+
+export CC OBJCOPY NM CFLAGS ALL_CFLAGS AR IPM PM_HEAP_SIZE PM_LIB_FN

src/platform/mmb103/plat.c

 #include <avr/pgmspace.h>
 #include <avr/eeprom.h>
 
-#include "../pm.h"
+#include "pm.h"
 
 
 /**

src/tests/system/Makefile

 SHELL = /bin/sh
 
-TARGET ?= DESKTOP
-HEAP_SIZE ?= 0x2000
-TARGET_MCU ?= atmega103
+# PyMite Configuration
+PLATFORM ?= desktop
+PM_LIB_ROOT = pmvm.$(PLATFORM)
+PM_LIB_FN = lib$(PM_LIB_ROOT).a
+PM_LIB_PATH = ../../vm/$(PM_LIB_FN)
+PM_USR_SOURCES = $(SOURCES:.c=.py)
+PM_HEAP_SIZE = 0x2000
+PMIMGCREATOR := ../../tools/pmImgCreator.py
+DEBUG = false
 
-PMIMGCREATOR := ../../tools/pmImgCreator.py
-CDEFS = -DHEAP_SIZE=$(HEAP_SIZE) -DTARGET_$(TARGET) -D__DEBUG__=1
-CFLAGS = -g -ggdb -Os -Wall -gstabs -Wstrict-prototypes -Werror $(CDEFS)
-CFLAGS += -I../../vm
 SOURCES = $(wildcard t???.c)
-PY_SOURCES = $(SOURCES:.c=.py)
 EXECS = $(SOURCES:.c=.out)
-IMG_SOURCES = $(subst .py,_img.c, $(PY_SOURCES))
-NAT_SOURCES = $(subst .py,_nat.c, $(PY_SOURCES))
+IMG_SOURCES = $(subst .py,_img.c, $(PM_USR_SOURCES))
+NAT_SOURCES = $(subst .py,_nat.c, $(PM_USR_SOURCES))
 
-ifeq ($(TARGET), DESKTOP)
-	CFLAGS += -ansi
+CDEFS = -DHEAP_SIZE=$(PM_HEAP_SIZE)
+ifeq ($(DEBUG),true)
+	CDEFS += -g -ggdb -D__DEBUG__=1
 endif
-ifeq ($(TARGET), AVR)
-	AR = avr-ar
-	CC = avr-gcc
-	SIZE = avr-size
-	CFLAGS += -mmcu=$(TARGET_MCU) -DTARGET_MCU=$(TARGET_MCU)
-endif
+CFLAGS = -Os -Wall -Wstrict-prototypes -Werror $(CDEFS) -ansi -I../../vm
+
 
 # Build an executable from the C sources
-%.out : %*_nat.c %*_img.c %.c
-	$(CC) $(CFLAGS) -o $@ $*_nat.c $*_img.c $*.c ../../vm/libpmvm.a
-ifeq ($(TARGET), DESKTOP)
+%.out : %*_nat.c %*_img.c %.c plat.o
+	$(CC) $(CFLAGS) -o $@ $*_nat.c $*_img.c $*.c plat.o $(PM_LIB_PATH)
+ifeq ($(PLATFORM), desktop)
 	$(addprefix ./,$@)
 endif
 
 
 .PHONY: all check clean
 
+export CFLAGS HEAP_SIZE PM_LIB_FN
+
 # Default action is to build tests; run tests if target is desktop
 all : check
 
-check : vm $(EXECS)
+check : $(PM_LIB_PATH) $(EXECS)
 
-vm :
-	make -C ../../vm DEBUG=true
+$(PM_LIB_PATH) : ../../vm/*.c ../../vm/*.h
+	make -C ../../vm
+
+plat.o : plat.c
+	$(CC) $(CFLAGS) -c -o $@ $<
 
 # Removes files made by default make
 clean :
 	$(RM) $(EXECS)
 	$(RM) $(IMG_SOURCES)
 	$(RM) $(NAT_SOURCES)
+	$(RM) plat.o

src/tests/system/plat.c

+/*
+ * PyMite - A flyweight Python interpreter for 8-bit and larger microcontrollers.
+ * Copyright 2002 Dean Hall.  All rights reserved.
+ * PyMite is offered through one of two licenses: commercial or open-source.
+ * See the LICENSE file at the root of this package for licensing details.
+ */
+
+
+#undef __FILE_ID__
+#define __FILE_ID__ 0x50
+
+
+/** PyMite platform-specific routines for Desktop target */
+
+
+/* PyMite build process uses -ansi which disables certain features that
+ * in turn disable features needed for signal processing. To work around
+ * this, temporarily disable the corresponding #define. This is not
+ * needed for Cygwin but for Linux. The -ansi option of GCC is explained
+ * here: http://gcc.gnu.org/onlinedocs/gcc-4.0.3/gcc/C-Dialect-Options.html
+ */
+#ifdef __STRICT_ANSI__
+#undef __STRICT_ANSI__
+#include <stdio.h>
+#define __STRICT_ANSI__
+#else
+#include <stdio.h>
+#endif
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+
+#include "pm.h"
+
+
+void plat_sigalrm_handler(int signal);
+
+
+/* Desktop target shall use stdio for I/O routines. */
+PmReturn_t
+plat_init(void)
+{
+    /* Let POSIX' SIGALRM fire every full millisecond. */
+    /*
+     * #67 Using sigaction complicates the use of getchar (below),
+     * so signal() is used instead.
+     */
+    signal(SIGALRM, plat_sigalrm_handler);
+    ualarm(1000, 1000);
+
+    return PM_RET_OK;
+}
+
+
+void
+plat_sigalrm_handler(int signal)
+{
+    PmReturn_t retval;
+    retval = pm_vmPeriodic(1000);
+    PM_REPORT_IF_ERROR(retval);
+}
+
+
+/*
+ * Gets a byte from the address in the designated memory space
+ * Post-increments *paddr.
+ */
+uint8_t
+plat_memGetByte(PmMemSpace_t memspace, uint8_t const **paddr)
+{
+    uint8_t b = 0;
+
+    switch (memspace)
+    {
+        case MEMSPACE_RAM:
+        case MEMSPACE_PROG:
+            b = **paddr;
+            *paddr += 1;
+            return b;
+
+        case MEMSPACE_EEPROM:
+        case MEMSPACE_SEEPROM:
+        case MEMSPACE_OTHER0:
+        case MEMSPACE_OTHER1:
+        case MEMSPACE_OTHER2:
+        case MEMSPACE_OTHER3:
+        default:
+            return 0;
+    }
+}
+
+
+/* Desktop target shall use stdio for I/O routines */
+PmReturn_t
+plat_getByte(uint8_t *b)
+{
+    int c;
+    PmReturn_t retval = PM_RET_OK;
+
+    c = getchar();
+    *b = c & 0xFF;
+
+    if (c == EOF)
+    {
+        PM_RAISE(retval, PM_RET_EX_IO);
+    }
+
+    return retval;
+}
+
+
+/* Desktop target shall use stdio for I/O routines */
+PmReturn_t
+plat_putByte(uint8_t b)
+{
+    int i;
+    PmReturn_t retval = PM_RET_OK;
+
+    i = putchar(b);
+    fflush(stdout);
+
+    if ((i != b) || (i == EOF))
+    {
+        PM_RAISE(retval, PM_RET_EX_IO);
+    }
+
+    return retval;
+}
+
+
+PmReturn_t
+plat_getMsTicks(uint32_t *r_ticks)
+{
+    *r_ticks = pm_timerMsTicks;
+
+    return PM_RET_OK;
+}
+
+
+void
+plat_reportError(PmReturn_t result)
+{
+    /* Print error */
+    printf("Error:     0x%02X\n", result);
+    printf("  Release: 0x%02X\n", gVmGlobal.errVmRelease);
+    printf("  FileId:  0x%02X\n", gVmGlobal.errFileId);
+    printf("  LineNum: %d\n", gVmGlobal.errLineNum);
+
+    /* Print traceback */
+    {
+        pPmObj_t pframe;
+        pPmObj_t pstr;
+        PmReturn_t retval;
+
+        printf("Traceback (top first):\n");
+
+        /* Get the top frame */
+        pframe = (pPmObj_t)gVmGlobal.pthread->pframe;
+
+        /* If it's the native frame, print the native function name */
+        if (pframe == (pPmObj_t)&(gVmGlobal.nativeframe))
+        {
+
+            /* The last name in the names tuple of the code obj is the name */
+            retval = tuple_getItem((pPmObj_t)gVmGlobal.nativeframe.nf_func->
+                                   f_co->co_names, -1, &pstr);
+            if ((retval) != PM_RET_OK)
+            {
+                printf("  Unable to get native func name.\n");
+                return;
+            }
+            else
+            {
+                printf("  %s() __NATIVE__\n", ((pPmString_t)pstr)->val);
+            }
+
+            /* Get the frame that called the native frame */
+            pframe = (pPmObj_t)gVmGlobal.nativeframe.nf_back;
+        }
+
+        /* Print the remaining frame stack */
+        for (;
+             pframe != C_NULL;
+             pframe = (pPmObj_t)((pPmFrame_t)pframe)->fo_back)
+        {
+            /* The last name in the names tuple of the code obj is the name */
+            retval = tuple_getItem((pPmObj_t)((pPmFrame_t)pframe)->
+                                   fo_func->f_co->co_names, -1, &pstr);
+            if ((retval) != PM_RET_OK) break;
+
+            printf("  %s()\n", ((pPmString_t)pstr)->val);
+        }
+        printf("  <module>.\n");
+    }
+}
+

src/tests/unit/Makefile

 SHELL = /bin/sh
 
-TARGET ?= DESKTOP
-HEAP_SIZE ?= 0x1000
+# PyMite Configuration
+PLATFORM ?= desktop
+PM_LIB_ROOT = pmvm.$(PLATFORM)
+PM_LIB_FN = lib$(PM_LIB_ROOT).a
+PM_LIB_PATH = ../../vm/$(PM_LIB_FN)
+PM_HEAP_SIZE ?= 0x1000
+DEBUG = true
 
-CDEFS = -DHEAP_SIZE=$(HEAP_SIZE) -DTARGET_$(TARGET) -D__DEBUG__=1
-CFLAGS = -g -ggdb -I../../vm $(CDEFS)
 UT_SOURCES = $(wildcard ut*.c)
-ALL_SOURCES = runTests.c CuTest.c $(UT_SOURCES)
+ALL_SOURCES = runTests.c plat.c CuTest.c $(UT_SOURCES)
 OBJS = $(ALL_SOURCES:.c=.o)
 PRODUCT = runTests.out
 
-.PHONY: all check
+CDEFS = -DHEAP_SIZE=$(PM_HEAP_SIZE)
+ifeq ($(DEBUG),true)
+	CDEFS += -g -ggdb -D__DEBUG__=1
+endif
+CFLAGS = -I../../vm $(CDEFS)
+
+.PHONY: all check clean
+
+export CFLAGS IPM HEAP_SIZE PM_LIB_FN
 
 # Default action is to build and run tests
 all : check
 
 check : $(PRODUCT)
 
-$(PRODUCT) : vm $(OBJS)
-	$(CC) -o $@ $(OBJS) -L../../vm/ -lpmvm
-ifeq ($(TARGET), DESKTOP)
+$(PRODUCT) : $(PM_LIB_PATH) $(OBJS)
+	$(CC) -o $@ $(OBJS) $(PM_LIB_PATH)
+ifeq ($(PLATFORM), desktop)
 	$(addprefix ./,$@)
 endif
 
 CuTest.o : CuTest.c
 	$(CC) -c -o $@ $<
 
-vm :
-	make -C ../../vm DEBUG=true
+$(PM_LIB_PATH) : ../../vm/*.c ../../vm/*.h
+	make -C ../../vm
 
 # Removes files made by default make
 clean :

src/tests/unit/plat.c

+/*
+ * PyMite - A flyweight Python interpreter for 8-bit and larger microcontrollers.
+ * Copyright 2002 Dean Hall.  All rights reserved.
+ * PyMite is offered through one of two licenses: commercial or open-source.
+ * See the LICENSE file at the root of this package for licensing details.
+ */
+
+
+#undef __FILE_ID__
+#define __FILE_ID__ 0x50
+
+
+/** PyMite platform-specific routines for Desktop target */
+
+
+/* PyMite build process uses -ansi which disables certain features that
+ * in turn disable features needed for signal processing. To work around
+ * this, temporarily disable the corresponding #define. This is not
+ * needed for Cygwin but for Linux. The -ansi option of GCC is explained
+ * here: http://gcc.gnu.org/onlinedocs/gcc-4.0.3/gcc/C-Dialect-Options.html
+ */
+#ifdef __STRICT_ANSI__
+#undef __STRICT_ANSI__
+#include <stdio.h>
+#define __STRICT_ANSI__
+#else
+#include <stdio.h>
+#endif
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+
+#include "pm.h"
+
+
+void plat_sigalrm_handler(int signal);
+
+
+/* Desktop target shall use stdio for I/O routines. */
+PmReturn_t
+plat_init(void)
+{
+    /* Let POSIX' SIGALRM fire every full millisecond. */
+    /*
+     * #67 Using sigaction complicates the use of getchar (below),
+     * so signal() is used instead.
+     */
+    signal(SIGALRM, plat_sigalrm_handler);
+    ualarm(1000, 1000);
+
+    return PM_RET_OK;
+}
+
+
+void
+plat_sigalrm_handler(int signal)
+{
+    PmReturn_t retval;
+    retval = pm_vmPeriodic(1000);
+    PM_REPORT_IF_ERROR(retval);
+}
+
+
+/*
+ * Gets a byte from the address in the designated memory space
+ * Post-increments *paddr.
+ */
+uint8_t
+plat_memGetByte(PmMemSpace_t memspace, uint8_t const **paddr)
+{
+    uint8_t b = 0;
+
+    switch (memspace)
+    {
+        case MEMSPACE_RAM:
+        case MEMSPACE_PROG:
+            b = **paddr;
+            *paddr += 1;
+            return b;
+
+        case MEMSPACE_EEPROM:
+        case MEMSPACE_SEEPROM:
+        case MEMSPACE_OTHER0:
+        case MEMSPACE_OTHER1:
+        case MEMSPACE_OTHER2:
+        case MEMSPACE_OTHER3:
+        default:
+            return 0;
+    }
+}
+
+
+/* Desktop target shall use stdio for I/O routines */
+PmReturn_t
+plat_getByte(uint8_t *b)
+{
+    int c;
+    PmReturn_t retval = PM_RET_OK;
+
+    c = getchar();
+    *b = c & 0xFF;
+
+    if (c == EOF)
+    {
+        PM_RAISE(retval, PM_RET_EX_IO);
+    }
+
+    return retval;
+}
+
+
+/* Desktop target shall use stdio for I/O routines */
+PmReturn_t
+plat_putByte(uint8_t b)
+{
+    int i;
+    PmReturn_t retval = PM_RET_OK;
+
+    i = putchar(b);
+    fflush(stdout);
+
+    if ((i != b) || (i == EOF))
+    {
+        PM_RAISE(retval, PM_RET_EX_IO);
+    }
+
+    return retval;
+}
+
+
+PmReturn_t
+plat_getMsTicks(uint32_t *r_ticks)
+{
+    *r_ticks = pm_timerMsTicks;
+
+    return PM_RET_OK;
+}
+
+
+void
+plat_reportError(PmReturn_t result)
+{
+    /* Print error */
+    printf("Error:     0x%02X\n", result);
+    printf("  Release: 0x%02X\n", gVmGlobal.errVmRelease);
+    printf("  FileId:  0x%02X\n", gVmGlobal.errFileId);
+    printf("  LineNum: %d\n", gVmGlobal.errLineNum);
+
+    /* Print traceback */
+    {
+        pPmObj_t pframe;
+        pPmObj_t pstr;
+        PmReturn_t retval;
+
+        printf("Traceback (top first):\n");
+
+        /* Get the top frame */
+        pframe = (pPmObj_t)gVmGlobal.pthread->pframe;
+
+        /* If it's the native frame, print the native function name */
+        if (pframe == (pPmObj_t)&(gVmGlobal.nativeframe))
+        {
+
+            /* The last name in the names tuple of the code obj is the name */
+            retval = tuple_getItem((pPmObj_t)gVmGlobal.nativeframe.nf_func->
+                                   f_co->co_names, -1, &pstr);
+            if ((retval) != PM_RET_OK)
+            {
+                printf("  Unable to get native func name.\n");
+                return;
+            }
+            else
+            {
+                printf("  %s() __NATIVE__\n", ((pPmString_t)pstr)->val);
+            }
+
+            /* Get the frame that called the native frame */
+            pframe = (pPmObj_t)gVmGlobal.nativeframe.nf_back;
+        }
+
+        /* Print the remaining frame stack */
+        for (;
+             pframe != C_NULL;
+             pframe = (pPmObj_t)((pPmFrame_t)pframe)->fo_back)
+        {
+            /* The last name in the names tuple of the code obj is the name */
+            retval = tuple_getItem((pPmObj_t)((pPmFrame_t)pframe)->
+                                   fo_func->f_co->co_names, -1, &pstr);
+            if ((retval) != PM_RET_OK) break;
+
+            printf("  %s()\n", ((pPmString_t)pstr)->val);
+        }
+        printf("  <module>.\n");
+    }
+}
+
     --baud=<r>  Specifies the baud rate for a serial connection (default=19200)
     """
 
-PMVM_EXE = "../sample/ipm-desktop/main.out"
+PMVM_EXE = "../platform/desktop/main.out"
 IPM_PROMPT = "ipm> "
 COMPILE_FN = "<ipm>"
 COMPILE_MODE = "single"
-#
 # Builds the PyMite VM as an archive
 #
+# This Makefile is not meant to be invoked directly.
+# This Makefile is meant to be invoked by a Makefile in src/platform/<plat>/
+# and requires the following environment variables to be exported by the caller:
+#   CC OBJCOPY NM CFLAGS AR IPM PM_HEAP_SIZE PM_LIB_FN
+#
+# The primary function of this makefile is to:
+#
+#   1. Build pmstdlib_img.c and pmstdlib_nat.c from PMSTDLIB_SOURCES
+#   2. Build libpmbm.a from all *.c files
+#
 
-# Configure the contents of pmstdlib by editing this list
+
+PMIMGCREATOR := ../tools/pmImgCreator.py
 PMSTDLIB_SOURCES = ../lib/list.py \
                    ../lib/dict.py \
                    ../lib/__bi.py \
                    ../lib/sys.py \
                    ../lib/string.py
-
-TARGET ?= DESKTOP
-HEAP_SIZE ?= 0x2000
-
-PMIMGCREATOR := ../tools/pmImgCreator.py
-DEFS = -DTARGET_$(TARGET) -DHEAP_SIZE=$(HEAP_SIZE)
-CFLAGS = -Os -Wall -Wstrict-prototypes -Werror $(DEFS)
-ARFLAGS := rcs
-SOURCE_IMG := pmstdlib_img.c
-SOURCE_NAT := pmstdlib_nat.c
-SOURCES = $(wildcard *.c) $(SOURCE_IMG) $(SOURCE_NAT)
-OBJECTS = $(SOURCES:.c=.o)
-PRODUCT_VM := libpmvm.a
-INDENT := $(call pathsearch,indent)
-
-#
-# If GDB debugging is wanted
-#
-ifeq ($(DEBUG),true)
-	DEFS += -g -ggdb -D__DEBUG__=1
-endif
-
-#
-# Target-specific definitions
-#
-ifeq ($(TARGET), DESKTOP)
-	CFLAGS += -ansi
-	SOURCES += plat/desktop.c
-	SIZE = size
-	IPM=true
-else
-ifeq ($(TARGET), AVR)
-	TARGET_MCU ?= atmega103
-	F_CPU ?= 4000000UL
-	UART_BAUD ?= 19200UL
-	AR = avr-ar
-	CC = avr-gcc
-	SIZE = avr-size
-	CFLAGS += -mmcu=$(TARGET_MCU) -fshort-enums
-	DEFS += -DTARGET_MCU=$(TARGET_MCU) -DF_CPU=$(F_CPU) -DUART_BAUD=$(UART_BAUD)
-	SOURCES += plat/avr.c
-	PMSTDLIB_SOURCES += ../lib/avr.py
-else
-ifeq ($(TARGET), AT91SAM7)
-	TARGET_MCU ?= arm7tdmi
-	MCK ?= 47923200
-	UART_BAUD ?= 19200
-	AR = arm-elf-ar
-	CC = arm-elf-gcc
-	SIZE = arm-elf-size
-	CFLAGS += -mcpu=$(TARGET_MCU) -mthumb -mthumb-interwork -DTARGET_MCU=$(TARGET_MCU)
-	CFLAGS += -DUART_BAUD=$(UART_BAUD) -DMCK=$(MCK)
-	SOURCES += plat/at91sam7.c
-	IPM=true
-endif
-endif
-endif
-
-#
-# If Interactive PyMite (ipm) is wanted
-#
 ifeq ($(IPM),true)
 	PMSTDLIB_SOURCES += ../lib/ipm.py
 endif
 
 
+SOURCE_IMG := pmstdlib_img.c
+SOURCE_NAT := pmstdlib_nat.c
+
+ARFLAGS = rcs
+SOURCES = $(wildcard *.c) $(SOURCE_IMG) $(SOURCE_NAT)
+OBJECTS = $(SOURCES:.c=.o)
+INDENT := $(call pathsearch,indent)
+
+
+# Fix flags from WinARM/WinAVR Makefile
+# If ALL_CFLAGS is defined, overwrite CFLAGS
+ifneq ($(ALL_CFLAGS),)
+    CFLAGS = $(ALL_CFLAGS)
+	IPM=true
+endif
+# If RM does not exist, define it as REMOVE
+ifeq ($(RM),)
+    RM = $(REMOVE)
+endif
+
+
 .PHONY: all size indent clean
+.INTERMEDIATE: $(SOURCE_IMG) $(SOURCE_NAT)
 
 # Default action is to build the archive from object files
-all : $(SOURCE_IMG) $(SOURCE_NAT) $(PRODUCT_VM)
+all : $(SOURCE_IMG) $(SOURCE_NAT) $(PM_LIB_FN)
 
 # The archive is generated by placing object files inside it
-$(PRODUCT_VM) : $(PRODUCT_VM)($(OBJECTS))
+$(PM_LIB_FN) : $(PM_LIB_FN)($(OBJECTS))
 
 # Build the standard library into an image file and native function file
 $(SOURCE_IMG) $(SOURCE_NAT) : $(PMSTDLIB_SOURCES)
-	$(PMIMGCREATOR) -c --memspace=flash -o $(SOURCE_IMG) --native-file=$(SOURCE_NAT) $(PMSTDLIB_SOURCES)
+	$(PMIMGCREATOR) -c -s --memspace=flash -o $(SOURCE_IMG) --native-file=$(SOURCE_NAT) $(PMSTDLIB_SOURCES)
 
-# Lists the size of the obejcts in the archive
-size : $(PRODUCT_VM)
-	@$(SIZE) $(PRODUCT_VM)
+size : $(PM_LIB_FN)
+	@$(SIZE) $(PM_LIB_FN)
 
 # Runs GNU indent on the source files
 indent :
 
 # Remove files made by default make
 clean :
-	@$(RM) $(PRODUCT_VM)
-	@$(RM) $(OBJECTS)
-	@$(RM) $(SOURCE_IMG) $(SOURCE_NAT)
+	@$(RM) $(PM_LIB_FN) $(SOURCE_IMG) $(SOURCE_NAT)
+#	@$(RM) $(OBJECTS)
  */
 
 
-#include <math.h>
-
 #include "pm.h"
 
 
 #define __PLAT_H__
 
 
-/** Platform-specific routines for Desktop target */
+/** PyMite's Porting Interface */
 
 
 /**
  */
 PmReturn_t plat_init(void);
 
-
 /**
- * Return the byte at the given address in memspace.
+ * Returns the byte at the given address in memspace.
  *
- * Increment the address (just like getc and read(1))
- * to make image loading work (recursive).
+ * Increments the address (just like getc and read(1))
+ * to make image loading work (recursively).
  *
  * PORT:    fill in getByte for each memspace in the system;
  *          call sys_error for invalid memspaces.
 #include "mem.h"
 #include "obj.h"
 #include "seq.h"
-#include "string.h"
+#include "strobj.h"
 #include "heap.h"
 #include "int.h"
 #include "tuple.h"
 #include "misc.h"
 #include "thread.h"
 #include "float.h"
-#include "plat/plat.h"
+#include "plat.h"
 
 
 /**