mbed library sources. Supersedes mbed-src. GR-PEACH runs on RAM.

Fork of mbed-dev by mbed official

Files at this revision

API Documentation at this revision

Comitter:
mbed_official
Date:
Fri Jan 15 13:15:11 2016 +0000
Parent:
51:2dcb841baa4f
Child:
53:340b9a9997b2
Commit message:
Synchronized with git revision fa45092ecb5b8bb969a1a14c37bb03a80c0e1ba9

Full URL: https://github.com/mbedmicro/mbed/commit/fa45092ecb5b8bb969a1a14c37bb03a80c0e1ba9/

[Silicon Labs] Allow faster I2C baudrates

Changed in this revision

targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/i2c_api.c Show annotated file Show diff for this revision Revisions of this file
targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/serial_api.c Show annotated file Show diff for this revision Revisions of this file
--- a/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/i2c_api.c	Fri Jan 15 08:00:11 2016 +0000
+++ b/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/i2c_api.c	Fri Jan 15 13:15:11 2016 +0000
@@ -107,6 +107,10 @@
     I2CName i2c_scl = (I2CName) pinmap_peripheral(scl, PinMap_I2C_SCL);
     obj->i2c.i2c = (I2C_TypeDef*) pinmap_merge(i2c_sda, i2c_scl);
     MBED_ASSERT(((int) obj->i2c.i2c) != NC);
+    
+    /* You need both SDA and SCL for I2C, so configuring one of them to NC is illegal */
+    MBED_ASSERT((uint32_t)sda != (uint32_t)NC);
+    MBED_ASSERT((uint32_t)scl != (uint32_t)NC);
 
     /* Enable clock for the peripheral */
     CMU_ClockEnable(i2c_get_clock(obj), true);
@@ -132,6 +136,8 @@
 #endif
 
     /* Set up the pins for I2C use */
+    /* Note: Set up pins in higher drive strength to reduce slew rate */
+    /*   Though this requires user knowledge, since drive strength is controlled per port, not pin */
     pin_mode(scl, WiredAndPullUp);
     pin_mode(sda, WiredAndPullUp);
 
@@ -192,7 +198,23 @@
 {
     /* Set frequency. As the second argument is 0,
      *  HFPER clock frequency is used as reference freq */
-    I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRStandard);
+    if (hz <= 0) return;
+    /* In I2C Normal mode (50% duty), we can go up to 100kHz */
+    if (hz <= 100000) {
+        I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRStandard);
+    }
+    /* In I2C Fast mode (6:3 ratio), we can go up to 400kHz */
+    else if (hz <= 400000) {
+        I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRAsymetric);
+    }
+    /* In I2C Fast+ mode (11:6 ratio), we can go up to 1 MHz */
+    else if (hz <= 1000000) {
+        I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, hz, i2cClockHLRFast);
+    }
+    /* Cap requested frequency at 1MHz */
+    else {
+        I2C_BusFreqSet(obj->i2c.i2c, REFERENCE_FREQUENCY, 1000000, i2cClockHLRFast);
+    }
 }
 
 /* Creates a start condition on the I2C bus */
@@ -352,11 +374,15 @@
 void i2c_slave_mode(i2c_t *obj, int enable_slave)
 {
     if(enable_slave) {
+        /* Reference manual note: DIV must be set to 1 during slave operation */
+        obj->i2c.i2c->CLKDIV = 1;
         obj->i2c.i2c->CTRL |= _I2C_CTRL_SLAVE_MASK;
         obj->i2c.i2c->CTRL |= _I2C_CTRL_AUTOACK_MASK; //Slave implementation assumes auto acking
     } else {
         obj->i2c.i2c->CTRL &= ~_I2C_CTRL_SLAVE_MASK;
         obj->i2c.i2c->CTRL &= ~_I2C_CTRL_AUTOACK_MASK; //Master implementation ACKs manually
+        /* function is only called with enable_slave = false through i2c_init(..), so frequency is
+           already guaranteed to be set */
     }
 }
 
--- a/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/serial_api.c	Fri Jan 15 08:00:11 2016 +0000
+++ b/targets/hal/TARGET_Silicon_Labs/TARGET_EFM32/serial_api.c	Fri Jan 15 13:15:11 2016 +0000
@@ -83,6 +83,7 @@
 static uint8_t serial_get_index(serial_t *obj);
 static void serial_enable(serial_t *obj, uint8_t enable);
 static void serial_enable_pins(serial_t *obj, uint8_t enable);
+static void serial_set_route(serial_t *obj);
 static IRQn_Type serial_get_rx_irq_index(serial_t *obj);
 static IRQn_Type serial_get_tx_irq_index(serial_t *obj);
 static CMU_Clock_TypeDef serial_get_clock(serial_t *obj);
@@ -482,7 +483,7 @@
         }
         /* Set DOUT first to prevent glitches */
         if(obj->serial.tx_pin != NC) {
-			GPIO_PinOutSet((GPIO_Port_TypeDef)(obj->serial.tx_pin >> 4 & 0xF), obj->serial.tx_pin & 0xF);
+            GPIO_PinOutSet((GPIO_Port_TypeDef)(obj->serial.tx_pin >> 4 & 0xF), obj->serial.tx_pin & 0xF);
             pin_mode(obj->serial.tx_pin, PushPull);
         }
     } else {
@@ -495,6 +496,69 @@
     }
 }
 
+static void serial_set_route(serial_t *obj)
+{
+    /* Enable pins for UART at correct location */
+    if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
+#ifdef _LEUART_ROUTE_LOCATION_SHIFT
+        obj->serial.periph.leuart->ROUTE = (obj->serial.location << _LEUART_ROUTE_LOCATION_SHIFT);
+        if(obj->serial.tx_pin != (uint32_t)NC) {
+            obj->serial.periph.leuart->ROUTE |= LEUART_ROUTE_TXPEN;
+        } else {
+            obj->serial.periph.leuart->ROUTE &= ~LEUART_ROUTE_TXPEN;
+        }
+        if(obj->serial.rx_pin != (uint32_t)NC) {
+            obj->serial.periph.leuart->ROUTE |= LEUART_ROUTE_RXPEN;
+        } else {
+            obj->serial.periph.leuart->CMD    = LEUART_CMD_RXBLOCKEN;
+            obj->serial.periph.leuart->ROUTE &= ~LEUART_ROUTE_RXPEN;
+        }
+#else
+        if(obj->serial.location_tx != NC) {
+            obj->serial.periph.leuart->ROUTELOC0 = (obj->serial.periph.leuart->ROUTELOC0 & (~_LEUART_ROUTELOC0_TXLOC_MASK)) | (obj->serial.location_tx << _LEUART_ROUTELOC0_TXLOC_SHIFT);
+            obj->serial.periph.leuart->ROUTEPEN  = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_TXPEN_MASK)) | LEUART_ROUTEPEN_TXPEN;
+        } else {
+            obj->serial.periph.leuart->ROUTEPEN  = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_TXPEN_MASK));
+        }
+        if(obj->serial.location_rx != NC) {
+            obj->serial.periph.leuart->ROUTELOC0 = (obj->serial.periph.leuart->ROUTELOC0 & (~_LEUART_ROUTELOC0_RXLOC_MASK)) | (obj->serial.location_rx << _LEUART_ROUTELOC0_RXLOC_SHIFT);
+            obj->serial.periph.leuart->ROUTEPEN  = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_RXPEN_MASK)) | LEUART_ROUTEPEN_RXPEN;
+        } else {
+            obj->serial.periph.leuart->CMD       = LEUART_CMD_RXBLOCKEN;
+            obj->serial.periph.leuart->ROUTEPEN  = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_RXPEN_MASK));
+        }
+#endif
+    } else {
+#ifdef _USART_ROUTE_LOCATION_SHIFT
+        obj->serial.periph.uart->ROUTE = (obj->serial.location << _LEUART_ROUTE_LOCATION_SHIFT);
+        if(obj->serial.tx_pin != (uint32_t)NC) {
+            obj->serial.periph.uart->ROUTE |= USART_ROUTE_TXPEN;
+        } else {
+            obj->serial.periph.uart->ROUTE &= ~USART_ROUTE_TXPEN;
+        }
+        if(obj->serial.rx_pin != (uint32_t)NC) {
+            obj->serial.periph.uart->ROUTE |= USART_ROUTE_RXPEN;
+        } else {
+            obj->serial.periph.uart->CMD    = USART_CMD_RXBLOCKEN;
+            obj->serial.periph.uart->ROUTE &= ~USART_ROUTE_RXPEN;
+        }
+#else
+        if(obj->serial.location_tx != NC) {
+            obj->serial.periph.uart->ROUTELOC0 = (obj->serial.periph.uart->ROUTELOC0 & (~_USART_ROUTELOC0_TXLOC_MASK)) | (obj->serial.location_tx << _USART_ROUTELOC0_TXLOC_SHIFT);
+            obj->serial.periph.uart->ROUTEPEN  = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_TXPEN_MASK)) | USART_ROUTEPEN_TXPEN;
+        } else {
+            obj->serial.periph.uart->ROUTEPEN  = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_TXPEN_MASK));
+        }
+        if(obj->serial.location_rx != NC) {
+            obj->serial.periph.uart->ROUTELOC0 = (obj->serial.periph.uart->ROUTELOC0 & (~_USART_ROUTELOC0_RXLOC_MASK)) | (obj->serial.location_rx << _USART_ROUTELOC0_RXLOC_SHIFT);
+            obj->serial.periph.uart->ROUTEPEN  = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_RXPEN_MASK)) | USART_ROUTEPEN_RXPEN;
+        } else {
+            obj->serial.periph.uart->CMD       = USART_CMD_RXBLOCKEN;
+            obj->serial.periph.uart->ROUTEPEN  = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_RXPEN_MASK));
+        }
+#endif
+    }
+}
 
 void serial_init(serial_t *obj, PinName tx, PinName rx)
 {
@@ -535,56 +599,13 @@
     uart_init(obj, baudrate, ParityNone, 1);
 
     /* Enable pins for UART at correct location */
+    serial_set_route(obj);
+
+    /* Reset interrupts */
     if(LEUART_REF_VALID(obj->serial.periph.leuart)) {
-#ifdef _LEUART_ROUTE_LOCATION_SHIFT
-        obj->serial.periph.leuart->ROUTE = (obj->serial.location << _LEUART_ROUTE_LOCATION_SHIFT);
-        if(tx != (uint32_t)NC) {
-            obj->serial.periph.leuart->ROUTE |= LEUART_ROUTE_TXPEN;
-        }
-        if(rx != (uint32_t)NC) {
-            obj->serial.periph.leuart->ROUTE |= LEUART_ROUTE_RXPEN;
-        }
-#else
-        if(obj->serial.location_tx != NC) {
-            obj->serial.periph.leuart->ROUTELOC0 = (obj->serial.periph.leuart->ROUTELOC0 & (~_LEUART_ROUTELOC0_TXLOC_MASK)) | (obj->serial.location_tx << _LEUART_ROUTELOC0_TXLOC_SHIFT);
-            obj->serial.periph.leuart->ROUTEPEN  = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_TXPEN_MASK)) | LEUART_ROUTEPEN_TXPEN;
-        } else {
-            obj->serial.periph.leuart->ROUTEPEN  = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_TXPEN_MASK));
-        }
-        if(obj->serial.location_rx != NC) {
-            obj->serial.periph.leuart->ROUTELOC0 = (obj->serial.periph.leuart->ROUTELOC0 & (~_LEUART_ROUTELOC0_RXLOC_MASK)) | (obj->serial.location_rx << _LEUART_ROUTELOC0_RXLOC_SHIFT);
-            obj->serial.periph.leuart->ROUTEPEN  = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_RXPEN_MASK)) | LEUART_ROUTEPEN_RXPEN;
-        } else {
-            obj->serial.periph.leuart->CMD       = LEUART_CMD_RXBLOCKEN;
-            obj->serial.periph.leuart->ROUTEPEN  = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_RXPEN_MASK));
-        }
-#endif
         obj->serial.periph.leuart->IFC = LEUART_IFC_TXC;
         obj->serial.periph.leuart->CTRL |= LEUART_CTRL_RXDMAWU | LEUART_CTRL_TXDMAWU;
     } else {
-#ifdef _USART_ROUTE_LOCATION_SHIFT
-        obj->serial.periph.uart->ROUTE = (obj->serial.location << _USART_ROUTE_LOCATION_SHIFT);
-        if(tx != (uint32_t)NC) {
-            obj->serial.periph.uart->ROUTE |= USART_ROUTE_TXPEN;
-        }
-        if(rx != (uint32_t)NC) {
-            obj->serial.periph.uart->ROUTE |= USART_ROUTE_RXPEN;
-        }
-#else
-        if(obj->serial.location_tx != NC) {
-            obj->serial.periph.uart->ROUTELOC0 = (obj->serial.periph.uart->ROUTELOC0 & (~_USART_ROUTELOC0_TXLOC_MASK)) | (obj->serial.location_tx << _USART_ROUTELOC0_TXLOC_SHIFT);
-            obj->serial.periph.uart->ROUTEPEN  = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_TXPEN_MASK)) | USART_ROUTEPEN_TXPEN;
-        } else {
-            obj->serial.periph.uart->ROUTEPEN  = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_TXPEN_MASK));
-        }
-        if(obj->serial.location_rx != NC) {
-            obj->serial.periph.uart->ROUTELOC0 = (obj->serial.periph.uart->ROUTELOC0 & (~_USART_ROUTELOC0_RXLOC_MASK)) | (obj->serial.location_rx << _USART_ROUTELOC0_RXLOC_SHIFT);
-            obj->serial.periph.uart->ROUTEPEN  = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_RXPEN_MASK)) | USART_ROUTEPEN_RXPEN;
-        } else {
-            obj->serial.periph.uart->CMD       = USART_CMD_RXBLOCKEN;
-            obj->serial.periph.uart->ROUTEPEN  = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_RXPEN_MASK));
-        }
-#endif
         obj->serial.periph.uart->IFC = USART_IFC_TXC;
     }
 
@@ -761,28 +782,7 @@
         LEUART_Init(obj->serial.periph.leuart, &init);
 
         /* Re-enable pins for UART at correct location */
-#ifdef _LEUART_ROUTE_LOCATION_SHIFT
-        obj->serial.periph.leuart->ROUTE = (obj->serial.location << _LEUART_ROUTE_LOCATION_SHIFT);
-        if(obj->serial.tx_pin != (uint32_t)NC) {
-            obj->serial.periph.leuart->ROUTE |= LEUART_ROUTE_TXPEN;
-        }
-        if(obj->serial.rx_pin != (uint32_t)NC) {
-            obj->serial.periph.leuart->ROUTE |= LEUART_ROUTE_RXPEN;
-        }
-#else
-        if(obj->serial.location_tx != NC) {
-            obj->serial.periph.leuart->ROUTELOC0 = (obj->serial.periph.leuart->ROUTELOC0 & (~_LEUART_ROUTELOC0_TXLOC_MASK)) | (obj->serial.location_tx << _LEUART_ROUTELOC0_TXLOC_SHIFT);
-            obj->serial.periph.leuart->ROUTEPEN  = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_TXPEN_MASK)) | LEUART_ROUTEPEN_TXPEN;
-        } else {
-            obj->serial.periph.leuart->ROUTEPEN  = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_TXPEN_MASK));
-        }
-        if(obj->serial.location_rx != NC) {
-            obj->serial.periph.leuart->ROUTELOC0 = (obj->serial.periph.leuart->ROUTELOC0 & (~_LEUART_ROUTELOC0_RXLOC_MASK)) | (obj->serial.location_rx << _LEUART_ROUTELOC0_RXLOC_SHIFT);
-            obj->serial.periph.leuart->ROUTEPEN  = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_RXPEN_MASK)) | LEUART_ROUTEPEN_RXPEN;
-        } else {
-            obj->serial.periph.leuart->ROUTEPEN  = (obj->serial.periph.leuart->ROUTEPEN & (~_LEUART_ROUTEPEN_RXPEN_MASK));
-        }
-#endif
+        serial_set_route(obj);
 
         /* Re-enable interrupts */
         if(was_enabled != 0) {
@@ -827,28 +827,7 @@
         USART_InitAsync(obj->serial.periph.uart, &init);
 
         /* Re-enable pins for UART at correct location */
-#ifdef _USART_ROUTE_LOCATION_SHIFT
-        obj->serial.periph.uart->ROUTE = (obj->serial.location << _USART_ROUTE_LOCATION_SHIFT);
-        if(obj->serial.tx_pin != (uint32_t)NC) {
-            obj->serial.periph.uart->ROUTE |= USART_ROUTE_TXPEN;
-        }
-        if(obj->serial.rx_pin != (uint32_t)NC) {
-            obj->serial.periph.uart->ROUTE |= USART_ROUTE_RXPEN;
-        }
-#else
-        if(obj->serial.location_tx != NC) {
-            obj->serial.periph.uart->ROUTELOC0 = (obj->serial.periph.uart->ROUTELOC0 & (~_USART_ROUTELOC0_TXLOC_MASK)) | (obj->serial.location_tx << _USART_ROUTELOC0_TXLOC_SHIFT);
-            obj->serial.periph.uart->ROUTEPEN  = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_TXPEN_MASK)) | USART_ROUTEPEN_TXPEN;
-        } else {
-            obj->serial.periph.uart->ROUTEPEN  = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_TXPEN_MASK));
-        }
-        if(obj->serial.location_rx != NC) {
-            obj->serial.periph.uart->ROUTELOC0 = (obj->serial.periph.uart->ROUTELOC0 & (~_USART_ROUTELOC0_RXLOC_MASK)) | (obj->serial.location_rx << _USART_ROUTELOC0_RXLOC_SHIFT);
-            obj->serial.periph.uart->ROUTEPEN  = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_RXPEN_MASK)) | USART_ROUTEPEN_RXPEN;
-        } else {
-            obj->serial.periph.uart->ROUTEPEN  = (obj->serial.periph.uart->ROUTEPEN & (~_USART_ROUTEPEN_RXPEN_MASK));
-        }
-#endif
+        serial_set_route(obj);
 
         /* Re-enable interrupts */
         if(was_enabled != 0) {