fsl_i2c_dma.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. /*
  2. * The Clear BSD License
  3. * Copyright (c) 2016, Freescale Semiconductor, Inc.
  4. * Copyright 2016-2017 NXP
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without modification,
  8. * are permitted (subject to the limitations in the disclaimer below) provided
  9. * that the following conditions are met:
  10. *
  11. * o Redistributions of source code must retain the above copyright notice, this list
  12. * of conditions and the following disclaimer.
  13. *
  14. * o Redistributions in binary form must reproduce the above copyright notice, this
  15. * list of conditions and the following disclaimer in the documentation and/or
  16. * other materials provided with the distribution.
  17. *
  18. * o Neither the name of the copyright holder nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  24. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  25. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  27. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  28. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  30. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include "fsl_i2c_dma.h"
  35. #include "fsl_flexcomm.h"
  36. /*******************************************************************************
  37. * Definitions
  38. ******************************************************************************/
  39. /* Component ID definition, used by tools. */
  40. #ifndef FSL_COMPONENT_ID
  41. #define FSL_COMPONENT_ID "platform.drivers.flexcomm_i2c_dma"
  42. #endif
  43. /*<! @brief Structure definition for i2c_master_dma_handle_t. The structure is private. */
  44. typedef struct _i2c_master_dma_private_handle
  45. {
  46. I2C_Type *base;
  47. i2c_master_dma_handle_t *handle;
  48. } i2c_master_dma_private_handle_t;
  49. /*******************************************************************************
  50. * Prototypes
  51. ******************************************************************************/
  52. /*!
  53. * @brief DMA callback for I2C master DMA driver.
  54. *
  55. * @param handle DMA handler for I2C master DMA driver
  56. * @param userData user param passed to the callback function
  57. */
  58. static void I2C_MasterTransferCallbackDMA(dma_handle_t *handle, void *userData);
  59. /*!
  60. * @brief Set up master transfer, send slave address and sub address(if any), wait until the
  61. * wait until address sent status return.
  62. *
  63. * @param base I2C peripheral base address.
  64. * @param handle pointer to i2c_master_dma_handle_t structure which stores the transfer state.
  65. * @param xfer pointer to i2c_master_transfer_t structure.
  66. */
  67. static status_t I2C_InitTransferStateMachineDMA(I2C_Type *base,
  68. i2c_master_dma_handle_t *handle,
  69. i2c_master_transfer_t *xfer);
  70. /*******************************************************************************
  71. * Variables
  72. ******************************************************************************/
  73. /*<! Private handle only used for internally. */
  74. static i2c_master_dma_private_handle_t s_dmaPrivateHandle[FSL_FEATURE_SOC_I2C_COUNT];
  75. /*! @brief IRQ name array */
  76. static const IRQn_Type s_i2cIRQ[] = I2C_IRQS;
  77. /*******************************************************************************
  78. * Codes
  79. ******************************************************************************/
  80. /*!
  81. * @brief Prepares the transfer state machine and fills in the command buffer.
  82. * @param handle Master nonblocking driver handle.
  83. */
  84. static status_t I2C_InitTransferStateMachineDMA(I2C_Type *base,
  85. i2c_master_dma_handle_t *handle,
  86. i2c_master_transfer_t *xfer)
  87. {
  88. struct _i2c_master_transfer *transfer;
  89. handle->transfer = *xfer;
  90. transfer = &(handle->transfer);
  91. handle->transferCount = 0;
  92. handle->remainingBytesDMA = 0;
  93. handle->buf = (uint8_t *)transfer->data;
  94. handle->remainingSubaddr = 0;
  95. if (transfer->flags & kI2C_TransferNoStartFlag)
  96. {
  97. /* Start condition shall be ommited, switch directly to next phase */
  98. if (transfer->dataSize == 0)
  99. {
  100. handle->state = kStopState;
  101. }
  102. else if (handle->transfer.direction == kI2C_Write)
  103. {
  104. handle->state = xfer->dataSize = kTransmitDataState;
  105. }
  106. else if (handle->transfer.direction == kI2C_Read)
  107. {
  108. handle->state = (xfer->dataSize == 1) ? kReceiveLastDataState : kReceiveDataState;
  109. }
  110. else
  111. {
  112. return kStatus_I2C_InvalidParameter;
  113. }
  114. }
  115. else
  116. {
  117. if (transfer->subaddressSize != 0)
  118. {
  119. int i;
  120. uint32_t subaddress;
  121. if (transfer->subaddressSize > sizeof(handle->subaddrBuf))
  122. {
  123. return kStatus_I2C_InvalidParameter;
  124. }
  125. /* Prepare subaddress transmit buffer, most significant byte is stored at the lowest address */
  126. subaddress = xfer->subaddress;
  127. for (i = xfer->subaddressSize - 1; i >= 0; i--)
  128. {
  129. handle->subaddrBuf[i] = subaddress & 0xff;
  130. subaddress >>= 8;
  131. }
  132. handle->remainingSubaddr = transfer->subaddressSize;
  133. }
  134. handle->state = kStartState;
  135. }
  136. return kStatus_Success;
  137. }
  138. static void I2C_RunDMATransfer(I2C_Type *base, i2c_master_dma_handle_t *handle)
  139. {
  140. int transfer_size;
  141. dma_transfer_config_t xferConfig;
  142. /* Update transfer count */
  143. handle->transferCount = handle->buf - (uint8_t *)handle->transfer.data;
  144. /* Check if there is anything to be transferred at all */
  145. if (handle->remainingBytesDMA == 0)
  146. {
  147. /* No data to be transferrred, disable DMA */
  148. base->MSTCTL = 0;
  149. return;
  150. }
  151. /* Calculate transfer size */
  152. transfer_size = handle->remainingBytesDMA;
  153. if (transfer_size > I2C_MAX_DMA_TRANSFER_COUNT)
  154. {
  155. transfer_size = I2C_MAX_DMA_TRANSFER_COUNT;
  156. }
  157. switch (handle->transfer.direction)
  158. {
  159. case kI2C_Write:
  160. DMA_PrepareTransfer(&xferConfig, handle->buf, (void *)&base->MSTDAT, sizeof(uint8_t), transfer_size,
  161. kDMA_MemoryToPeripheral, NULL);
  162. break;
  163. case kI2C_Read:
  164. DMA_PrepareTransfer(&xferConfig, (void *)&base->MSTDAT, handle->buf, sizeof(uint8_t), transfer_size,
  165. kDMA_PeripheralToMemory, NULL);
  166. break;
  167. default:
  168. /* This should never happen */
  169. assert(0);
  170. break;
  171. }
  172. DMA_SubmitTransfer(handle->dmaHandle, &xferConfig);
  173. DMA_StartTransfer(handle->dmaHandle);
  174. handle->remainingBytesDMA -= transfer_size;
  175. handle->buf += transfer_size;
  176. }
  177. /*!
  178. * @brief Execute states until the transfer is done.
  179. * @param handle Master nonblocking driver handle.
  180. * @param[out] isDone Set to true if the transfer has completed.
  181. * @retval #kStatus_Success
  182. * @retval #kStatus_I2C_ArbitrationLost
  183. * @retval #kStatus_I2C_Nak
  184. */
  185. static status_t I2C_RunTransferStateMachineDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, bool *isDone)
  186. {
  187. uint32_t status;
  188. uint32_t master_state;
  189. struct _i2c_master_transfer *transfer;
  190. dma_transfer_config_t xferConfig;
  191. status_t err;
  192. uint32_t start_flag = 0;
  193. transfer = &(handle->transfer);
  194. *isDone = false;
  195. status = I2C_GetStatusFlags(base);
  196. if (status & I2C_STAT_MSTARBLOSS_MASK)
  197. {
  198. I2C_MasterClearStatusFlags(base, I2C_STAT_MSTARBLOSS_MASK);
  199. DMA_AbortTransfer(handle->dmaHandle);
  200. base->MSTCTL = 0;
  201. return kStatus_I2C_ArbitrationLost;
  202. }
  203. if (status & I2C_STAT_MSTSTSTPERR_MASK)
  204. {
  205. I2C_MasterClearStatusFlags(base, I2C_STAT_MSTSTSTPERR_MASK);
  206. DMA_AbortTransfer(handle->dmaHandle);
  207. base->MSTCTL = 0;
  208. return kStatus_I2C_StartStopError;
  209. }
  210. if ((status & I2C_STAT_MSTPENDING_MASK) == 0)
  211. {
  212. return kStatus_I2C_Busy;
  213. }
  214. /* Get the state of the I2C module */
  215. master_state = (status & I2C_STAT_MSTSTATE_MASK) >> I2C_STAT_MSTSTATE_SHIFT;
  216. if ((master_state == I2C_STAT_MSTCODE_NACKADR) || (master_state == I2C_STAT_MSTCODE_NACKDAT))
  217. {
  218. /* Slave NACKed last byte, issue stop and return error */
  219. DMA_AbortTransfer(handle->dmaHandle);
  220. base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
  221. handle->state = kWaitForCompletionState;
  222. return kStatus_I2C_Nak;
  223. }
  224. err = kStatus_Success;
  225. if (handle->state == kStartState)
  226. {
  227. /* set start flag for later use */
  228. start_flag = I2C_MSTCTL_MSTSTART_MASK;
  229. if (handle->remainingSubaddr)
  230. {
  231. base->MSTDAT = (uint32_t)transfer->slaveAddress << 1;
  232. handle->state = kTransmitSubaddrState;
  233. }
  234. else if (transfer->direction == kI2C_Write)
  235. {
  236. base->MSTDAT = (uint32_t)transfer->slaveAddress << 1;
  237. if (transfer->dataSize == 0)
  238. {
  239. /* No data to be transferred, initiate start and schedule stop */
  240. base->MSTCTL = I2C_MSTCTL_MSTSTART_MASK;
  241. handle->state = kStopState;
  242. return err;
  243. }
  244. handle->state = kTransmitDataState;
  245. }
  246. else if ((transfer->direction == kI2C_Read) && (transfer->dataSize > 0))
  247. {
  248. base->MSTDAT = ((uint32_t)transfer->slaveAddress << 1) | 1u;
  249. if (transfer->dataSize == 1)
  250. {
  251. /* The very last byte is always received by means of SW */
  252. base->MSTCTL = I2C_MSTCTL_MSTSTART_MASK;
  253. handle->state = kReceiveLastDataState;
  254. return err;
  255. }
  256. handle->state = kReceiveDataState;
  257. }
  258. else
  259. {
  260. handle->state = kIdleState;
  261. err = kStatus_I2C_UnexpectedState;
  262. return err;
  263. }
  264. }
  265. switch (handle->state)
  266. {
  267. case kTransmitSubaddrState:
  268. if ((master_state != I2C_STAT_MSTCODE_TXREADY) && (!start_flag))
  269. {
  270. return kStatus_I2C_UnexpectedState;
  271. }
  272. base->MSTCTL = start_flag | I2C_MSTCTL_MSTDMA_MASK;
  273. /* Prepare and submit DMA transfer. */
  274. DMA_PrepareTransfer(&xferConfig, handle->subaddrBuf, (void *)&base->MSTDAT, sizeof(uint8_t),
  275. handle->remainingSubaddr, kDMA_MemoryToPeripheral, NULL);
  276. DMA_SubmitTransfer(handle->dmaHandle, &xferConfig);
  277. DMA_StartTransfer(handle->dmaHandle);
  278. handle->remainingSubaddr = 0;
  279. if (transfer->dataSize)
  280. {
  281. /* There is data to be transferred, if there is write to read turnaround it is necessary to perform
  282. * repeated start */
  283. handle->state = (transfer->direction == kI2C_Read) ? kStartState : kTransmitDataState;
  284. }
  285. else
  286. {
  287. /* No more data, schedule stop condition */
  288. handle->state = kStopState;
  289. }
  290. break;
  291. case kTransmitDataState:
  292. if ((master_state != I2C_STAT_MSTCODE_TXREADY) && (!start_flag))
  293. {
  294. return kStatus_I2C_UnexpectedState;
  295. }
  296. base->MSTCTL = start_flag | I2C_MSTCTL_MSTDMA_MASK;
  297. handle->remainingBytesDMA = handle->transfer.dataSize;
  298. I2C_RunDMATransfer(base, handle);
  299. /* Schedule stop condition */
  300. handle->state = kStopState;
  301. break;
  302. case kReceiveDataState:
  303. if ((master_state != I2C_STAT_MSTCODE_RXREADY) && (!start_flag))
  304. {
  305. return kStatus_I2C_UnexpectedState;
  306. }
  307. base->MSTCTL = start_flag | I2C_MSTCTL_MSTDMA_MASK;
  308. handle->remainingBytesDMA = handle->transfer.dataSize - 1;
  309. I2C_RunDMATransfer(base, handle);
  310. /* Schedule reception of last data byte */
  311. handle->state = kReceiveLastDataState;
  312. break;
  313. case kReceiveLastDataState:
  314. if (master_state != I2C_STAT_MSTCODE_RXREADY)
  315. {
  316. return kStatus_I2C_UnexpectedState;
  317. }
  318. ((uint8_t *)transfer->data)[transfer->dataSize - 1] = base->MSTDAT;
  319. handle->transferCount++;
  320. /* No more data expected, issue NACK and STOP right away */
  321. base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
  322. handle->state = kWaitForCompletionState;
  323. break;
  324. case kStopState:
  325. if (transfer->flags & kI2C_TransferNoStopFlag)
  326. {
  327. /* Stop condition is omitted, we are done */
  328. *isDone = true;
  329. handle->state = kIdleState;
  330. break;
  331. }
  332. /* Send stop condition */
  333. base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
  334. handle->state = kWaitForCompletionState;
  335. break;
  336. case kWaitForCompletionState:
  337. *isDone = true;
  338. handle->state = kIdleState;
  339. break;
  340. case kStartState:
  341. case kIdleState:
  342. default:
  343. /* State machine shall not be invoked again once it enters the idle state */
  344. err = kStatus_I2C_UnexpectedState;
  345. break;
  346. }
  347. return err;
  348. }
  349. void I2C_MasterTransferDMAHandleIRQ(I2C_Type *base, i2c_master_dma_handle_t *handle)
  350. {
  351. bool isDone;
  352. status_t result;
  353. /* Don't do anything if we don't have a valid handle. */
  354. if (!handle)
  355. {
  356. return;
  357. }
  358. result = I2C_RunTransferStateMachineDMA(base, handle, &isDone);
  359. if (isDone || (result != kStatus_Success))
  360. {
  361. /* Disable internal IRQ enables. */
  362. I2C_DisableInterrupts(base,
  363. I2C_INTSTAT_MSTPENDING_MASK | I2C_INTSTAT_MSTARBLOSS_MASK | I2C_INTSTAT_MSTSTSTPERR_MASK);
  364. /* Invoke callback. */
  365. if (handle->completionCallback)
  366. {
  367. handle->completionCallback(base, handle, result, handle->userData);
  368. }
  369. }
  370. }
  371. static void I2C_MasterTransferCallbackDMA(dma_handle_t *handle, void *userData)
  372. {
  373. i2c_master_dma_private_handle_t *dmaPrivateHandle;
  374. /* Don't do anything if we don't have a valid handle. */
  375. if (!handle)
  376. {
  377. return;
  378. }
  379. dmaPrivateHandle = (i2c_master_dma_private_handle_t *)userData;
  380. I2C_RunDMATransfer(dmaPrivateHandle->base, dmaPrivateHandle->handle);
  381. }
  382. void I2C_MasterTransferCreateHandleDMA(I2C_Type *base,
  383. i2c_master_dma_handle_t *handle,
  384. i2c_master_dma_transfer_callback_t callback,
  385. void *userData,
  386. dma_handle_t *dmaHandle)
  387. {
  388. uint32_t instance;
  389. assert(handle);
  390. assert(dmaHandle);
  391. /* Zero handle. */
  392. memset(handle, 0, sizeof(*handle));
  393. /* Look up instance number */
  394. instance = I2C_GetInstance(base);
  395. /* Set the user callback and userData. */
  396. handle->completionCallback = callback;
  397. handle->userData = userData;
  398. FLEXCOMM_SetIRQHandler(base, (flexcomm_irq_handler_t)I2C_MasterTransferDMAHandleIRQ, handle);
  399. /* Clear internal IRQ enables and enable NVIC IRQ. */
  400. I2C_DisableInterrupts(base,
  401. I2C_INTSTAT_MSTPENDING_MASK | I2C_INTSTAT_MSTARBLOSS_MASK | I2C_INTSTAT_MSTSTSTPERR_MASK);
  402. EnableIRQ(s_i2cIRQ[instance]);
  403. /* Set the handle for DMA. */
  404. handle->dmaHandle = dmaHandle;
  405. s_dmaPrivateHandle[instance].base = base;
  406. s_dmaPrivateHandle[instance].handle = handle;
  407. DMA_SetCallback(dmaHandle, (dma_callback)I2C_MasterTransferCallbackDMA, &s_dmaPrivateHandle[instance]);
  408. }
  409. status_t I2C_MasterTransferDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, i2c_master_transfer_t *xfer)
  410. {
  411. status_t result;
  412. assert(handle);
  413. assert(xfer);
  414. assert(xfer->subaddressSize <= sizeof(xfer->subaddress));
  415. /* Return busy if another transaction is in progress. */
  416. if (handle->state != kIdleState)
  417. {
  418. return kStatus_I2C_Busy;
  419. }
  420. /* Prepare transfer state machine. */
  421. result = I2C_InitTransferStateMachineDMA(base, handle, xfer);
  422. /* Clear error flags. */
  423. I2C_MasterClearStatusFlags(base, I2C_STAT_MSTARBLOSS_MASK | I2C_STAT_MSTSTSTPERR_MASK);
  424. /* Enable I2C internal IRQ sources */
  425. I2C_EnableInterrupts(base,
  426. I2C_INTSTAT_MSTARBLOSS_MASK | I2C_INTSTAT_MSTSTSTPERR_MASK | I2C_INTSTAT_MSTPENDING_MASK);
  427. return result;
  428. }
  429. status_t I2C_MasterTransferGetCountDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, size_t *count)
  430. {
  431. assert(handle);
  432. if (!count)
  433. {
  434. return kStatus_InvalidArgument;
  435. }
  436. /* Catch when there is not an active transfer. */
  437. if (handle->state == kIdleState)
  438. {
  439. *count = 0;
  440. return kStatus_NoTransferInProgress;
  441. }
  442. /* There is no necessity to disable interrupts as we read a single integer value */
  443. *count = handle->transferCount;
  444. return kStatus_Success;
  445. }
  446. void I2C_MasterTransferAbortDMA(I2C_Type *base, i2c_master_dma_handle_t *handle)
  447. {
  448. uint32_t status;
  449. uint32_t master_state;
  450. if (handle->state != kIdleState)
  451. {
  452. DMA_AbortTransfer(handle->dmaHandle);
  453. /* Disable DMA */
  454. base->MSTCTL = 0;
  455. /* Disable internal IRQ enables. */
  456. I2C_DisableInterrupts(base,
  457. I2C_INTSTAT_MSTPENDING_MASK | I2C_INTSTAT_MSTARBLOSS_MASK | I2C_INTSTAT_MSTSTSTPERR_MASK);
  458. /* Wait until module is ready */
  459. do
  460. {
  461. status = I2C_GetStatusFlags(base);
  462. } while ((status & I2C_STAT_MSTPENDING_MASK) == 0);
  463. /* Clear controller state. */
  464. I2C_MasterClearStatusFlags(base, I2C_STAT_MSTARBLOSS_MASK | I2C_STAT_MSTSTSTPERR_MASK);
  465. /* Get the state of the I2C module */
  466. master_state = (status & I2C_STAT_MSTSTATE_MASK) >> I2C_STAT_MSTSTATE_SHIFT;
  467. if (master_state != I2C_STAT_MSTCODE_IDLE)
  468. {
  469. /* Send a stop command to finalize the transfer. */
  470. base->MSTCTL = I2C_MSTCTL_MSTSTOP_MASK;
  471. /* Wait until module is ready */
  472. do
  473. {
  474. status = I2C_GetStatusFlags(base);
  475. } while ((status & I2C_STAT_MSTPENDING_MASK) == 0);
  476. /* Clear controller state. */
  477. I2C_MasterClearStatusFlags(base, I2C_STAT_MSTARBLOSS_MASK | I2C_STAT_MSTSTSTPERR_MASK);
  478. }
  479. /* Reset the state to idle. */
  480. handle->state = kIdleState;
  481. }
  482. }