mbed library sources. Supersedes mbed-src.
Fork of mbed-dev by
Revision 52:4ce9155acc4d, committed 2016-01-15
- 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
--- 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) {
