summaryrefslogtreecommitdiff
path: root/examples/imx7d_sdb_m4/demo_apps/sensor_demo/common/i2c_xfer.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/imx7d_sdb_m4/demo_apps/sensor_demo/common/i2c_xfer.c')
-rw-r--r--examples/imx7d_sdb_m4/demo_apps/sensor_demo/common/i2c_xfer.c303
1 files changed, 161 insertions, 142 deletions
diff --git a/examples/imx7d_sdb_m4/demo_apps/sensor_demo/common/i2c_xfer.c b/examples/imx7d_sdb_m4/demo_apps/sensor_demo/common/i2c_xfer.c
index b8410d4..faf6395 100644
--- a/examples/imx7d_sdb_m4/demo_apps/sensor_demo/common/i2c_xfer.c
+++ b/examples/imx7d_sdb_m4/demo_apps/sensor_demo/common/i2c_xfer.c
@@ -28,294 +28,313 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "FreeRTOS.h"
+#include "task.h"
#include "semphr.h"
#include "device_imx.h"
#include "i2c_imx.h"
-#include "board.h"
-
-typedef struct _i2c_state {
- const uint8_t* cmdBuff; /*!< The buffer of I2C command. */
- const uint8_t* txBuff; /*!< The buffer of data being sent.*/
- uint8_t* rxBuff; /*!< The buffer of received data. */
- uint32_t cmdSize; /*!< The remaining number of commands to be transmitted. */
- uint32_t txSize; /*!< The remaining number of bytes to be transmitted. */
- uint32_t rxSize; /*!< The remaining number of bytes to be received. */
- bool isBusy; /*!< True if there is an active transmission. */
- uint32_t operateDir; /*!< Overall I2C bus operating direction. */
- uint32_t currentDir; /*!< Current Data transfer direction. */
- uint32_t currentMode; /*!< Current I2C Bus role of this module. */
- SemaphoreHandle_t xSemaphore; /*!< I2C internal synchronize semaphore. */
-} i2c_state_t;
-
-/* I2C runtime state structure */
-static volatile i2c_state_t i2cState;
-
-void I2C_XFER_Config(i2c_init_config_t* initConfig)
+#include "i2c_xfer.h"
+
+void I2C_XFER_Init(i2c_handle_t *handle, i2c_xfer_init_config_t *initConfig)
{
/* Initialize I2C state structure content. */
- i2cState.cmdBuff = 0;
- i2cState.txBuff = 0;
- i2cState.rxBuff = 0;
- i2cState.cmdSize = 0;
- i2cState.txSize = 0;
- i2cState.rxSize = 0;
- i2cState.isBusy = false;
- i2cState.operateDir = i2cDirectionReceive;
- i2cState.currentDir = i2cDirectionReceive;
- i2cState.currentMode = i2cModeSlave;
- i2cState.xSemaphore = xSemaphoreCreateBinary();
+ handle->base = initConfig->base;
+ handle->irqNum = initConfig->irqNum;
+ handle->irqPrio = initConfig->irqPrio;
+ handle->cmdBuff = 0;
+ handle->txBuff = 0;
+ handle->rxBuff = 0;
+ handle->cmdSize = 0;
+ handle->txSize = 0;
+ handle->rxSize = 0;
+ handle->isBusy = false;
+ handle->operateDir = i2cDirectionReceive;
+ handle->currentDir = i2cDirectionReceive;
+ handle->currentMode = i2cModeSlave;
+ handle->xSemaphore = xSemaphoreCreateBinary();
/* Initialize I2C baud rate, mode, transfer direction and slave address. */
- I2C_Init(BOARD_I2C_BASEADDR, initConfig);
+ I2C_Init(handle->base, &initConfig->config);
/* Set I2C Interrupt priority */
- NVIC_SetPriority(BOARD_I2C_IRQ_NUM, 3);
+ NVIC_SetPriority(handle->irqNum, handle->irqPrio);
/* Call core API to enable the IRQ. */
- NVIC_EnableIRQ(BOARD_I2C_IRQ_NUM);
+ NVIC_EnableIRQ(handle->irqNum);
/* Finally, enable the I2C module */
- I2C_Enable(BOARD_I2C_BASEADDR);
+ I2C_Enable(handle->base);
}
-bool I2C_XFER_SendDataBlocking(const uint8_t* cmdBuff, uint32_t cmdSize,
- const uint8_t* txBuffer, uint32_t txSize)
+bool I2C_XFER_SendDataBlocking(i2c_handle_t *handle, const uint8_t *cmdBuff, uint32_t cmdSize,
+ const uint8_t *txBuffer, uint32_t txSize)
{
- if ((i2cState.isBusy) || (0 == txSize))
+ TickType_t tickOld, tickNew;
+
+ if ((handle->isBusy) || (0 == txSize))
return false;
/* Initialize i2c transfer struct */
- i2cState.cmdBuff = cmdBuff;
- i2cState.cmdSize = cmdSize;
- i2cState.txBuff = txBuffer;
- i2cState.txSize = txSize;
- i2cState.isBusy = true;
- i2cState.operateDir = i2cDirectionTransmit;
+ handle->cmdBuff = cmdBuff;
+ handle->cmdSize = cmdSize;
+ handle->txBuff = txBuffer;
+ handle->txSize = txSize;
+ handle->isBusy = true;
+ handle->operateDir = i2cDirectionTransmit;
/* Clear I2C interrupt flag to avoid spurious interrupt */
- I2C_ClearStatusFlag(BOARD_I2C_BASEADDR, i2cStatusInterrupt);
+ I2C_ClearStatusFlag(handle->base, i2cStatusInterrupt);
- if (I2C_GetStatusFlag(BOARD_I2C_BASEADDR, i2cStatusBusBusy))
+ if (I2C_GetStatusFlag(handle->base, i2cStatusBusBusy))
{
/* Reset i2c transfer state. */
- i2cState.operateDir = i2cDirectionReceive;
- i2cState.isBusy = false;
+ handle->operateDir = i2cDirectionReceive;
+ handle->isBusy = false;
return false;
}
/* Set I2C work under Tx mode */
- I2C_SetDirMode(BOARD_I2C_BASEADDR, i2cDirectionTransmit);
- i2cState.currentDir = i2cDirectionTransmit;
+ I2C_SetDirMode(handle->base, i2cDirectionTransmit);
+ handle->currentDir = i2cDirectionTransmit;
/* Switch to Master Mode and Send Start Signal. */
- I2C_SetWorkMode(BOARD_I2C_BASEADDR, i2cModeMaster);
- i2cState.currentMode = i2cModeMaster;
+ I2C_SetWorkMode(handle->base, i2cModeMaster);
+ handle->currentMode = i2cModeMaster;
if (0 != cmdSize)
{
- I2C_WriteByte(BOARD_I2C_BASEADDR, *i2cState.cmdBuff);
- i2cState.cmdBuff++;
- i2cState.cmdSize--;
+ I2C_WriteByte(handle->base, *handle->cmdBuff);
+ handle->cmdBuff++;
+ handle->cmdSize--;
}
else
{
- I2C_WriteByte(BOARD_I2C_BASEADDR, *i2cState.txBuff);
- i2cState.txBuff++;
- i2cState.txSize--;
+ I2C_WriteByte(handle->base, *handle->txBuff);
+ handle->txBuff++;
+ handle->txSize--;
}
/* Enable I2C interrupt, subsequent data transfer will be handled in ISR. */
- I2C_SetIntCmd(BOARD_I2C_BASEADDR, true);
+ I2C_SetIntCmd(handle->base, true);
/* Wait until send data finish. */
- xSemaphoreTake(i2cState.xSemaphore, portMAX_DELAY);
+ xSemaphoreTake(handle->xSemaphore, portMAX_DELAY);
+
+ /* Wait bus idle */
+ tickOld = xTaskGetTickCount();
+
+ while (I2C_GetStatusFlag(handle->base, i2cStatusBusBusy))
+ {
+ tickNew = xTaskGetTickCount();
+
+ /* A 50ms time-out to wait bus idle */
+ if ((50 * portTICK_PERIOD_MS) < (tickNew - tickOld))
+ return false;
+ }
return true;
}
-uint32_t I2C_XFER_GetSendStatus(void)
+uint32_t I2C_XFER_GetSendStatus(i2c_handle_t *handle)
{
- return i2cState.txSize;
+ return handle->txSize;
}
-bool I2C_XFER_ReceiveDataBlocking(const uint8_t* cmdBuff, uint32_t cmdSize,
- uint8_t* rxBuffer, uint32_t rxSize)
+bool I2C_XFER_ReceiveDataBlocking(i2c_handle_t *handle, const uint8_t* cmdBuff, uint32_t cmdSize,
+ uint8_t* rxBuffer, uint32_t rxSize)
{
- if ((i2cState.isBusy) || (0 == rxSize))
+ TickType_t tickOld, tickNew;
+
+ if ((handle->isBusy) || (0 == rxSize))
return false;
/* Initialize i2c transfer struct */
- i2cState.cmdBuff = cmdBuff;
- i2cState.cmdSize = cmdSize;
- i2cState.rxBuff = rxBuffer;
- i2cState.rxSize = rxSize;
- i2cState.isBusy = true;
- i2cState.operateDir = i2cDirectionReceive;
+ handle->cmdBuff = cmdBuff;
+ handle->cmdSize = cmdSize;
+ handle->rxBuff = rxBuffer;
+ handle->rxSize = rxSize;
+ handle->isBusy = true;
+ handle->operateDir = i2cDirectionReceive;
/* Clear I2C interrupt flag to avoid spurious interrupt */
- I2C_ClearStatusFlag(BOARD_I2C_BASEADDR, i2cStatusInterrupt);
+ I2C_ClearStatusFlag(handle->base, i2cStatusInterrupt);
- if (I2C_GetStatusFlag(BOARD_I2C_BASEADDR, i2cStatusBusBusy))
+ if (I2C_GetStatusFlag(handle->base, i2cStatusBusBusy))
{
/* Reset i2c transfer state. */
- i2cState.operateDir = i2cDirectionReceive;
- i2cState.isBusy = false;
+ handle->operateDir = i2cDirectionReceive;
+ handle->isBusy = false;
return false;
}
/* Set I2C work under Tx mode */
- I2C_SetDirMode(BOARD_I2C_BASEADDR, i2cDirectionTransmit);
- i2cState.currentDir = i2cDirectionTransmit;
+ I2C_SetDirMode(handle->base, i2cDirectionTransmit);
+ handle->currentDir = i2cDirectionTransmit;
/* Switch to Master Mode and Send Start Signal. */
- I2C_SetWorkMode(BOARD_I2C_BASEADDR, i2cModeMaster);
- i2cState.currentMode = i2cModeMaster;
+ I2C_SetWorkMode(handle->base, i2cModeMaster);
+ handle->currentMode = i2cModeMaster;
/* Is there command to be sent before receive data? */
- if (0 != i2cState.cmdSize)
+ if (0 != handle->cmdSize)
{
- if (1 == i2cState.cmdSize)
- I2C_SendRepeatStart(BOARD_I2C_BASEADDR);
- I2C_WriteByte(BOARD_I2C_BASEADDR, *i2cState.cmdBuff);
- i2cState.cmdBuff++;
- i2cState.cmdSize--;
+ if (1 == handle->cmdSize)
+ I2C_SendRepeatStart(handle->base);
+ I2C_WriteByte(handle->base, *handle->cmdBuff);
+ handle->cmdBuff++;
+ handle->cmdSize--;
}
else
{
/* Change to receive state. */
- I2C_SetDirMode(BOARD_I2C_BASEADDR, i2cDirectionReceive);
- i2cState.currentDir = i2cDirectionReceive;
+ I2C_SetDirMode(handle->base, i2cDirectionReceive);
+ handle->currentDir = i2cDirectionReceive;
if (1 == rxSize)
/* Send Nack */
- I2C_SetAckBit(BOARD_I2C_BASEADDR, false);
+ I2C_SetAckBit(handle->base, false);
else
/* Send Ack */
- I2C_SetAckBit(BOARD_I2C_BASEADDR, true);
+ I2C_SetAckBit(handle->base, true);
/* dummy read to clock in 1st byte */
- I2C_ReadByte(BOARD_I2C_BASEADDR);
+ I2C_ReadByte(handle->base);
}
/* Enable I2C interrupt, subsequent data transfer will be handled in ISR. */
- I2C_SetIntCmd(BOARD_I2C_BASEADDR, true);
+ I2C_SetIntCmd(handle->base, true);
/* Wait until receive data finish. */
- xSemaphoreTake(i2cState.xSemaphore, portMAX_DELAY);
+ xSemaphoreTake(handle->xSemaphore, portMAX_DELAY);
+
+ /* Wait bus idle */
+ tickOld = xTaskGetTickCount();
+
+ while (I2C_GetStatusFlag(handle->base, i2cStatusBusBusy))
+ {
+ tickNew = xTaskGetTickCount();
+
+ /* A 50ms time-out to wait bus idle */
+ if ((50 * portTICK_PERIOD_MS) < (tickNew - tickOld))
+ return false;
+ }
return true;
}
-uint32_t I2C_XFER_GetReceiveStatus(void)
+uint32_t I2C_XFER_GetReceiveStatus(i2c_handle_t *handle)
{
- return i2cState.rxSize;
+ return handle->rxSize;
}
-void BOARD_I2C_HANDLER(void)
+void I2C_XFER_Handler(i2c_handle_t *handle)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* Clear interrupt flag. */
- I2C_ClearStatusFlag(BOARD_I2C_BASEADDR, i2cStatusInterrupt);
+ I2C_ClearStatusFlag(handle->base, i2cStatusInterrupt);
/* Exit the ISR if no transfer is happening for this instance. */
- if (!i2cState.isBusy)
+ if (!handle->isBusy)
return;
- if (i2cModeMaster == i2cState.currentMode)
+ if (i2cModeMaster == handle->currentMode)
{
- if (i2cDirectionTransmit == i2cState.currentDir)
+ if (i2cDirectionTransmit == handle->currentDir)
{
- if ((I2C_GetStatusFlag(BOARD_I2C_BASEADDR, i2cStatusReceivedAck)) ||
- ((0 == i2cState.txSize) && (0 == i2cState.cmdSize)))
+ if ((I2C_GetStatusFlag(handle->base, i2cStatusReceivedAck)) ||
+ ((0 == handle->txSize) && (0 == handle->cmdSize)))
{
- if ((i2cDirectionTransmit == i2cState.operateDir) ||
- (I2C_GetStatusFlag(BOARD_I2C_BASEADDR, i2cStatusReceivedAck)))
+ if ((i2cDirectionTransmit == handle->operateDir) ||
+ (I2C_GetStatusFlag(handle->base, i2cStatusReceivedAck)))
{
/* Switch to Slave mode and Generate a Stop Signal. */
- I2C_SetWorkMode(BOARD_I2C_BASEADDR, i2cModeSlave);
- i2cState.currentMode = i2cModeSlave;
+ I2C_SetWorkMode(handle->base, i2cModeSlave);
+ handle->currentMode = i2cModeSlave;
/* Switch back to Rx direction. */
- I2C_SetDirMode(BOARD_I2C_BASEADDR, i2cDirectionReceive);
- i2cState.currentDir = i2cDirectionReceive;
+ I2C_SetDirMode(handle->base, i2cDirectionReceive);
+ handle->currentDir = i2cDirectionReceive;
/* Close I2C interrupt. */
- I2C_SetIntCmd(BOARD_I2C_BASEADDR, false);
+ I2C_SetIntCmd(handle->base, false);
/* Release I2C Bus. */
- i2cState.isBusy = false;
- xSemaphoreGiveFromISR(i2cState.xSemaphore, &xHigherPriorityTaskWoken);
+ handle->isBusy = false;
+ xSemaphoreGiveFromISR(handle->xSemaphore, &xHigherPriorityTaskWoken);
+ /* Perform a context switch to wake the higher priority task. */
+ portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
else
{
/* Switch back to Rx direction. */
- I2C_SetDirMode(BOARD_I2C_BASEADDR, i2cDirectionReceive);
- i2cState.currentDir = i2cDirectionReceive;
+ I2C_SetDirMode(handle->base, i2cDirectionReceive);
+ handle->currentDir = i2cDirectionReceive;
- if (1 == i2cState.rxSize)
+ if (1 == handle->rxSize)
/* Send Nack */
- I2C_SetAckBit(BOARD_I2C_BASEADDR, false);
+ I2C_SetAckBit(handle->base, false);
else
/* Send Ack */
- I2C_SetAckBit(BOARD_I2C_BASEADDR, true);
+ I2C_SetAckBit(handle->base, true);
/* dummy read to clock in 1st byte */
- *i2cState.rxBuff = I2C_ReadByte(BOARD_I2C_BASEADDR);
+ *handle->rxBuff = I2C_ReadByte(handle->base);
}
}
else
{
- if (0 != i2cState.cmdSize)
+ if (0 != handle->cmdSize)
{
- if ((1 == i2cState.cmdSize) && (i2cDirectionReceive == i2cState.operateDir))
- I2C_SendRepeatStart(BOARD_I2C_BASEADDR);
- I2C_WriteByte(BOARD_I2C_BASEADDR, *i2cState.cmdBuff);
- i2cState.cmdBuff++;
- i2cState.cmdSize--;
+ if ((1 == handle->cmdSize) && (i2cDirectionReceive == handle->operateDir))
+ I2C_SendRepeatStart(handle->base);
+ I2C_WriteByte(handle->base, *handle->cmdBuff);
+ handle->cmdBuff++;
+ handle->cmdSize--;
}
else
{
- I2C_WriteByte(BOARD_I2C_BASEADDR, *i2cState.txBuff);
- i2cState.txBuff++;
- i2cState.txSize--;
+ I2C_WriteByte(handle->base, *handle->txBuff);
+ handle->txBuff++;
+ handle->txSize--;
}
}
}
else
{
/* Normal read operation. */
- if (2 == i2cState.rxSize)
+ if (2 == handle->rxSize)
/* Send Nack */
- I2C_SetAckBit(BOARD_I2C_BASEADDR, false);
+ I2C_SetAckBit(handle->base, false);
else
/* Send Nack */
- I2C_SetAckBit(BOARD_I2C_BASEADDR, true);
+ I2C_SetAckBit(handle->base, true);
- if (1 == i2cState.rxSize)
+ if (1 == handle->rxSize)
{
/* Switch back to Tx direction to avoid additional I2C bus read. */
- I2C_SetDirMode(BOARD_I2C_BASEADDR, i2cDirectionTransmit);
- i2cState.currentDir = i2cDirectionTransmit;
+ I2C_SetDirMode(handle->base, i2cDirectionTransmit);
+ handle->currentDir = i2cDirectionTransmit;
}
- *i2cState.rxBuff = I2C_ReadByte(BOARD_I2C_BASEADDR);
- i2cState.rxBuff++;
- i2cState.rxSize--;
+ *handle->rxBuff = I2C_ReadByte(handle->base);
+ handle->rxBuff++;
+ handle->rxSize--;
/* receive finished. */
- if (0 == i2cState.rxSize)
+ if (0 == handle->rxSize)
{
/* Switch to Slave mode and Generate a Stop Signal. */
- I2C_SetWorkMode(BOARD_I2C_BASEADDR, i2cModeSlave);
- i2cState.currentMode = i2cModeSlave;
+ I2C_SetWorkMode(handle->base, i2cModeSlave);
+ handle->currentMode = i2cModeSlave;
/* Switch back to Rx direction. */
- I2C_SetDirMode(BOARD_I2C_BASEADDR, i2cDirectionReceive);
- i2cState.currentDir = i2cDirectionReceive;
+ I2C_SetDirMode(handle->base, i2cDirectionReceive);
+ handle->currentDir = i2cDirectionReceive;
/* Close I2C interrupt. */
- I2C_SetIntCmd(BOARD_I2C_BASEADDR, false);
+ I2C_SetIntCmd(handle->base, false);
/* Release I2C Bus. */
- i2cState.isBusy = false;
+ handle->isBusy = false;
/* Release I2C Sem4 */
- xSemaphoreGiveFromISR(i2cState.xSemaphore, &xHigherPriorityTaskWoken);
+ xSemaphoreGiveFromISR(handle->xSemaphore, &xHigherPriorityTaskWoken);
+ /* Perform a context switch to wake the higher priority task. */
+ portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
}