You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

240 lines
8.7 KiB

  1. /*
  2. * Copyright (c) 2015, Freescale Semiconductor, Inc.
  3. * Copyright 2016-2019 NXP
  4. * All rights reserved.
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #include "fsl_flexcan_edma.h"
  9. /*******************************************************************************
  10. * Definitions
  11. ******************************************************************************/
  12. /* Component ID definition, used by tools. */
  13. #ifndef FSL_COMPONENT_ID
  14. #define FSL_COMPONENT_ID "platform.drivers.flexcan_edma"
  15. #endif
  16. /*<! Structure definition for flexcan_edma_private_handle_t. The structure is private. */
  17. typedef struct _flexcan_edma_private_handle
  18. {
  19. CAN_Type *base;
  20. flexcan_edma_handle_t *handle;
  21. } flexcan_edma_private_handle_t;
  22. /* FlexCAN EDMA transfer handle. */
  23. enum _flexcan_edma_tansfer_state
  24. {
  25. KFLEXCAN_RxFifoIdle = 0U, /* Rx Fifo idle. */
  26. KFLEXCAN_RxFifoBusy = 1U, /* Rx Fifo busy. */
  27. };
  28. /*******************************************************************************
  29. * Variables
  30. ******************************************************************************/
  31. /*<! Private handle only used for internally. */
  32. static flexcan_edma_private_handle_t s_flexcanEdmaPrivateHandle[FSL_FEATURE_SOC_FLEXCAN_COUNT];
  33. /*******************************************************************************
  34. * Prototypes
  35. ******************************************************************************/
  36. /*!
  37. * @brief FlexCAN EDMA receive finished callback function.
  38. *
  39. * This function is called when FlexCAN Rx FIFO EDMA receive finished.
  40. * It disables the FlexCAN Rx FIFO EDMA request and sends
  41. * @ref kStatus_FLEXCAN_RxFifoIdle to FlexCAN EDMA callback.
  42. *
  43. * @param handle The EDMA handle.
  44. * @param param Callback function parameter.
  45. */
  46. static void FLEXCAN_ReceiveFifoEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds);
  47. /*******************************************************************************
  48. * Code
  49. ******************************************************************************/
  50. static void FLEXCAN_ReceiveFifoEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds)
  51. {
  52. handle = handle;
  53. tcds = tcds;
  54. flexcan_edma_private_handle_t *flexcanPrivateHandle = (flexcan_edma_private_handle_t *)param;
  55. if (transferDone)
  56. {
  57. /* Disable transfer. */
  58. FLEXCAN_TransferAbortReceiveFifoEDMA(flexcanPrivateHandle->base, flexcanPrivateHandle->handle);
  59. if (NULL != flexcanPrivateHandle->handle->callback)
  60. {
  61. flexcanPrivateHandle->handle->callback(flexcanPrivateHandle->base, flexcanPrivateHandle->handle,
  62. kStatus_FLEXCAN_RxFifoIdle, flexcanPrivateHandle->handle->userData);
  63. }
  64. }
  65. }
  66. /*!
  67. * brief Initializes the FlexCAN handle, which is used in transactional functions.
  68. *
  69. * param base FlexCAN peripheral base address.
  70. * param handle Pointer to flexcan_edma_handle_t structure.
  71. * param callback The callback function.
  72. * param userData The parameter of the callback function.
  73. * param rxFifoEdmaHandle User-requested DMA handle for Rx FIFO DMA transfer.
  74. */
  75. void FLEXCAN_TransferCreateHandleEDMA(CAN_Type *base,
  76. flexcan_edma_handle_t *handle,
  77. flexcan_edma_transfer_callback_t callback,
  78. void *userData,
  79. edma_handle_t *rxFifoEdmaHandle)
  80. {
  81. assert(NULL != handle);
  82. uint32_t instance = FLEXCAN_GetInstance(base);
  83. s_flexcanEdmaPrivateHandle[instance].base = base;
  84. s_flexcanEdmaPrivateHandle[instance].handle = handle;
  85. (void)memset(handle, 0, sizeof(flexcan_edma_handle_t));
  86. handle->rxFifoState = (uint8_t)KFLEXCAN_RxFifoIdle;
  87. handle->rxFifoEdmaHandle = rxFifoEdmaHandle;
  88. /* Register Callback. */
  89. handle->callback = callback;
  90. handle->userData = userData;
  91. /* Configure Rx FIFO DMA. */
  92. EDMA_SetCallback(handle->rxFifoEdmaHandle, FLEXCAN_ReceiveFifoEDMACallback, &s_flexcanEdmaPrivateHandle[instance]);
  93. }
  94. /*!
  95. * brief Prepares the eDMA transfer configuration for FLEXCAN Legacy RX FIFO.
  96. *
  97. * This function prepares the eDMA transfer configuration structure according to FLEXCAN Legacy RX FIFO.
  98. *
  99. * param base FlexCAN peripheral base address.
  100. * param pFifoXfer FlexCAN Rx FIFO EDMA transfer structure, see #flexcan_fifo_transfer_t.
  101. * param pEdmaConfig The user configuration structure of type edma_transfer_t.
  102. *
  103. */
  104. void FLEXCAN_PrepareTransfConfiguration(CAN_Type *base,
  105. flexcan_fifo_transfer_t *pFifoXfer,
  106. edma_transfer_config_t *pEdmaConfig)
  107. {
  108. assert(NULL != pFifoXfer);
  109. assert(NULL != pFifoXfer->frame);
  110. assert(NULL != pEdmaConfig);
  111. flexcan_frame_t *fifoAddr = (flexcan_frame_t *)FLEXCAN_GetRxFifoHeadAddr(base);
  112. #if (defined(FSL_FEATURE_EDMA_SUPPORT_16_BYTES_TRANSFER) && FSL_FEATURE_EDMA_SUPPORT_16_BYTES_TRANSFER)
  113. EDMA_PrepareTransfer(pEdmaConfig, (void *)fifoAddr, sizeof(flexcan_frame_t), (void *)pFifoXfer->frame,
  114. sizeof(uint32_t), sizeof(flexcan_frame_t), sizeof(flexcan_frame_t), kEDMA_PeripheralToMemory);
  115. #else
  116. /* The Data Size of FLEXCAN Legacy RX FIFO output port is 16 Bytes, but lots of chips not support 16Bytes width DMA
  117. * transfer. These chips always support 4Byte width memory transfer, so we need prepare Memory to Memory mode by 4
  118. * Bytes width mode.
  119. */
  120. EDMA_PrepareTransfer(pEdmaConfig, (void *)fifoAddr, 4U, (void *)pFifoXfer->frame, sizeof(uint32_t),
  121. sizeof(flexcan_frame_t), sizeof(flexcan_frame_t), kEDMA_MemoryToMemory);
  122. #endif
  123. }
  124. /*!
  125. * brief Start Transfer Data from the FLEXCAN Legacy Rx FIFO using eDMA.
  126. *
  127. * This function to Update edma transfer confiugration and Start eDMA transfer
  128. *
  129. * param base FlexCAN peripheral base address.
  130. * param handle Pointer to flexcan_edma_handle_t structure.
  131. * param pEdmaConfig The user configuration structure of type edma_transfer_t.
  132. * retval kStatus_Success if succeed, others failed.
  133. * retval kStatus_FLEXCAN_RxFifoBusy Previous transfer ongoing.
  134. */
  135. status_t FLEXCAN_StartTransferDatafromRxFIFO(CAN_Type *base,
  136. flexcan_edma_handle_t *handle,
  137. edma_transfer_config_t *pEdmaConfig)
  138. {
  139. assert(NULL != handle->rxFifoEdmaHandle);
  140. assert(NULL != pEdmaConfig);
  141. status_t status;
  142. /* If previous Rx FIFO receive not finished. */
  143. if ((uint8_t)KFLEXCAN_RxFifoBusy == handle->rxFifoState)
  144. {
  145. status = kStatus_FLEXCAN_RxFifoBusy;
  146. }
  147. else
  148. {
  149. handle->rxFifoState = (uint8_t)KFLEXCAN_RxFifoBusy;
  150. /* Enable FlexCAN Rx FIFO EDMA. */
  151. FLEXCAN_EnableRxFifoDMA(base, true);
  152. /* Submit configuration. */
  153. (void)EDMA_SubmitTransfer(handle->rxFifoEdmaHandle, (const edma_transfer_config_t *)pEdmaConfig);
  154. /* Start transfer. */
  155. EDMA_StartTransfer(handle->rxFifoEdmaHandle);
  156. status = kStatus_Success;
  157. }
  158. return status;
  159. }
  160. /*!
  161. * brief Receives the CAN Message from the Rx FIFO using eDMA.
  162. *
  163. * This function receives the CAN Message using eDMA. This is a non-blocking function, which returns
  164. * right away. After the CAN Message is received, the receive callback function is called.
  165. *
  166. * param base FlexCAN peripheral base address.
  167. * param handle Pointer to flexcan_edma_handle_t structure.
  168. * param pFifoXfer FlexCAN Rx FIFO EDMA transfer structure, see #flexcan_fifo_transfer_t.
  169. * retval kStatus_Success if succeed, others failed.
  170. * retval kStatus_FLEXCAN_RxFifoBusy Previous transfer ongoing.
  171. */
  172. status_t FLEXCAN_TransferReceiveFifoEDMA(CAN_Type *base,
  173. flexcan_edma_handle_t *handle,
  174. flexcan_fifo_transfer_t *pFifoXfer)
  175. {
  176. assert(NULL != handle->rxFifoEdmaHandle);
  177. edma_transfer_config_t dmaXferConfig;
  178. status_t status;
  179. /* Prepare transfer. */
  180. FLEXCAN_PrepareTransfConfiguration(base, pFifoXfer, &dmaXferConfig);
  181. /* Submit configuration and start edma transfer. */
  182. status = FLEXCAN_StartTransferDatafromRxFIFO(base, handle, &dmaXferConfig);
  183. return status;
  184. }
  185. /*!
  186. * brief Aborts the receive process which used eDMA.
  187. *
  188. * This function aborts the receive process which used eDMA.
  189. *
  190. * param base FlexCAN peripheral base address.
  191. * param handle Pointer to flexcan_edma_handle_t structure.
  192. */
  193. void FLEXCAN_TransferAbortReceiveFifoEDMA(CAN_Type *base, flexcan_edma_handle_t *handle)
  194. {
  195. assert(NULL != handle->rxFifoEdmaHandle);
  196. /* Stop transfer. */
  197. EDMA_AbortTransfer(handle->rxFifoEdmaHandle);
  198. handle->rxFifoState = (uint8_t)KFLEXCAN_RxFifoIdle;
  199. /* Disable FlexCAN Rx FIFO EDMA. */
  200. FLEXCAN_EnableRxFifoDMA(base, false);
  201. }