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.
Dependents: SPIne CH_Communicatuin_Test CH_Communicatuin_Test2 MCP_SPIne ... more
Fork of mbed-dev-f303 by
Diff: targets/TARGET_STM/i2c_api.c
- Revision:
- 156:95d6b41a828b
- Parent:
- 154:37f96f9d4de2
- Child:
- 157:ff67d9f36b67
--- a/targets/TARGET_STM/i2c_api.c Thu Jan 05 10:51:54 2017 +0000
+++ b/targets/TARGET_STM/i2c_api.c Mon Jan 16 15:03:32 2017 +0000
@@ -341,6 +341,9 @@
// I2C Xfer operation init
obj_s->event = 0;
obj_s->XferOperation = I2C_FIRST_AND_LAST_FRAME;
+#ifdef I2C_IP_VERSION_V2
+ obj_s->pending_start = 0;
+#endif
}
void i2c_frequency(i2c_t *obj, int hz)
@@ -366,22 +369,22 @@
if (hz == 1000000) {
#if defined(I2C1_BASE) && defined(__HAL_SYSCFG_FASTMODEPLUS_ENABLE) && defined (I2C_FASTMODEPLUS_I2C1)
if (obj_s->i2c == I2C_1) {
- __HAL_SYSCFG_FASTMODEPLUS_ENABLE(I2C_FASTMODEPLUS_I2C1);
+ HAL_I2CEx_EnableFastModePlus(I2C_FASTMODEPLUS_I2C1);
}
#endif
#if defined(I2C2_BASE) && defined(__HAL_SYSCFG_FASTMODEPLUS_ENABLE) && defined (I2C_FASTMODEPLUS_I2C2)
if (obj_s->i2c == I2C_2) {
- __HAL_SYSCFG_FASTMODEPLUS_ENABLE(I2C_FASTMODEPLUS_I2C2);
+ HAL_I2CEx_EnableFastModePlus(I2C_FASTMODEPLUS_I2C2);
}
#endif
#if defined(I2C3_BASE) && defined(__HAL_SYSCFG_FASTMODEPLUS_ENABLE) && defined (I2C_FASTMODEPLUS_I2C3)
if (obj_s->i2c == I2C_3) {
- __HAL_SYSCFG_FASTMODEPLUS_ENABLE(I2C_FASTMODEPLUS_I2C3);
+ HAL_I2CEx_EnableFastModePlus(I2C_FASTMODEPLUS_I2C3);
}
#endif
#if defined(I2C4_BASE) && defined(__HAL_SYSCFG_FASTMODEPLUS_ENABLE) && defined (I2C_FASTMODEPLUS_I2C4)
if (obj_s->i2c == I2C_4) {
- __HAL_SYSCFG_FASTMODEPLUS_ENABLE(I2C_FASTMODEPLUS_I2C4);
+ HAL_I2CEx_EnableFastModePlus(I2C_FASTMODEPLUS_I2C4);
}
#endif
}
@@ -440,6 +443,14 @@
return (obj);
}
+void i2c_reset(i2c_t *obj) {
+ struct i2c_s *obj_s = I2C_S(obj);
+ /* As recommended in i2c_api.h, mainly send stop */
+ i2c_stop(obj);
+ /* then re-init */
+ i2c_init(obj, obj_s->sda, obj_s->scl);
+}
+
/*
* UNITARY APIS.
* For very basic operations, direct registers access is needed
@@ -535,7 +546,7 @@
(__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BTF) == RESET) &&
(__HAL_I2C_GET_FLAG(handle, I2C_FLAG_ADDR) == RESET)) {
if ((timeout--) == 0) {
- return 0;
+ return 2;
}
}
@@ -548,92 +559,161 @@
}
#endif //I2C_IP_VERSION_V1
#ifdef I2C_IP_VERSION_V2
+
int i2c_start(i2c_t *obj) {
struct i2c_s *obj_s = I2C_S(obj);
- I2C_HandleTypeDef *handle = &(obj_s->handle);
- I2C_TypeDef *i2c = (I2C_TypeDef *)obj_s->i2c;
- int timeout;
-
- // Clear Acknowledge failure flag
- __HAL_I2C_CLEAR_FLAG(handle, I2C_FLAG_AF);
-
- // Wait the STOP condition has been previously correctly sent
- timeout = FLAG_TIMEOUT;
- while ((i2c->CR2 & I2C_CR2_STOP) == I2C_CR2_STOP){
- if ((timeout--) == 0) {
- return 1;
- }
- }
-
- // Generate the START condition
- i2c->CR2 |= I2C_CR2_START;
-
- // Wait the START condition has been correctly sent
- timeout = FLAG_TIMEOUT;
- while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_BUSY) == RESET) {
- if ((timeout--) == 0) {
- return 1;
- }
- }
-
+ /* This I2C IP doesn't */
+ obj_s->pending_start = 1;
return 0;
}
int i2c_stop(i2c_t *obj) {
struct i2c_s *obj_s = I2C_S(obj);
- I2C_TypeDef *i2c = (I2C_TypeDef *)obj_s->i2c;
+ I2C_HandleTypeDef *handle = &(obj_s->handle);
+ int timeout = FLAG_TIMEOUT;
+#if DEVICE_I2CSLAVE
+ if (obj_s->slave) {
+ /* re-init slave when stop is requested */
+ i2c_init(obj, obj_s->sda, obj_s->scl);
+ return 0;
+ }
+#endif
+ // Disable reload mode
+ handle->Instance->CR2 &= (uint32_t)~I2C_CR2_RELOAD;
+ // Generate the STOP condition
+ handle->Instance->CR2 |= I2C_CR2_STOP;
- // Generate the STOP condition
- i2c->CR2 |= I2C_CR2_STOP;
+ timeout = FLAG_TIMEOUT;
+ while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_STOPF)) {
+ if ((timeout--) == 0) {
+ return I2C_ERROR_BUS_BUSY;
+ }
+ }
+
+ /* Clear STOP Flag */
+ __HAL_I2C_CLEAR_FLAG(handle, I2C_FLAG_STOPF);
+
+ /* Erase slave address, this wiil be used as a marker
+ * to know when we need to prepare next start */
+ handle->Instance->CR2 &= ~I2C_CR2_SADD;
+
+ /* In case of mixed usage of the APIs (unitary + SYNC)
+ * re-inti HAL state */
+ if (obj_s->XferOperation != I2C_FIRST_AND_LAST_FRAME) {
+ i2c_init(obj, obj_s->sda, obj_s->scl);
+ }
return 0;
}
int i2c_byte_read(i2c_t *obj, int last) {
struct i2c_s *obj_s = I2C_S(obj);
- I2C_TypeDef *i2c = (I2C_TypeDef *)obj_s->i2c;
I2C_HandleTypeDef *handle = &(obj_s->handle);
- int timeout;
+ int timeout = FLAG_TIMEOUT;
+ uint32_t tmpreg = handle->Instance->CR2;
+ char data;
+#if DEVICE_I2CSLAVE
+ if (obj_s->slave) {
+ return i2c_slave_read(obj, &data, 1);
+ }
+#endif
+ /* Then send data when there's room in the TX fifo */
+ if ((tmpreg & I2C_CR2_RELOAD) != 0) {
+ while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TCR)) {
+ if ((timeout--) == 0) {
+ DEBUG_PRINTF("timeout in byte_read\r\n");
+ return -1;
+ }
+ }
+ }
- // Wait until the byte is received
+ /* Enable reload mode as we don't know how many bytes will eb sent */
+ handle->Instance->CR2 |= I2C_CR2_RELOAD;
+ /* Set transfer size to 1 */
+ handle->Instance->CR2 |= (I2C_CR2_NBYTES & (1 << 16));
+ /* Set the prepared configuration */
+ handle->Instance->CR2 = tmpreg;
+
timeout = FLAG_TIMEOUT;
- while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_RXNE) == RESET) {
+ while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_RXNE)) {
if ((timeout--) == 0) {
return -1;
}
}
- return (int)i2c->RXDR;
+ /* Then Get Byte */
+ data = handle->Instance->RXDR;
+
+ if (last) {
+ /* Disable Address Acknowledge */
+ handle->Instance->CR2 |= I2C_CR2_NACK;
+ }
+
+ return data;
}
int i2c_byte_write(i2c_t *obj, int data) {
struct i2c_s *obj_s = I2C_S(obj);
- I2C_TypeDef *i2c = (I2C_TypeDef *)obj_s->i2c;
I2C_HandleTypeDef *handle = &(obj_s->handle);
- int timeout;
+ int timeout = FLAG_TIMEOUT;
+ uint32_t tmpreg = handle->Instance->CR2;
+#if DEVICE_I2CSLAVE
+ if (obj_s->slave) {
+ return i2c_slave_write(obj, (char *) &data, 1);
+ }
+#endif
+ if (obj_s->pending_start) {
+ obj_s->pending_start = 0;
+ //* First byte after the start is the address */
+ tmpreg |= (uint32_t)((uint32_t)data & I2C_CR2_SADD);
+ if (data & 0x01) {
+ tmpreg |= I2C_CR2_START | I2C_CR2_RD_WRN;
+ } else {
+ tmpreg |= I2C_CR2_START;
+ tmpreg &= ~I2C_CR2_RD_WRN;
+ }
+ /* Disable reload first to use it later */
+ tmpreg &= ~I2C_CR2_RELOAD;
+ /* Disable Autoend */
+ tmpreg &= ~I2C_CR2_AUTOEND;
+ /* Do not set any transfer size for now */
+ tmpreg |= (I2C_CR2_NBYTES & (1 << 16));
+ /* Set the prepared configuration */
+ handle->Instance->CR2 = tmpreg;
+ } else {
+ /* Set the prepared configuration */
+ tmpreg = handle->Instance->CR2;
- // Wait until the previous byte is transmitted
- timeout = FLAG_TIMEOUT;
- while (__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TXIS) == RESET) {
- if ((timeout--) == 0) {
- return 0;
+ /* Then send data when there's room in the TX fifo */
+ if ((tmpreg & I2C_CR2_RELOAD) != 0) {
+ while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TCR)) {
+ if ((timeout--) == 0) {
+ DEBUG_PRINTF("timeout in byte_write\r\n");
+ return 2;
+ }
+ }
}
+ /* Enable reload mode as we don't know how many bytes will eb sent */
+ tmpreg |= I2C_CR2_RELOAD;
+ /* Set transfer size to 1 */
+ tmpreg |= (I2C_CR2_NBYTES & (1 << 16));
+ /* Set the prepared configuration */
+ handle->Instance->CR2 = tmpreg;
+ /* Prepare next write */
+ timeout = FLAG_TIMEOUT;
+ while (!__HAL_I2C_GET_FLAG(handle, I2C_FLAG_TXE)) {
+ if ((timeout--) == 0) {
+ return 2;
+ }
+ }
+ /* Write byte */
+ handle->Instance->TXDR = data;
}
- i2c->TXDR = (uint8_t)data;
-
return 1;
}
#endif //I2C_IP_VERSION_V2
-void i2c_reset(i2c_t *obj) {
- struct i2c_s *obj_s = I2C_S(obj);
- /* As recommended in i2c_api.h, mainly send stop */
- i2c_stop(obj);
- /* then re-init */
- i2c_init(obj, obj_s->sda, obj_s->scl);
-}
-
/*
* SYNC APIS
*/
