diff --git a/stm/Makefile b/stm/Makefile
index a305a9bcabe03e03478caa442e6c745af52b3df2..b7e565e9aac5b56da80a25bb6c49ff1dc990843b 100644
--- a/stm/Makefile
+++ b/stm/Makefile
@@ -18,6 +18,7 @@ SRC_C = \
 	lcd.c \
 	flash.c \
 	storage.c \
+	mma.c \
 	string0.c \
 	malloc0.c \
 	systick.c  \
@@ -29,10 +30,10 @@ SRC_S = \
 	startup_stm32f40xx.s \
 
 PY_O = \
-#	nlrthumb.o \
+	nlrthumb.o \
 	malloc.o \
 	qstr.o \
-#	misc.o \
+	misc.o \
 	lexer.o \
 	parse.o \
 	scope.o \
diff --git a/stm/lib/usb_bsp.c b/stm/lib/usb_bsp.c
index 293ee95e2046dfbcff259207836b27df4201cddb..c4839bdf9696f39ee342c9e4d1556055ce4b2dc4 100644
--- a/stm/lib/usb_bsp.c
+++ b/stm/lib/usb_bsp.c
@@ -106,8 +106,8 @@ void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev) {
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
     GPIO_Init(GPIOA, &GPIO_InitStructure);
 
-    GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_OTG1_FS);
-    GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_OTG1_FS);
+    GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_OTG_FS);
+    GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_OTG_FS);
 
     /* Configure VBUS Pin (or disable VBUS_SENSING_ENABLED) */
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
@@ -123,16 +123,16 @@ void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev) {
 
 /**
 * @brief  USB_OTG_BSP_EnableInterrupt
-*         Enabele USB Global interrupt
+*         Enable USB Global interrupt
 * @param  None
 * @retval None
 */
 void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev) {
+    // this assumes we use NVIC_PriorityGroup_4
     NVIC_InitTypeDef NVIC_InitStructure;
-    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
     NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_IRQn;
-    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
-    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8;
+    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&NVIC_InitStructure);
 }
diff --git a/stm/lib/usbd_storage_msd.c b/stm/lib/usbd_storage_msd.c
index 47790bb110710c822b634f972ecfc91e358fbfd7..afdd47865d03b4bd65c5bbaa987e000c0c5ef90f 100644
--- a/stm/lib/usbd_storage_msd.c
+++ b/stm/lib/usbd_storage_msd.c
@@ -28,6 +28,9 @@
 /* Includes ------------------------------------------------------------------*/
 #include "usbd_msc_mem.h"
 #include "usb_conf.h"
+
+#include "misc.h"
+#include "storage.h"
 #include "diskio.h"
 
 /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
@@ -198,9 +201,9 @@ int8_t STORAGE_GetCapacity (uint8_t lun, uint32_t *block_num, uint32_t *block_si
   */
 
   
-  *block_size =  512;  
+  *block_size = storage_get_block_size();
   //*block_num =  SDCardInfo.CardCapacity / 512;  
-  *block_num = 256 + 128;
+  *block_num = storage_get_block_count();
   
   return (0);
   
@@ -305,7 +308,7 @@ int8_t STORAGE_Write (uint8_t lun,
   while (SD_GetStatus() != SD_TRANSFER_OK);  
 #endif  
 */
-    disk_write(0, buf, blk_addr, blk_len);
+    //disk_write(0, buf, blk_addr, blk_len);
   return (0);
 }
 
diff --git a/stm/lib/usbd_usr.c b/stm/lib/usbd_usr.c
index 844a3ed7f59388618ebf4f06ebd23b35c9858b39..a5a7fb7ffbdcb38e645c111630a7830e1192bac5 100644
--- a/stm/lib/usbd_usr.c
+++ b/stm/lib/usbd_usr.c
@@ -46,8 +46,8 @@ USBD_Usr_cb_TypeDef USR_cb = {
 * @retval None
 */
 void USBD_USR_Init() {
-    printf("USB OTG FS\n");
-    printf("USB device start\n");
+    //printf("USB OTG FS\n");
+    //printf("USB device start\n");
 }
 
 /**
@@ -57,7 +57,7 @@ void USBD_USR_Init() {
 * @retval None
 */
 void USBD_USR_DeviceReset(uint8_t speed) {
-    printf("USB reset %d\n", speed);
+    //printf("USB reset %d\n", speed);
 }
 
 /**
@@ -67,7 +67,7 @@ void USBD_USR_DeviceReset(uint8_t speed) {
 * @retval Staus
 */
 void USBD_USR_DeviceConfigured() {
-    printf("USB dev config\n");
+    //printf("USB dev config\n");
 }
 
 /**
@@ -77,7 +77,7 @@ void USBD_USR_DeviceConfigured() {
 * @retval None
 */
 void USBD_USR_DeviceSuspended() {
-    printf("USB dev suspend\n");
+    //printf("USB dev suspend\n");
 }
 
 /**
@@ -87,7 +87,7 @@ void USBD_USR_DeviceSuspended() {
 * @retval None
 */
 void USBD_USR_DeviceResumed() {
-    printf("USB dev resume\n");
+    //printf("USB dev resume\n");
 }
 
 
@@ -98,7 +98,7 @@ void USBD_USR_DeviceResumed() {
 * @retval Staus
 */
 void USBD_USR_DeviceConnected() {
-    printf("USB dev connect\n");
+    //printf("USB dev connect\n");
 }
 
 
@@ -109,7 +109,7 @@ void USBD_USR_DeviceConnected() {
 * @retval Staus
 */
 void USBD_USR_DeviceDisconnected() {
-    printf("USB dev disconn\n");
+    //printf("USB dev disconn\n");
 }
 
 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stm/main.c b/stm/main.c
index ca14d1ce9d0fd4d991a2977f9a8179004c2abfe8..e06e119a5572e665fa8e497a3bda25b0ed15a73f 100644
--- a/stm/main.c
+++ b/stm/main.c
@@ -9,6 +9,7 @@
 #include "led.h"
 #include "lcd.h"
 #include "storage.h"
+#include "mma.h"
 #include "usb.h"
 
 static void impl02_c_version() {
@@ -26,137 +27,6 @@ static void impl02_c_version() {
     }
 }
 
-void set_bits(__IO uint32_t *addr, uint32_t shift, uint32_t mask, uint32_t value) {
-    uint32_t x = *addr;
-    x &= ~(mask << shift);
-    x |= (value << shift);
-    *addr = x;
-}
-
-void gpio_init() {
-    RCC->AHB1ENR |= RCC_AHB1ENR_CCMDATARAMEN | RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOAEN;
-}
-
-/*
-void gpio_pin_af(GPIO_TypeDef *gpio, uint32_t pin, uint32_t af) {
-    // set the AF bits for the given pin
-    // pins 0-7 use low word of AFR, pins 8-15 use high word
-    set_bits(&gpio->AFR[pin >> 3], 4 * (pin & 0x07), 0xf, af);
-}
-*/
-
-static void mma_init() {
-    // XXX
-    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // enable I2C1
-    //gpio_pin_init(GPIOB, 6 /* B6 is SCL */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */);
-    //gpio_pin_init(GPIOB, 7 /* B7 is SDA */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */);
-    //gpio_pin_af(GPIOB, 6, 4 /* AF 4 for I2C1 */);
-    //gpio_pin_af(GPIOB, 7, 4 /* AF 4 for I2C1 */);
-
-    // get clock speeds
-    RCC_ClocksTypeDef rcc_clocks;
-    RCC_GetClocksFreq(&rcc_clocks);
-
-    // disable the I2C peripheral before we configure it
-    I2C1->CR1 &= ~I2C_CR1_PE;
-
-    // program peripheral input clock
-    I2C1->CR2 = 4; // no interrupts; 4 MHz (hopefully!) (could go up to 42MHz)
-
-    // configure clock control reg
-    uint32_t freq = rcc_clocks.PCLK1_Frequency / (100000 << 1); // want 100kHz, this is the formula for freq
-    I2C1->CCR = freq; // standard mode (speed), freq calculated as above
-
-    // configure rise time reg
-    I2C1->TRISE = (rcc_clocks.PCLK1_Frequency / 1000000) + 1; // formula for trise, gives maximum rise time
-
-    // enable the I2C peripheral
-    I2C1->CR1 |= I2C_CR1_PE;
-
-    // set START bit in CR1 to generate a start cond!
-}
-
-static uint32_t i2c_get_sr() {
-    // must read SR1 first, then SR2, as the read can clear some flags
-    uint32_t sr1 = I2C1->SR1;
-    uint32_t sr2 = I2C1->SR2;
-    return (sr2 << 16) | sr1;
-}
-
-static void mma_restart(uint8_t addr, int write) {
-    // send start condition
-    I2C1->CR1 |= I2C_CR1_START;
-
-    // wait for BUSY, MSL and SB --> Slave has acknowledged start condition
-    while ((i2c_get_sr() & 0x00030001) != 0x00030001) {
-    }
-
-    if (write) {
-        // send address and write bit
-        I2C1->DR = (addr << 1) | 0;
-        // wait for BUSY, MSL, ADDR, TXE and TRA
-        while ((i2c_get_sr() & 0x00070082) != 0x00070082) {
-        }
-    } else {
-        // send address and read bit
-        I2C1->DR = (addr << 1) | 1;
-        // wait for BUSY, MSL and ADDR flags
-        while ((i2c_get_sr() & 0x00030002) != 0x00030002) {
-        }
-    }
-}
-
-static void mma_start(uint8_t addr, int write) {
-    // wait until I2C is not busy
-    while (I2C1->SR2 & I2C_SR2_BUSY) {
-    }
-
-    // do rest of start
-    mma_restart(addr, write);
-}
-
-static void mma_send_byte(uint8_t data) {
-    // send byte
-    I2C1->DR = data;
-    // wait for TRA, BUSY, MSL, TXE and BTF (byte transmitted)
-    int timeout = 1000000;
-    while ((i2c_get_sr() & 0x00070084) != 0x00070084) {
-        if (timeout-- <= 0) {
-            printf("mma_send_byte timed out!\n");
-            break;
-        }
-    }
-}
-
-static uint8_t mma_read_ack() {
-    // enable ACK of received byte
-    I2C1->CR1 |= I2C_CR1_ACK;
-    // wait for BUSY, MSL and RXNE (byte received)
-    while ((i2c_get_sr() & 0x00030040) != 0x00030040) {
-    }
-    // read and return data
-    uint8_t data = I2C1->DR;
-    return data;
-}
-
-static uint8_t mma_read_nack() {
-    // disable ACK of received byte (to indicate end of receiving)
-    I2C1->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK);
-    // last byte should apparently also generate a stop condition
-    I2C1->CR1 |= I2C_CR1_STOP;
-    // wait for BUSY, MSL and RXNE (byte received)
-    while ((i2c_get_sr() & 0x00030040) != 0x00030040) {
-    }
-    // read and return data
-    uint8_t data = I2C1->DR;
-    return data;
-}
-
-static void mma_stop() {
-    // send stop condition
-    I2C1->CR1 |= I2C_CR1_STOP;
-}
-
 #define PYB_USRSW_PORT (GPIOA)
 #define PYB_USRSW_PIN (GPIO_Pin_13)
 
@@ -200,7 +70,6 @@ void __fatal_error(const char *msg) {
 #include "compile.h"
 #include "runtime.h"
 
-#if 0
 py_obj_t pyb_delay(py_obj_t count) {
     sys_tick_delay_ms(rt_get_int(count));
     return py_const_none;
@@ -218,14 +87,13 @@ py_obj_t pyb_sw() {
         return py_const_false;
     }
 }
-#endif
 
 #include "ff.h"
 FATFS fatfs0;
 
+#include "nlr.h"
 
 /*
-#include "nlr.h"
 void g(uint i) {
     printf("g:%d\n", i);
     if (i & 1) {
@@ -262,7 +130,7 @@ void fatality() {
     led_state(PYB_LED_G2, 1);
 }
 
-static const char *fresh_boot_py =
+static const char fresh_boot_py[] =
 "# boot.py -- run on boot-up\n"
 "# can run arbitrary Python, but best to keep it minimal\n"
 "\n"
@@ -316,9 +184,14 @@ static void board_info() {
 int main() {
     // TODO disable JTAG
 
+    // set interrupt priority config to use all 4 bits for pre-empting
+    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
+
+    // enable the CCM RAM and the GPIO's
+    RCC->AHB1ENR |= RCC_AHB1ENR_CCMDATARAMEN | RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN;
+
     // basic sub-system init
     sys_tick_init();
-    gpio_init();
     led_init();
 
     // turn on LED to indicate bootup
@@ -330,8 +203,8 @@ int main() {
     storage_init();
 
     // Python init
-    //qstr_init();
-    //rt_init();
+    qstr_init();
+    rt_init();
 
     // print a message
     printf(" micro py board\n");
@@ -356,8 +229,8 @@ int main() {
                 __fatal_error("could not create LFS");
             }
 
-            // keep LED on for at least 100ms
-            sys_tick_wait_at_least(stc, 100);
+            // keep LED on for at least 200ms
+            sys_tick_wait_at_least(stc, 200);
             led_state(PYB_LED_R2, 0);
         } else {
             __fatal_error("could not access LFS");
@@ -390,8 +263,8 @@ int main() {
             // TODO check we could write n bytes
             f_close(&fp);
 
-            // keep LED on for at least 100ms
-            sys_tick_wait_at_least(stc, 100);
+            // keep LED on for at least 200ms
+            sys_tick_wait_at_least(stc, 200);
             led_state(PYB_LED_R2, 0);
         }
     }
@@ -419,7 +292,6 @@ int main() {
     //printf("init;al=%u\n", m_get_total_bytes_allocated()); // 1600, due to qstr_init
     //sys_tick_delay_ms(1000);
 
-    #if 0
     // Python!
     if (0) {
         //const char *pysrc = "def f():\n  x=x+1\nprint(42)\n";
@@ -570,7 +442,6 @@ int main() {
             }
         }
     }
-    #endif
 
     // benchmark C version of impl02.py
     if (0) {
@@ -663,7 +534,7 @@ int main() {
             led_state(PYB_LED_G1, 0);
         }
         if (sys_tick_has_passed(stc, 500)) {
-            stc = sys_tick_counter;
+            stc += 500;
             led_toggle(PYB_LED_G2);
         }
     }
diff --git a/stm/mma.c b/stm/mma.c
new file mode 100644
index 0000000000000000000000000000000000000000..e56608ef4cb554fc5c8c217ed64af3fe38d50bba
--- /dev/null
+++ b/stm/mma.c
@@ -0,0 +1,128 @@
+#include <stdio.h>
+
+#include <stm32f4xx.h>
+#include <stm32f4xx_rcc.h>
+#include <stm32f4xx_gpio.h>
+
+#include "mma.h"
+
+void mma_init() {
+    RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // enable I2C1
+    //gpio_pin_init(GPIOB, 6 /* B6 is SCL */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */);
+    //gpio_pin_init(GPIOB, 7 /* B7 is SDA */, 2 /* AF mode */, 1 /* open drain output */, 1 /* 25 MHz */, 0 /* no pull up or pull down */);
+    //gpio_pin_af(GPIOB, 6, 4 /* AF 4 for I2C1 */);
+    //gpio_pin_af(GPIOB, 7, 4 /* AF 4 for I2C1 */);
+    // XXX untested GPIO init! (was above code)
+    GPIO_InitTypeDef GPIO_InitStructure;
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
+    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
+    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
+    GPIO_Init(GPIOB, &GPIO_InitStructure);
+    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
+    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
+
+    // get clock speeds
+    RCC_ClocksTypeDef rcc_clocks;
+    RCC_GetClocksFreq(&rcc_clocks);
+
+    // disable the I2C peripheral before we configure it
+    I2C1->CR1 &= ~I2C_CR1_PE;
+
+    // program peripheral input clock
+    I2C1->CR2 = 4; // no interrupts; 4 MHz (hopefully!) (could go up to 42MHz)
+
+    // configure clock control reg
+    uint32_t freq = rcc_clocks.PCLK1_Frequency / (100000 << 1); // want 100kHz, this is the formula for freq
+    I2C1->CCR = freq; // standard mode (speed), freq calculated as above
+
+    // configure rise time reg
+    I2C1->TRISE = (rcc_clocks.PCLK1_Frequency / 1000000) + 1; // formula for trise, gives maximum rise time
+
+    // enable the I2C peripheral
+    I2C1->CR1 |= I2C_CR1_PE;
+
+    // set START bit in CR1 to generate a start cond!
+}
+
+static uint32_t i2c_get_sr() {
+    // must read SR1 first, then SR2, as the read can clear some flags
+    uint32_t sr1 = I2C1->SR1;
+    uint32_t sr2 = I2C1->SR2;
+    return (sr2 << 16) | sr1;
+}
+
+void mma_restart(uint8_t addr, int write) {
+    // send start condition
+    I2C1->CR1 |= I2C_CR1_START;
+
+    // wait for BUSY, MSL and SB --> Slave has acknowledged start condition
+    while ((i2c_get_sr() & 0x00030001) != 0x00030001) {
+    }
+
+    if (write) {
+        // send address and write bit
+        I2C1->DR = (addr << 1) | 0;
+        // wait for BUSY, MSL, ADDR, TXE and TRA
+        while ((i2c_get_sr() & 0x00070082) != 0x00070082) {
+        }
+    } else {
+        // send address and read bit
+        I2C1->DR = (addr << 1) | 1;
+        // wait for BUSY, MSL and ADDR flags
+        while ((i2c_get_sr() & 0x00030002) != 0x00030002) {
+        }
+    }
+}
+
+void mma_start(uint8_t addr, int write) {
+    // wait until I2C is not busy
+    while (I2C1->SR2 & I2C_SR2_BUSY) {
+    }
+
+    // do rest of start
+    mma_restart(addr, write);
+}
+
+void mma_send_byte(uint8_t data) {
+    // send byte
+    I2C1->DR = data;
+    // wait for TRA, BUSY, MSL, TXE and BTF (byte transmitted)
+    int timeout = 1000000;
+    while ((i2c_get_sr() & 0x00070084) != 0x00070084) {
+        if (timeout-- <= 0) {
+            printf("mma_send_byte timed out!\n");
+            break;
+        }
+    }
+}
+
+uint8_t mma_read_ack() {
+    // enable ACK of received byte
+    I2C1->CR1 |= I2C_CR1_ACK;
+    // wait for BUSY, MSL and RXNE (byte received)
+    while ((i2c_get_sr() & 0x00030040) != 0x00030040) {
+    }
+    // read and return data
+    uint8_t data = I2C1->DR;
+    return data;
+}
+
+uint8_t mma_read_nack() {
+    // disable ACK of received byte (to indicate end of receiving)
+    I2C1->CR1 &= (uint16_t)~((uint16_t)I2C_CR1_ACK);
+    // last byte should apparently also generate a stop condition
+    I2C1->CR1 |= I2C_CR1_STOP;
+    // wait for BUSY, MSL and RXNE (byte received)
+    while ((i2c_get_sr() & 0x00030040) != 0x00030040) {
+    }
+    // read and return data
+    uint8_t data = I2C1->DR;
+    return data;
+}
+
+void mma_stop() {
+    // send stop condition
+    I2C1->CR1 |= I2C_CR1_STOP;
+}
diff --git a/stm/mma.h b/stm/mma.h
new file mode 100644
index 0000000000000000000000000000000000000000..88efa3ef25eb5e3c99ae08a9d4c3bfda4f143f65
--- /dev/null
+++ b/stm/mma.h
@@ -0,0 +1,7 @@
+void mma_init();
+void mma_restart(uint8_t addr, int write);
+void mma_start(uint8_t addr, int write);
+void mma_send_byte(uint8_t data);
+uint8_t mma_read_ack();
+uint8_t mma_read_nack();
+void mma_stop();
diff --git a/stm/storage.c b/stm/storage.c
index 89dbd97c6a4798866b8608ed538d56495be56f9a..ce89bdf6fe16e8a2c5a57360dacaa9128b84bbe9 100644
--- a/stm/storage.c
+++ b/stm/storage.c
@@ -53,6 +53,14 @@ void storage_init() {
     }
 }
 
+uint32_t storage_get_block_size() {
+    return BLOCK_SIZE;
+}
+
+uint32_t storage_get_block_count() {
+    return FLASH_PART1_START_BLOCK + FLASH_PART1_NUM_BLOCKS;
+}
+
 void storage_flush() {
     cache_flush();
 }
diff --git a/stm/storage.h b/stm/storage.h
index 542329e4ba7849aca51486cd32120f669275ecf0..e7895fd5105b0fde0a558940480d082ac7214fd3 100644
--- a/stm/storage.h
+++ b/stm/storage.h
@@ -1,4 +1,6 @@
 void storage_init();
+uint32_t storage_get_block_size();
+uint32_t storage_get_block_count();
 void storage_flush();
 bool storage_read_block(uint8_t *dest, uint32_t block);
 bool storage_write_block(const uint8_t *src, uint32_t block);
diff --git a/stm/systick.c b/stm/systick.c
index 172b7540404c474d47318cdfb71e30edb9f26af0..9464132e2dfbdbc0efd9f5e372632727ab0755fe 100644
--- a/stm/systick.c
+++ b/stm/systick.c
@@ -8,6 +8,7 @@ void sys_tick_init() {
     // sys-tick interrupt called at 1ms intervals
     sys_tick_counter = 0;
     SysTick_Config(SystemCoreClock / 1000);
+    NVIC_SetPriority(SysTick_IRQn, 0); // make it highest priority
 }
 
 // called on SysTick interrupt