diff --git a/stmhal/input.c b/stmhal/input.c
index 7f3b17c6fe35e2bc860c7ce95b236c65d00fa4fc..9b67b641c640f859c92d5081b71d744840ec34e0 100644
--- a/stmhal/input.c
+++ b/stmhal/input.c
@@ -41,7 +41,7 @@ STATIC mp_obj_t mp_builtin_input(uint n_args, const mp_obj_t *args) {
     vstr_t line;
     vstr_init(&line, 16);
     int ret = readline(&line, "");
-    if (line.len == 0 && ret == VCP_CHAR_CTRL_D) {
+    if (line.len == 0 && ret == CHAR_CTRL_D) {
         nlr_raise(mp_obj_new_exception(&mp_type_EOFError));
     }
     mp_obj_t o = mp_obj_new_str(line.buf, line.len, false);
diff --git a/stmhal/mphal.c b/stmhal/mphal.c
index 7fcd982dcb8a3642c24b03411c3c9a4179a89e77..43e1b9ba367cca9d9ef2402ee9e97bd00fd1c62b 100644
--- a/stmhal/mphal.c
+++ b/stmhal/mphal.c
@@ -5,6 +5,7 @@
 #include "misc.h"
 #include "qstr.h"
 #include "obj.h"
+#include "usb.h"
 #include "mphal.h"
 
 // this table converts from HAL_StatusTypeDef to POSIX errno
@@ -18,3 +19,7 @@ const byte mp_hal_status_to_errno_table[4] = {
 NORETURN void mp_hal_raise(HAL_StatusTypeDef status) {
     nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(mp_hal_status_to_errno_table[status])));
 }
+
+void mp_hal_set_interrupt_char(int c) {
+    usb_vcp_set_interrupt_char(c);
+}
diff --git a/stmhal/mphal.h b/stmhal/mphal.h
index 4b43cf886d4b11bae50835a5afcbbe9c7feb4236..fb567d141113f69a2e07410ae6fdd90c17a3db41 100644
--- a/stmhal/mphal.h
+++ b/stmhal/mphal.h
@@ -10,3 +10,4 @@
 extern const byte mp_hal_status_to_errno_table[4];
 
 NORETURN void mp_hal_raise(HAL_StatusTypeDef status);
+void mp_hal_set_interrupt_char(int c); // -1 to disable
diff --git a/stmhal/pyexec.c b/stmhal/pyexec.c
index 3fd797c0d3c605b0692f4ea6632a6cf3544192f7..6bf8009a19ffed4479a0c91213756213fb45ca8c 100644
--- a/stmhal/pyexec.c
+++ b/stmhal/pyexec.c
@@ -46,8 +46,6 @@
 #include "systick.h"
 #include "readline.h"
 #include "pyexec.h"
-#include "usb.h"
-#include "uart.h"
 #include "pybstdio.h"
 #include "genhdr/py-version.h"
 
@@ -97,9 +95,9 @@ STATIC int parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_ki
     nlr_buf_t nlr;
     uint32_t start = HAL_GetTick();
     if (nlr_push(&nlr) == 0) {
-        usb_vcp_set_interrupt_char(VCP_CHAR_CTRL_C); // allow ctrl-C to interrupt us
+        mp_hal_set_interrupt_char(CHAR_CTRL_C); // allow ctrl-C to interrupt us
         mp_call_function_0(module_fun);
-        usb_vcp_set_interrupt_char(VCP_CHAR_NONE); // disable interrupt
+        mp_hal_set_interrupt_char(-1); // disable interrupt
         nlr_pop();
         ret = 1;
         if (exec_flags & EXEC_FLAG_PRINT_EOF) {
@@ -108,7 +106,7 @@ STATIC int parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_ki
     } else {
         // uncaught exception
         // FIXME it could be that an interrupt happens just before we disable it here
-        usb_vcp_set_interrupt_char(VCP_CHAR_NONE); // disable interrupt
+        mp_hal_set_interrupt_char(-1); // disable interrupt
         // print EOF after normal output
         if (exec_flags & EXEC_FLAG_PRINT_EOF) {
             stdout_tx_strn("\x04", 1);
@@ -125,8 +123,8 @@ STATIC int parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t input_ki
 
     // display debugging info if wanted
     if ((exec_flags & EXEC_FLAG_ALLOW_DEBUGGING) && repl_display_debugging_info) {
-        uint32_t ticks = HAL_GetTick() - start; // TODO implement a function that does this properly
-        printf("took %lu ms\n", ticks);
+        mp_uint_t ticks = HAL_GetTick() - start; // TODO implement a function that does this properly
+        printf("took " UINT_FMT " ms\n", ticks);
         gc_collect();
         // qstr info
         {
@@ -166,19 +164,19 @@ raw_repl_reset:
         stdout_tx_str(">");
         for (;;) {
             char c = stdin_rx_chr();
-            if (c == VCP_CHAR_CTRL_A) {
+            if (c == CHAR_CTRL_A) {
                 // reset raw REPL
                 goto raw_repl_reset;
-            } else if (c == VCP_CHAR_CTRL_B) {
+            } else if (c == CHAR_CTRL_B) {
                 // change to friendly REPL
                 stdout_tx_str("\r\n");
                 vstr_clear(&line);
                 pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;
                 return 0;
-            } else if (c == VCP_CHAR_CTRL_C) {
+            } else if (c == CHAR_CTRL_C) {
                 // clear line
                 vstr_reset(&line);
-            } else if (c == VCP_CHAR_CTRL_D) {
+            } else if (c == CHAR_CTRL_D) {
                 // input finished
                 break;
             } else if (c <= 127) {
@@ -230,7 +228,7 @@ friendly_repl_reset:
         for (;;) {
             nlr_buf_t nlr;
             printf("pyexec_repl: %p\n", x);
-            usb_vcp_set_interrupt_char(VCP_CHAR_CTRL_C);
+            mp_hal_set_interrupt_char(CHAR_CTRL_C);
             if (nlr_push(&nlr) == 0) {
                 for (;;) {
                 }
@@ -246,21 +244,21 @@ friendly_repl_reset:
         vstr_reset(&line);
         int ret = readline(&line, ">>> ");
 
-        if (ret == VCP_CHAR_CTRL_A) {
+        if (ret == CHAR_CTRL_A) {
             // change to raw REPL
             stdout_tx_str("\r\n");
             vstr_clear(&line);
             pyexec_mode_kind = PYEXEC_MODE_RAW_REPL;
             return 0;
-        } else if (ret == VCP_CHAR_CTRL_B) {
+        } else if (ret == CHAR_CTRL_B) {
             // reset friendly REPL
             stdout_tx_str("\r\n");
             goto friendly_repl_reset;
-        } else if (ret == VCP_CHAR_CTRL_C) {
+        } else if (ret == CHAR_CTRL_C) {
             // break
             stdout_tx_str("\r\n");
             continue;
-        } else if (ret == VCP_CHAR_CTRL_D) {
+        } else if (ret == CHAR_CTRL_D) {
             // exit for a soft reset
             stdout_tx_str("\r\n");
             vstr_clear(&line);
@@ -272,11 +270,11 @@ friendly_repl_reset:
         while (mp_repl_continue_with_input(vstr_str(&line))) {
             vstr_add_char(&line, '\n');
             int ret = readline(&line, "... ");
-            if (ret == VCP_CHAR_CTRL_C) {
+            if (ret == CHAR_CTRL_C) {
                 // cancel everything
                 stdout_tx_str("\r\n");
                 goto input_restart;
-            } else if (ret == VCP_CHAR_CTRL_D) {
+            } else if (ret == CHAR_CTRL_D) {
                 // stop entering compound statement
                 break;
             }
diff --git a/stmhal/readline.c b/stmhal/readline.c
index 4b1f48baae12f7b70a0a9f07bce7f339093bc3e9..b49156b85216bafa168ee5cbd9cc3d45d0efe6ae 100644
--- a/stmhal/readline.c
+++ b/stmhal/readline.c
@@ -36,7 +36,6 @@
 #include MICROPY_HAL_H
 #include "readline.h"
 #include "usb.h"
-#include "uart.h"
 #include "pybstdio.h"
 
 #if 0 // print debugging info
@@ -80,16 +79,16 @@ int readline(vstr_t *line, const char *prompt) {
         bool redraw_from_cursor = false;
         int redraw_step_forward = 0;
         if (escape_seq == ESEQ_NONE) {
-            if (VCP_CHAR_CTRL_A <= c && c <= VCP_CHAR_CTRL_D && vstr_len(line) == orig_line_len) {
+            if (CHAR_CTRL_A <= c && c <= CHAR_CTRL_D && vstr_len(line) == orig_line_len) {
                 // control character with empty line
                 return c;
-            } else if (c == VCP_CHAR_CTRL_A) {
+            } else if (c == CHAR_CTRL_A) {
                 // CTRL-A with non-empty line is go-to-start-of-line
                 goto home_key;
-            } else if (c == VCP_CHAR_CTRL_C) {
+            } else if (c == CHAR_CTRL_C) {
                 // CTRL-C with non-empty line is cancel
                 return c;
-            } else if (c == VCP_CHAR_CTRL_E) {
+            } else if (c == CHAR_CTRL_E) {
                 // CTRL-E is go-to-end-of-line
                 goto end_key;
             } else if (c == '\r') {
diff --git a/stmhal/readline.h b/stmhal/readline.h
index 8bbc43b435dcff4e44298d95b87707a7fbdff651..d5ce4704ea29bfdf5d0fa12efadd2c7faecdd5f4 100644
--- a/stmhal/readline.h
+++ b/stmhal/readline.h
@@ -24,5 +24,11 @@
  * THE SOFTWARE.
  */
 
+#define CHAR_CTRL_A (1)
+#define CHAR_CTRL_B (2)
+#define CHAR_CTRL_C (3)
+#define CHAR_CTRL_D (4)
+#define CHAR_CTRL_E (5)
+
 void readline_init0(void);
 int readline(vstr_t *line, const char *prompt);
diff --git a/stmhal/usb.c b/stmhal/usb.c
index 2dc789894435197657bbf66149d73435b73eaf29..0499aaa8d696ed486b18bc178ffba869cf85a283 100644
--- a/stmhal/usb.c
+++ b/stmhal/usb.c
@@ -54,7 +54,7 @@ STATIC mp_obj_t mp_const_vcp_interrupt = MP_OBJ_NULL;
 void pyb_usb_init0(void) {
     // create an exception object for interrupting by VCP
     mp_const_vcp_interrupt = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
-    USBD_CDC_SetInterrupt(VCP_CHAR_NONE, mp_const_vcp_interrupt);
+    USBD_CDC_SetInterrupt(-1, mp_const_vcp_interrupt);
 }
 
 void pyb_usb_dev_init(usb_device_mode_t mode, usb_storage_medium_t medium) {
@@ -105,7 +105,7 @@ bool usb_vcp_is_connected(void) {
 
 void usb_vcp_set_interrupt_char(int c) {
     if (dev_is_enabled) {
-        if (c != VCP_CHAR_NONE) {
+        if (c != -1) {
             mp_obj_exception_clear_traceback(mp_const_vcp_interrupt);
         }
         USBD_CDC_SetInterrupt(c, mp_const_vcp_interrupt);
diff --git a/stmhal/usb.h b/stmhal/usb.h
index 168bfbd5fef686dbfa5944ee066ca7d0c6481a5a..e0bfe9a76e0c89dd3f3f9633390da55df49d2b86 100644
--- a/stmhal/usb.h
+++ b/stmhal/usb.h
@@ -24,13 +24,6 @@
  * THE SOFTWARE.
  */
 
-#define VCP_CHAR_NONE   (0)
-#define VCP_CHAR_CTRL_A (1)
-#define VCP_CHAR_CTRL_B (2)
-#define VCP_CHAR_CTRL_C (3)
-#define VCP_CHAR_CTRL_D (4)
-#define VCP_CHAR_CTRL_E (5)
-
 typedef enum {
     USB_DEVICE_MODE_CDC_MSC,
     USB_DEVICE_MODE_CDC_HID,
diff --git a/stmhal/usbd_cdc_interface.c b/stmhal/usbd_cdc_interface.c
index 7f1eef5b3e62d1aca1af85d0febaa266f593da49..c09c970f673b022bda2100756b058dfad02f8bd6 100644
--- a/stmhal/usbd_cdc_interface.c
+++ b/stmhal/usbd_cdc_interface.c
@@ -41,12 +41,6 @@
 #include "usbd_cdc_interface.h"
 #include "pendsv.h"
 
-#include "mpconfig.h"
-#include "misc.h"
-#include "qstr.h"
-#include "obj.h"
-#include "usb.h"
-
 // CDC control commands
 #define CDC_SEND_ENCAPSULATED_COMMAND               0x00
 #define CDC_GET_ENCAPSULATED_RESPONSE               0x01
@@ -79,7 +73,7 @@ static uint16_t UserTxBufPtrOutShadow = 0; // shadow of above
 static uint8_t UserTxBufPtrWaitCount = 0; // used to implement a timeout waiting for low-level USB driver
 static uint8_t UserTxNeedEmptyPacket = 0; // used to flush the USB IN endpoint if the last packet was exactly the endpoint packet size
 
-static int user_interrupt_char = VCP_CHAR_NONE;
+static int user_interrupt_char = -1;
 static void *user_interrupt_data = NULL;
 
 /* USB handler declaration */
@@ -159,7 +153,7 @@ static int8_t CDC_Itf_Init(void)
      * may be called before this init function to set these values.
      * This can happen if the USB enumeration occurs after the call to
      * USBD_CDC_SetInterrupt.
-    user_interrupt_char = VCP_CHAR_NONE;
+    user_interrupt_char = -1;
     user_interrupt_data = NULL;
     */
 
@@ -351,7 +345,7 @@ static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) {
 
     uint32_t delta_len;
 
-    if (user_interrupt_char == VCP_CHAR_NONE) {
+    if (user_interrupt_char == -1) {
         // no special interrupt character
         delta_len = *Len;
 
diff --git a/teensy/teensy_hal.c b/teensy/teensy_hal.c
index 39f41ad8ad2b6a7a752ed192eb8843de94bb8baa..6e9a27c30d4de699b580ea12e7b0701dc653a05d 100644
--- a/teensy/teensy_hal.c
+++ b/teensy/teensy_hal.c
@@ -14,3 +14,9 @@ uint32_t HAL_GetTick(void) {
 void HAL_Delay(uint32_t Delay) {
   delay(Delay);
 }
+
+void mp_hal_set_interrupt_char(int c) {
+  // The teensy 3.1 usb stack doesn't currently have the notion of generating
+  // an exception when a certain character is received. That just means that
+  // you can't press Control-C and get your python script to stop.
+}
diff --git a/teensy/teensy_hal.h b/teensy/teensy_hal.h
index d27116d41537c2b47ff3afa5b86b7fcfd4ac26a8..ee434fd20940096abf45620a087dfc486e0c94e8 100644
--- a/teensy/teensy_hal.h
+++ b/teensy/teensy_hal.h
@@ -114,6 +114,7 @@ __attribute__(( always_inline )) static inline void __WFI(void) {
 
 uint32_t HAL_GetTick(void);
 void     HAL_Delay(uint32_t Delay);
+void mp_hal_set_interrupt_char(int c);
 
 void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *init);
 
diff --git a/teensy/usb.c b/teensy/usb.c
index 9fb50967dbc2c2d33b3d5b0715459fea3bacb266..d1601c32d3e7d107d5bd255e0411bd64c5a48900 100644
--- a/teensy/usb.c
+++ b/teensy/usb.c
@@ -22,12 +22,6 @@ bool usb_vcp_is_enabled(void)
   return true;
 }
 
-void usb_vcp_set_interrupt_char(int c) {
-  // The teensy 3.1 usb stack doesn't currently have the notion of generating
-  // an exception when a certain character is received. That just means that
-  // you can't press Control-C and get your python script to stop.
-}
-
 int usb_vcp_rx_num(void) {
   return usb_serial_available();
 }