diff --git a/stm/boards/NETDUINO_PLUS_2/mpconfigboard.h b/stm/boards/NETDUINO_PLUS_2/mpconfigboard.h
index 2c0e4b74c0a81ae56945475010407c926690c7fb..9bc5149ecf85e8b9469418c6fb7043f0fac57b86 100644
--- a/stm/boards/NETDUINO_PLUS_2/mpconfigboard.h
+++ b/stm/boards/NETDUINO_PLUS_2/mpconfigboard.h
@@ -25,21 +25,14 @@
 #define USRSW_PRESSED       (1)
 
 /* LED */
-#define PYB_LED1_PORT   (GPIOA)         // Blue LED
-#define PYB_LED1_PIN    (GPIO_Pin_10)
-
-#define PYB_LED2_PORT   (GPIOC)         // White LED (aka Power)
-#define PYB_LED2_PIN    (GPIO_Pin_13)
-
-#define PYB_LED3_PORT   (GPIOA)         // Same as Led(1)
-#define PYB_LED3_PIN    (GPIO_Pin_10)
-
-#define PYB_LED4_PORT   (GPIOC)         // Same as Led(2)
-#define PYB_LED4_PIN    (GPIO_Pin_13)
+#define PYB_LED1        (pin_A10)   // Blue LED
+#define PYB_LED2        (pin_C13)   // White LED (aka Power)
+#define PYB_LED3        (pin_A10)   // Same as Led(1)
+#define PYB_LED4        (pin_C13)   // Same as Led(2)
 
 #define PYB_OTYPE       (GPIO_OType_PP)
 
-#define PYB_LED_ON(port, pin)  (port->BSRRL = pin)
-#define PYB_LED_OFF(port, pin) (port->BSRRH = pin)
+#define PYB_LED_ON(pin)  (pin->gpio->BSRRL = pin->pin_mask)
+#define PYB_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask)
 
 #define HSE_VALUE (25000000)
diff --git a/stm/boards/PYBOARD3/mpconfigboard.h b/stm/boards/PYBOARD3/mpconfigboard.h
index 88573e2b1655e1e515613176ae3caec2960d476e..29e23eaab6a27a1c35dad8885d17910965a6efce 100644
--- a/stm/boards/PYBOARD3/mpconfigboard.h
+++ b/stm/boards/PYBOARD3/mpconfigboard.h
@@ -21,19 +21,12 @@
 #define USRSW_PRESSED       (0)
 
 /* LED */
-#define PYB_LED1_PORT   (GPIOA)
-#define PYB_LED1_PIN    (GPIO_Pin_8)
+#define PYB_LED1        (pin_A8)  // R1 - red
+#define PYB_LED2        (pin_A10) // R2 - red
+#define PYB_LED3        (pin_C4)  // G1 - green
+#define PYB_LED4        (pin_C5)  // G2 - green
 
-#define PYB_LED2_PORT   (GPIOA)
-#define PYB_LED2_PIN    (GPIO_Pin_10)
+#define PYB_OTYPE       (GPIO_OType_PP)
 
-#define PYB_LED3_PORT   (GPIOC)
-#define PYB_LED3_PIN    (GPIO_Pin_4)
-
-#define PYB_LED4_PORT   (GPIOC)
-#define PYB_LED4_PIN    (GPIO_Pin_5)
-
-#define PYB_OTYPE       (GPIO_OType_OD)
-
-#define PYB_LED_ON(port, pin)  (port->BSRRH = pin)
-#define PYB_LED_OFF(port, pin) (port->BSRRL = pin)
+#define PYB_LED_ON(pin)  (pin->gpio->BSRRH = pin->pin_mask)
+#define PYB_LED_OFF(pin) (pin->gpio->BSRRL = pin->pin_mask)
diff --git a/stm/boards/PYBOARD4/mpconfigboard.h b/stm/boards/PYBOARD4/mpconfigboard.h
index 88c3944312967db5eb6452856844de1d57975320..8bc8ee2ae6231b55e47751fa1a0bc1464562e9db 100644
--- a/stm/boards/PYBOARD4/mpconfigboard.h
+++ b/stm/boards/PYBOARD4/mpconfigboard.h
@@ -21,19 +21,13 @@
 #define USRSW_PRESSED       (0)
 
 /* LED */
-#define PYB_LED1_PORT   (GPIOA)
-#define PYB_LED1_PIN    (GPIO_Pin_13)
-
-#define PYB_LED2_PORT   (GPIOA)
-#define PYB_LED2_PIN    (GPIO_Pin_14)
-
-#define PYB_LED3_PORT   (GPIOA)
-#define PYB_LED3_PIN    (GPIO_Pin_15)
-
-#define PYB_LED4_PORT   (GPIOB)
-#define PYB_LED4_PIN    (GPIO_Pin_4)
+#define PYB_LED1        (pin_A13) // red
+#define PYB_LED2        (pin_A14) // green
+#define PYB_LED3        (pin_A15) // yellow
+#define PYB_LED4        (pin_B4)  // blue
 
 #define PYB_OTYPE       (GPIO_OType_PP)
 
-#define PYB_LED_ON(port, pin)  (port->BSRRL = pin)
-#define PYB_LED_OFF(port, pin) (port->BSRRH = pin)
+#define PYB_LED_ON(pin)  (pin->gpio->BSRRL = pin->pin_mask)
+#define PYB_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask)
+
diff --git a/stm/boards/STM32F4DISC/mpconfigboard.h b/stm/boards/STM32F4DISC/mpconfigboard.h
index 1e26f730ec06d2443ee76a44df44b03bfd904729..b463c90ad3d64f0822727af424736bdd8be3443d 100644
--- a/stm/boards/STM32F4DISC/mpconfigboard.h
+++ b/stm/boards/STM32F4DISC/mpconfigboard.h
@@ -21,20 +21,13 @@
 #define USRSW_PRESSED       (1)
 
 /* LED */
-#define PYB_LED1_PORT   (GPIOD)
-#define PYB_LED1_PIN    (GPIO_Pin_14)
-
-#define PYB_LED2_PORT   (GPIOD)
-#define PYB_LED2_PIN    (GPIO_Pin_12)
-
-#define PYB_LED3_PORT   (GPIOD)
-#define PYB_LED3_PIN    (GPIO_Pin_15)
-
-#define PYB_LED4_PORT   (GPIOD)
-#define PYB_LED4_PIN    (GPIO_Pin_13)
+#define PYB_LED1        (pin_D14) // red
+#define PYB_LED2        (pin_D12) // green
+#define PYB_LED3        (pin_D13) // orange
+#define PYB_LED4        (pin_D15) // blue
 
 #define PYB_OTYPE       (GPIO_OType_PP)
 
-#define PYB_LED_ON(port, pin)  (port->BSRRL = pin)
-#define PYB_LED_OFF(port, pin) (port->BSRRH = pin)
+#define PYB_LED_ON(pin)  (pin->gpio->BSRRL = pin->pin_mask)
+#define PYB_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask)
 
diff --git a/stm/led.c b/stm/led.c
index 0e02715f464229b7ea3729199b70fd7d7d0284ed..aa74dfe2f20a80cc4ce565fdc9e40d9a4b9d3080 100644
--- a/stm/led.c
+++ b/stm/led.c
@@ -7,12 +7,22 @@
 #include "qstr.h"
 #include "obj.h"
 #include "led.h"
-
-/* LED numbers, used internally */
-#define PYB_LED_1   (1)
-#define PYB_LED_2   (2)
-#define PYB_LED_3   (3)
-#define PYB_LED_4   (4)
+#include "pin.h"
+#include "build/pins.h"
+
+static const pin_obj_t *gLed[] = {
+    &PYB_LED1,
+#if defined(PYB_LED2)
+    &PYB_LED2,
+#if defined(PYB_LED3)
+    &PYB_LED3,
+#if defined(PYB_LED4)
+    &PYB_LED4,
+#endif
+#endif
+#endif
+};
+#define NUM_LEDS (sizeof(gLed) / sizeof(gLed[0]))
 
 void led_init(void) {
     /* GPIO structure */
@@ -24,92 +34,43 @@ void led_init(void) {
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
     GPIO_InitStructure.GPIO_OType = PYB_OTYPE;
 
-    /* Turn off LEDs */
-    PYB_LED_OFF(PYB_LED1_PORT, PYB_LED1_PIN);
-    PYB_LED_OFF(PYB_LED2_PORT, PYB_LED2_PIN);
-    PYB_LED_OFF(PYB_LED3_PORT, PYB_LED3_PIN);
-    PYB_LED_OFF(PYB_LED4_PORT, PYB_LED4_PIN);
-
-    /* Initialize LEDs */
-    GPIO_InitStructure.GPIO_Pin = PYB_LED1_PIN;
-    GPIO_Init(PYB_LED1_PORT, &GPIO_InitStructure);
-
-    GPIO_InitStructure.GPIO_Pin = PYB_LED2_PIN;
-    GPIO_Init(PYB_LED2_PORT, &GPIO_InitStructure);
-
-    GPIO_InitStructure.GPIO_Pin = PYB_LED3_PIN;
-    GPIO_Init(PYB_LED3_PORT, &GPIO_InitStructure);
-
-    GPIO_InitStructure.GPIO_Pin = PYB_LED4_PIN;
-    GPIO_Init(PYB_LED4_PORT, &GPIO_InitStructure);
+    /* Turn off LEDs and initialize */
+    for (int led = 0; led < NUM_LEDS; led++) {
+        PYB_LED_OFF(gLed[led]); 
+        GPIO_InitStructure.GPIO_Pin = gLed[led]->pin_mask;
+        GPIO_Init(gLed[led]->gpio, &GPIO_InitStructure);
+    }
 }
 
 void led_state(pyb_led_t led, int state) {
-    GPIO_TypeDef *port;
-    uint32_t pin;
-
-    switch (led) {
-        case PYB_LED_1:
-            pin  = PYB_LED1_PIN;
-            port = PYB_LED1_PORT;
-            break;
-        case PYB_LED_2:
-            pin  = PYB_LED2_PIN;
-            port = PYB_LED2_PORT;
-            break;
-        case PYB_LED_3:
-            pin  = PYB_LED3_PIN;
-            port = PYB_LED3_PORT;
-            break;
-        case PYB_LED_4:
-            pin  = PYB_LED4_PIN;
-            port = PYB_LED4_PORT;
-            break;
-        default:
-            return;
+    if (led < 1 || led > NUM_LEDS) {
+        return;
     }
-
+    const pin_obj_t *led_pin = gLed[led - 1];
     if (state == 0) {
         // turn LED off
-        PYB_LED_OFF(port, pin);
+        PYB_LED_OFF(led_pin);
     } else {
         // turn LED on
-        PYB_LED_ON(port, pin);
+        PYB_LED_ON(led_pin);
     }
 }
 
 void led_toggle(pyb_led_t led) {
-    GPIO_TypeDef *port;
-    uint32_t pin;
-
-    switch (led) {
-        case PYB_LED_1:
-            pin  = PYB_LED1_PIN;
-            port = PYB_LED1_PORT;
-            break;
-        case PYB_LED_2:
-            pin  = PYB_LED2_PIN;
-            port = PYB_LED2_PORT;
-            break;
-        case PYB_LED_3:
-            pin  = PYB_LED3_PIN;
-            port = PYB_LED3_PORT;
-            break;
-        case PYB_LED_4:
-            pin  = PYB_LED4_PIN;
-            port = PYB_LED4_PORT;
-            break;
-        default:
-            return;
+    if (led < 1 || led > NUM_LEDS) {
+        return;
     }
-
-    // XXX this assumes LED is driven by a high MCU output (false for PYBv3, true for PYBv4)
-    if (port->ODR & pin) {
-        // turn LED off
-        PYB_LED_OFF(port, pin);
+    const pin_obj_t *led_pin = gLed[led - 1];
+    GPIO_TypeDef *gpio = led_pin->gpio;
+
+    // We don't know if we're turning the LED on or off, but we don't really
+    // care. Just invert the state.
+    if (gpio->ODR & led_pin->pin_mask) {
+        // pin is high, make it low
+        gpio->BSRRH = led_pin->pin_mask;
     } else {
-        // turn LED on (output low)
-        PYB_LED_ON(port, pin);
+        // pin is low, make it high
+        gpio->BSRRL = led_pin->pin_mask;
     }
 }
 
@@ -138,12 +99,20 @@ mp_obj_t led_obj_off(mp_obj_t self_in) {
     return mp_const_none;
 }
 
+mp_obj_t led_obj_toggle(mp_obj_t self_in) {
+    pyb_led_obj_t *self = self_in;
+    led_toggle(self->led_id);
+    return mp_const_none;
+}
+
 static MP_DEFINE_CONST_FUN_OBJ_1(led_obj_on_obj, led_obj_on);
 static MP_DEFINE_CONST_FUN_OBJ_1(led_obj_off_obj, led_obj_off);
+static MP_DEFINE_CONST_FUN_OBJ_1(led_obj_toggle_obj, led_obj_toggle);
 
 static const mp_method_t led_methods[] = {
     { "on", &led_obj_on_obj },
     { "off", &led_obj_off_obj },
+    { "toggle", &led_obj_toggle_obj },
     { NULL, NULL },
 };