drv_spi.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * Copyright (c) 2006-2024, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-07-15 yandld The first version for MCXN
  9. */
  10. #include "rtdevice.h"
  11. #include "fsl_common.h"
  12. #include "fsl_lpspi.h"
  13. #include "fsl_lpspi_edma.h"
  14. #define DMA_MAX_TRANSFER_COUNT (32767)
  15. enum
  16. {
  17. #ifdef BSP_USING_SPI3
  18. SPI3_INDEX,
  19. #endif
  20. #ifdef BSP_USING_SPI6
  21. SPI6_INDEX,
  22. #endif
  23. #ifdef BSP_USING_SPI7
  24. SPI7_INDEX,
  25. #endif
  26. };
  27. struct lpc_spi
  28. {
  29. struct rt_spi_bus parent;
  30. LPSPI_Type *LPSPIx;
  31. clock_attach_id_t clock_attach_id;
  32. clock_div_name_t clock_div_name;
  33. clock_name_t clock_name;
  34. DMA_Type *DMAx;
  35. uint8_t tx_dma_chl;
  36. uint8_t rx_dma_chl;
  37. edma_handle_t dma_tx_handle;
  38. edma_handle_t dma_rx_handle;
  39. dma_request_source_t tx_dma_request;
  40. dma_request_source_t rx_dma_request;
  41. lpspi_master_edma_handle_t spi_dma_handle;
  42. rt_sem_t sem;
  43. char *name;
  44. };
  45. static struct lpc_spi lpc_obj[] =
  46. {
  47. #ifdef BSP_USING_SPI3
  48. {
  49. .LPSPIx = LPSPI3,
  50. .clock_attach_id = kFRO_HF_DIV_to_FLEXCOMM3,
  51. .clock_div_name = kCLOCK_DivFlexcom3Clk,
  52. .clock_name = kCLOCK_FroHf,
  53. .tx_dma_request = kDmaRequestMuxLpFlexcomm3Tx,
  54. .rx_dma_request = kDmaRequestMuxLpFlexcomm3Rx,
  55. .DMAx = DMA0,
  56. .tx_dma_chl = 2,
  57. .rx_dma_chl = 3,
  58. .name = "spi3",
  59. },
  60. #endif /* BSP_USING_SPI3 */
  61. #ifdef BSP_USING_SPI6
  62. {
  63. .LPSPIx = LPSPI6,
  64. .clock_attach_id = kFRO_HF_DIV_to_FLEXCOMM6,
  65. .clock_div_name = kCLOCK_DivFlexcom6Clk,
  66. .clock_name = kCLOCK_FroHf,
  67. .tx_dma_request = kDmaRequestMuxLpFlexcomm6Tx,
  68. .rx_dma_request = kDmaRequestMuxLpFlexcomm6Rx,
  69. .DMAx = DMA0,
  70. .tx_dma_chl = 4,
  71. .rx_dma_chl = 5,
  72. .name = "spi6",
  73. #endif /* BSP_USING_SPI6 */
  74. #ifdef BSP_USING_SPI7
  75. {
  76. .LPSPIx = LPSPI7,
  77. .clock_attach_id = kFRO_HF_DIV_to_FLEXCOMM7,
  78. .clock_div_name = kCLOCK_DivFlexcom7Clk,
  79. .clock_name = kCLOCK_FroHf,
  80. .tx_dma_request = kDmaRequestMuxLpFlexcomm7Tx,
  81. .rx_dma_request = kDmaRequestMuxLpFlexcomm7Rx,
  82. .DMAx = DMA0,
  83. .tx_dma_chl = 2,
  84. .rx_dma_chl = 3,
  85. .name = "spi7",
  86. },
  87. #endif /* BSP_USING_SPI7 */
  88. };
  89. struct lpc_sw_spi_cs
  90. {
  91. rt_uint32_t pin;
  92. };
  93. rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin)
  94. {
  95. rt_err_t ret = RT_EOK;
  96. struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
  97. struct lpc_sw_spi_cs *cs_pin = (struct lpc_sw_spi_cs *)rt_malloc(sizeof(struct lpc_sw_spi_cs));
  98. cs_pin->pin = pin;
  99. rt_pin_mode(pin, PIN_MODE_OUTPUT);
  100. rt_pin_write(pin, PIN_HIGH);
  101. ret = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
  102. return ret;
  103. }
  104. static rt_err_t spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
  105. {
  106. rt_err_t ret = RT_EOK;
  107. // struct lpc_spi *spi = RT_NULL;
  108. // spi = (struct lpc_spi *)(device->bus->parent.user_data);
  109. // ret = lpc_spi_init(spi->SPIx, cfg);
  110. return ret;
  111. }
  112. static void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_edma_handle_t *handle, status_t status, void *userData)
  113. {
  114. struct lpc_spi *spi = (struct lpc_spi*)userData;
  115. rt_sem_release(spi->sem);
  116. }
  117. static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
  118. {
  119. int i;
  120. lpspi_transfer_t transfer = {0};
  121. RT_ASSERT(device != RT_NULL);
  122. RT_ASSERT(device->bus != RT_NULL);
  123. RT_ASSERT(device->bus->parent.user_data != RT_NULL);
  124. struct lpc_spi *spi = (struct lpc_spi *)(device->bus->parent.user_data);
  125. // struct lpc_sw_spi_cs *cs = device->parent.user_data;
  126. if(message->cs_take)
  127. {
  128. rt_pin_write(device->cs_pin, PIN_LOW);
  129. }
  130. transfer.dataSize = message->length;
  131. transfer.rxData = (uint8_t *)(message->recv_buf);
  132. transfer.txData = (uint8_t *)(message->send_buf);
  133. // if(message->length < MAX_DMA_TRANSFER_SIZE)
  134. if(0)
  135. {
  136. LPSPI_MasterTransferBlocking(spi->LPSPIx, &transfer);
  137. }
  138. else
  139. {
  140. uint32_t block, remain;
  141. block = message->length / DMA_MAX_TRANSFER_COUNT;
  142. remain = message->length % DMA_MAX_TRANSFER_COUNT;
  143. for(i=0; i<block; i++)
  144. {
  145. transfer.dataSize = DMA_MAX_TRANSFER_COUNT;
  146. if(message->recv_buf) transfer.rxData = (uint8_t *)(message->recv_buf + i*DMA_MAX_TRANSFER_COUNT);
  147. if(message->send_buf) transfer.txData = (uint8_t *)(message->send_buf + i*DMA_MAX_TRANSFER_COUNT);
  148. LPSPI_MasterTransferEDMA(spi->LPSPIx, &spi->spi_dma_handle, &transfer);
  149. rt_sem_take(spi->sem, RT_WAITING_FOREVER);
  150. }
  151. if(remain)
  152. {
  153. transfer.dataSize = remain;
  154. if(message->recv_buf) transfer.rxData = (uint8_t *)(message->recv_buf + i*DMA_MAX_TRANSFER_COUNT);
  155. if(message->send_buf) transfer.txData = (uint8_t *)(message->send_buf + i*DMA_MAX_TRANSFER_COUNT);
  156. LPSPI_MasterTransferEDMA(spi->LPSPIx, &spi->spi_dma_handle, &transfer);
  157. rt_sem_take(spi->sem, RT_WAITING_FOREVER);
  158. }
  159. }
  160. if(message->cs_release)
  161. {
  162. rt_pin_write(device->cs_pin, PIN_HIGH);
  163. }
  164. return message->length;
  165. }
  166. static struct rt_spi_ops lpc_spi_ops =
  167. {
  168. .configure = spi_configure,
  169. .xfer = spixfer
  170. };
  171. int rt_hw_spi_init(void)
  172. {
  173. int i;
  174. for(i=0; i<ARRAY_SIZE(lpc_obj); i++)
  175. {
  176. CLOCK_SetClkDiv(lpc_obj[i].clock_div_name, 1u);
  177. CLOCK_AttachClk(lpc_obj[i].clock_attach_id);
  178. lpc_obj[i].parent.parent.user_data = &lpc_obj[i];
  179. lpc_obj[i].sem = rt_sem_create("sem_spi", 0, RT_IPC_FLAG_FIFO);
  180. lpspi_master_config_t masterConfig;
  181. LPSPI_MasterGetDefaultConfig(&masterConfig);
  182. masterConfig.baudRate = 24*1000*1000;
  183. masterConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.baudRate * 1U;
  184. masterConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.baudRate * 1U;
  185. masterConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.baudRate * 1U;
  186. LPSPI_MasterInit(lpc_obj[i].LPSPIx, &masterConfig, CLOCK_GetFreq(lpc_obj[i].clock_name));
  187. EDMA_CreateHandle(&lpc_obj[i].dma_tx_handle, lpc_obj[i].DMAx, lpc_obj[i].tx_dma_chl);
  188. EDMA_CreateHandle(&lpc_obj[i].dma_rx_handle, lpc_obj[i].DMAx, lpc_obj[i].rx_dma_chl);
  189. EDMA_SetChannelMux(lpc_obj[i].DMAx, lpc_obj[i].tx_dma_chl, lpc_obj[i].tx_dma_request);
  190. EDMA_SetChannelMux(lpc_obj[i].DMAx, lpc_obj[i].rx_dma_chl, lpc_obj[i].rx_dma_request);
  191. LPSPI_MasterTransferCreateHandleEDMA(lpc_obj[i].LPSPIx, &lpc_obj[i].spi_dma_handle, LPSPI_MasterUserCallback, &lpc_obj[i], &lpc_obj[i].dma_rx_handle, &lpc_obj[i].dma_tx_handle);
  192. rt_spi_bus_register(&lpc_obj[i].parent, lpc_obj[i].name, &lpc_spi_ops);
  193. }
  194. return RT_EOK;
  195. }
  196. INIT_DEVICE_EXPORT(rt_hw_spi_init);