Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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) {
