drv_spi.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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. * 2024-08-1 hywing The first version for MCXA
  9. */
  10. #include "rtdevice.h"
  11. #include "drv_spi.h"
  12. #include "fsl_lpspi.h"
  13. #ifdef RT_USING_SPI
  14. #define DBG_TAG "drv.spi"
  15. #define DBG_LVL DBG_INFO
  16. #include <rtdbg.h>
  17. enum
  18. {
  19. #ifdef BSP_USING_SPI0
  20. SPI0_INDEX,
  21. #endif
  22. #ifdef BSP_USING_SPI1
  23. SPI1_INDEX,
  24. #endif
  25. };
  26. struct mcx_spi_bus
  27. {
  28. struct rt_spi_bus spi_bus;
  29. LPSPI_Type *spi_base;
  30. clock_ip_name_t clock_ip_name;
  31. clock_ip_src_t clock_ip_src;
  32. rt_sem_t sem;
  33. char *name;
  34. };
  35. static struct mcx_spi_bus mcx_spi_buses[] =
  36. {
  37. #ifdef BSP_USING_SPI0
  38. {
  39. .spi_base = LPSPI0,
  40. .clock_ip_name = kCLOCK_Lpspi0,
  41. .clock_ip_src = kCLOCK_IpSrcSysOscAsync,
  42. .name = "spi0",
  43. },
  44. #endif
  45. #ifdef BSP_USING_SPI1
  46. {
  47. .spi_base = LPSPI1,
  48. .clock_ip_name = kCLOCK_Lpspi1,
  49. .clock_ip_src = kCLOCK_IpSrcSysOscAsync,
  50. .name = "spi1",
  51. },
  52. #endif
  53. #ifdef BSP_USING_SPI2
  54. {
  55. .spi_base = LPSPI2,
  56. .clock_ip_name = kCLOCK_Lpspi2,
  57. .clock_ip_src = kCLOCK_IpSrcSysOscAsync,
  58. .name = "spi2",
  59. },
  60. #endif
  61. };
  62. rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin)
  63. {
  64. struct rt_spi_device *spi_device = rt_malloc(sizeof(struct rt_spi_device));
  65. if (!spi_device)
  66. {
  67. return -RT_ENOMEM;
  68. }
  69. return rt_spi_bus_attach_device_cspin(spi_device, device_name, bus_name, pin, NULL);
  70. }
  71. static rt_err_t spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
  72. {
  73. return RT_EOK;
  74. }
  75. static rt_ssize_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
  76. {
  77. lpspi_transfer_t transfer = {0};
  78. status_t status;
  79. RT_ASSERT(device != RT_NULL);
  80. RT_ASSERT(device->bus != RT_NULL);
  81. RT_ASSERT(device->bus->parent.user_data != RT_NULL);
  82. struct mcx_spi_bus *spi = device->bus->parent.user_data;
  83. if (message->cs_take)
  84. {
  85. rt_pin_write(device->cs_pin, PIN_LOW);
  86. }
  87. transfer.dataSize = message->length;
  88. transfer.rxData = (uint8_t *)(message->recv_buf);
  89. transfer.txData = (uint8_t *)(message->send_buf);
  90. transfer.configFlags = kLPSPI_MasterPcs0;
  91. // Use blocking transfer instead of DMA
  92. status = LPSPI_MasterTransferBlocking(spi->spi_base, &transfer);
  93. if (message->cs_release)
  94. {
  95. rt_pin_write(device->cs_pin, PIN_HIGH);
  96. }
  97. if (status != kStatus_Success)
  98. {
  99. return 0; // Transfer failed
  100. }
  101. return message->length;
  102. }
  103. static struct rt_spi_ops lpc_spi_ops =
  104. {
  105. .configure = spi_configure,
  106. .xfer = spixfer};
  107. int rt_hw_spi_init(void)
  108. {
  109. int i;
  110. for (i = 0; i < ARRAY_SIZE(mcx_spi_buses); i++)
  111. {
  112. struct mcx_spi_bus *priv = &mcx_spi_buses[i];
  113. CLOCK_SetIpSrc(priv->clock_ip_name, priv->clock_ip_src);
  114. priv->spi_bus.parent.user_data = &mcx_spi_buses[i];
  115. priv->sem = rt_sem_create("sem_spi", 0, RT_IPC_FLAG_FIFO);
  116. lpspi_master_config_t masterConfig;
  117. LPSPI_MasterGetDefaultConfig(&masterConfig);
  118. masterConfig.baudRate = 10 * 1000 * 1000;
  119. masterConfig.pcsToSckDelayInNanoSec = 1000000000U / masterConfig.baudRate * 1U;
  120. masterConfig.lastSckToPcsDelayInNanoSec = 1000000000U / masterConfig.baudRate * 1U;
  121. masterConfig.betweenTransferDelayInNanoSec = 1000000000U / masterConfig.baudRate * 1U;
  122. LPSPI_MasterInit(priv->spi_base, &masterConfig, CLOCK_GetIpFreq(priv->clock_ip_name));
  123. rt_spi_bus_register(&priv->spi_bus, priv->name, &lpc_spi_ops);
  124. }
  125. return RT_EOK;
  126. }
  127. INIT_DEVICE_EXPORT(rt_hw_spi_init);
  128. #endif /* RT_USING_SPI */