drv_spi.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. * Copyright (c) 2006-2025, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-08-23 Mr.Tiger first version
  9. * 2021-11-04 Sherman ADD complete_event
  10. * 2022-12-7 Vandoul ADD sci spi support
  11. */
  12. /**< Note : Turn on any DMA mode and all SPIs will turn on DMA */
  13. #include "drv_spi.h"
  14. #ifdef BSP_USING_SPI
  15. //#define DRV_DEBUG
  16. #define DBG_TAG "drv.spi"
  17. #ifdef DRV_DEBUG
  18. #define DBG_LVL DBG_LOG
  19. #else
  20. #define DBG_LVL DBG_INFO
  21. #endif /* DRV_DEBUG */
  22. #include <rtdbg.h>
  23. #if defined(BSP_USING_SPI0) || defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2)
  24. #define RA_SPI0_EVENT 0x01
  25. #define RA_SPI1_EVENT 0x02
  26. #define RA_SPI2_EVENT 0x03
  27. static struct rt_event complete_event = {0};
  28. #ifdef SOC_SERIES_R7FA8M85
  29. #define R_SPI_Write R_SPI_B_Write
  30. #define R_SPI_Read R_SPI_B_Read
  31. #define R_SPI_WriteRead R_SPI_B_WriteRead
  32. #define R_SPI_Open R_SPI_B_Open
  33. #define spi_extended_cfg_t spi_b_extended_cfg_t
  34. #endif
  35. static struct ra_spi_handle spi_handle[] =
  36. {
  37. #ifdef BSP_USING_SPI0
  38. {.bus_name = "spi0", .spi_ctrl_t = &g_spi0_ctrl, .spi_cfg_t = &g_spi0_cfg,},
  39. #endif
  40. #ifdef BSP_USING_SPI1
  41. {.bus_name = "spi1", .spi_ctrl_t = &g_spi1_ctrl, .spi_cfg_t = &g_spi1_cfg,},
  42. #endif
  43. #ifdef BSP_USING_SPI2
  44. {.bus_name = "spi2", .spi_ctrl_t = &g_spi2_ctrl, .spi_cfg_t = &g_spi2_cfg,},
  45. #endif
  46. };
  47. static struct ra_spi spi_config[sizeof(spi_handle) / sizeof(spi_handle[0])] = {0};
  48. void spi0_callback(spi_callback_args_t *p_args)
  49. {
  50. rt_interrupt_enter();
  51. if (SPI_EVENT_TRANSFER_COMPLETE == p_args->event)
  52. {
  53. rt_event_send(&complete_event, RA_SPI0_EVENT);
  54. }
  55. rt_interrupt_leave();
  56. }
  57. void spi1_callback(spi_callback_args_t *p_args)
  58. {
  59. rt_interrupt_enter();
  60. if (SPI_EVENT_TRANSFER_COMPLETE == p_args->event)
  61. {
  62. rt_event_send(&complete_event, RA_SPI1_EVENT);
  63. }
  64. rt_interrupt_leave();
  65. }
  66. void spi2_callback(spi_callback_args_t *p_args)
  67. {
  68. rt_interrupt_enter();
  69. if (SPI_EVENT_TRANSFER_COMPLETE == p_args->event)
  70. {
  71. rt_event_send(&complete_event, RA_SPI2_EVENT);
  72. }
  73. rt_interrupt_leave();
  74. }
  75. static rt_err_t ra_wait_complete(rt_event_t event, const char bus_name[RT_NAME_MAX])
  76. {
  77. rt_uint32_t recved = 0x00;
  78. if (bus_name[3] == '0')
  79. {
  80. return rt_event_recv(event,
  81. RA_SPI0_EVENT,
  82. RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
  83. (rt_int32_t)rt_tick_from_millisecond(200),
  84. &recved);
  85. }
  86. else if (bus_name[3] == '1')
  87. {
  88. return rt_event_recv(event,
  89. RA_SPI1_EVENT,
  90. RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
  91. (rt_int32_t)rt_tick_from_millisecond(200),
  92. &recved);
  93. }
  94. else if (bus_name[3] == '2')
  95. {
  96. return rt_event_recv(event,
  97. RA_SPI2_EVENT,
  98. RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
  99. (rt_int32_t)rt_tick_from_millisecond(200),
  100. &recved);
  101. }
  102. return -RT_EINVAL;
  103. }
  104. static spi_bit_width_t ra_width_shift(rt_uint8_t data_width)
  105. {
  106. spi_bit_width_t bit_width = SPI_BIT_WIDTH_8_BITS;
  107. if (data_width == 1)
  108. bit_width = SPI_BIT_WIDTH_8_BITS;
  109. else if (data_width == 2)
  110. bit_width = SPI_BIT_WIDTH_16_BITS;
  111. else if (data_width == 4)
  112. bit_width = SPI_BIT_WIDTH_32_BITS;
  113. return bit_width;
  114. }
  115. static rt_err_t ra_write_message(struct rt_spi_device *device, const void *send_buf, const rt_size_t len)
  116. {
  117. RT_ASSERT(device != NULL);
  118. RT_ASSERT(send_buf != NULL);
  119. RT_ASSERT(len > 0);
  120. rt_err_t err = RT_EOK;
  121. struct ra_spi *spi_dev = rt_container_of(device->bus, struct ra_spi, bus);
  122. spi_bit_width_t bit_width = ra_width_shift(spi_dev->rt_spi_cfg_t->data_width);
  123. /**< send msessage */
  124. err = R_SPI_Write((spi_ctrl_t *)spi_dev->ra_spi_handle_t->spi_ctrl_t, send_buf, len, bit_width);
  125. if (RT_EOK != err)
  126. {
  127. LOG_E("%s write failed.", spi_dev->ra_spi_handle_t->bus_name);
  128. return -RT_ERROR;
  129. }
  130. /* Wait for SPI_EVENT_TRANSFER_COMPLETE callback event. */
  131. ra_wait_complete(&complete_event, spi_dev->ra_spi_handle_t->bus_name);
  132. return len;
  133. }
  134. static rt_err_t ra_read_message(struct rt_spi_device *device, void *recv_buf, const rt_size_t len)
  135. {
  136. RT_ASSERT(device != NULL);
  137. RT_ASSERT(recv_buf != NULL);
  138. RT_ASSERT(len > 0);
  139. rt_err_t err = RT_EOK;
  140. struct ra_spi *spi_dev = rt_container_of(device->bus, struct ra_spi, bus);
  141. spi_bit_width_t bit_width = ra_width_shift(spi_dev->rt_spi_cfg_t->data_width);
  142. /**< receive message */
  143. err = R_SPI_Read((spi_ctrl_t *)spi_dev->ra_spi_handle_t->spi_ctrl_t, recv_buf, len, bit_width);
  144. if (RT_EOK != err)
  145. {
  146. LOG_E("\n%s write failed.\n", spi_dev->ra_spi_handle_t->bus_name);
  147. return -RT_ERROR;
  148. }
  149. /* Wait for SPI_EVENT_TRANSFER_COMPLETE callback event. */
  150. ra_wait_complete(&complete_event, spi_dev->ra_spi_handle_t->bus_name);
  151. return len;
  152. }
  153. static rt_err_t ra_write_read_message(struct rt_spi_device *device, struct rt_spi_message *message)
  154. {
  155. RT_ASSERT(device != NULL);
  156. RT_ASSERT(message != NULL);
  157. RT_ASSERT(message->length > 0);
  158. rt_err_t err = RT_EOK;
  159. struct ra_spi *spi_dev = rt_container_of(device->bus, struct ra_spi, bus);
  160. spi_bit_width_t bit_width = ra_width_shift(spi_dev->rt_spi_cfg_t->data_width);
  161. /**< write and receive message */
  162. err = R_SPI_WriteRead((spi_ctrl_t *)spi_dev->ra_spi_handle_t->spi_ctrl_t, message->send_buf, message->recv_buf, message->length, bit_width);
  163. if (RT_EOK != err)
  164. {
  165. LOG_E("%s write and read failed.", spi_dev->ra_spi_handle_t->bus_name);
  166. return -RT_ERROR;
  167. }
  168. #if defined(SOC_SERIES_R9A07G0)
  169. R_BSP_CacheCleanInvalidateAll();
  170. #endif
  171. /* Wait for SPI_EVENT_TRANSFER_COMPLETE callback event. */
  172. ra_wait_complete(&complete_event, spi_dev->ra_spi_handle_t->bus_name);
  173. return message->length;
  174. }
  175. /**< init spi TODO : MSB does not support modification */
  176. static rt_err_t ra_hw_spi_configure(struct rt_spi_device *device,
  177. struct rt_spi_configuration *configuration)
  178. {
  179. RT_ASSERT(device != NULL);
  180. RT_ASSERT(configuration != NULL);
  181. rt_err_t err = RT_EOK;
  182. struct ra_spi *spi_dev = rt_container_of(device->bus, struct ra_spi, bus);
  183. /**< data_width : 1 -> 8 bits , 2 -> 16 bits, 4 -> 32 bits, default 32 bits*/
  184. rt_uint8_t data_width = configuration->data_width / 8;
  185. RT_ASSERT(data_width == 1 || data_width == 2 || data_width == 4);
  186. configuration->data_width = configuration->data_width / 8;
  187. spi_dev->rt_spi_cfg_t = configuration;
  188. spi_extended_cfg_t spi_cfg = *(spi_extended_cfg_t *)spi_dev->ra_spi_handle_t->spi_cfg_t->p_extend;
  189. /**< Configure Select Line */
  190. rt_pin_write(device->cs_pin, PIN_HIGH);
  191. /**< config bitrate */
  192. #ifdef SOC_SERIES_R7FA8M85
  193. R_SPI_B_CalculateBitrate(spi_dev->rt_spi_cfg_t->max_hz, SPI_B_CLOCK_SOURCE_PCLK, &spi_cfg.spck_div);
  194. #elif defined(SOC_SERIES_R9A07G0)
  195. R_SPI_CalculateBitrate(spi_dev->rt_spi_cfg_t->max_hz, SPI_CLOCK_SOURCE_PCLKM, &spi_cfg.spck_div);
  196. #else
  197. R_SPI_CalculateBitrate(spi_dev->rt_spi_cfg_t->max_hz, &spi_cfg.spck_div);
  198. #endif
  199. /**< init */
  200. err = R_SPI_Open((spi_ctrl_t *)spi_dev->ra_spi_handle_t->spi_ctrl_t, (spi_cfg_t const * const)spi_dev->ra_spi_handle_t->spi_cfg_t);
  201. /* handle error */
  202. if (RT_EOK != err)
  203. {
  204. LOG_E("%s init failed.", spi_dev->ra_spi_handle_t->bus_name);
  205. return -RT_ERROR;
  206. }
  207. return RT_EOK;
  208. }
  209. static rt_ssize_t ra_spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
  210. {
  211. RT_ASSERT(device != RT_NULL);
  212. RT_ASSERT(device->bus != RT_NULL);
  213. RT_ASSERT(message != RT_NULL);
  214. rt_err_t err = RT_EOK;
  215. if (message->cs_take && !(device->config.mode & RT_SPI_NO_CS) && (device->cs_pin != PIN_NONE))
  216. {
  217. if (device->config.mode & RT_SPI_CS_HIGH)
  218. rt_pin_write(device->cs_pin, PIN_HIGH);
  219. else
  220. rt_pin_write(device->cs_pin, PIN_LOW);
  221. }
  222. if (message->length > 0)
  223. {
  224. if (message->send_buf == RT_NULL && message->recv_buf != RT_NULL)
  225. {
  226. /**< receive message */
  227. err = ra_read_message(device, (void *)message->recv_buf, (const rt_size_t)message->length);
  228. }
  229. else if (message->send_buf != RT_NULL && message->recv_buf == RT_NULL)
  230. {
  231. /**< send message */
  232. err = ra_write_message(device, (const void *)message->send_buf, (const rt_size_t)message->length);
  233. }
  234. else if (message->send_buf != RT_NULL && message->recv_buf != RT_NULL)
  235. {
  236. /**< send and receive message */
  237. err = ra_write_read_message(device, message);
  238. }
  239. }
  240. if (message->cs_release && !(device->config.mode & RT_SPI_NO_CS) && (device->cs_pin != PIN_NONE))
  241. {
  242. if (device->config.mode & RT_SPI_CS_HIGH)
  243. rt_pin_write(device->cs_pin, PIN_LOW);
  244. else
  245. rt_pin_write(device->cs_pin, PIN_HIGH);
  246. }
  247. return err;
  248. }
  249. static const struct rt_spi_ops ra_spi_ops =
  250. {
  251. .configure = ra_hw_spi_configure,
  252. .xfer = ra_spixfer,
  253. };
  254. int ra_hw_spi_init(void)
  255. {
  256. for (rt_uint8_t spi_index = 0; spi_index < sizeof(spi_handle) / sizeof(spi_handle[0]); spi_index++)
  257. {
  258. spi_config[spi_index].ra_spi_handle_t = &spi_handle[spi_index];
  259. /**< register spi bus */
  260. rt_err_t err = rt_spi_bus_register(&spi_config[spi_index].bus, spi_handle[spi_index].bus_name, &ra_spi_ops);
  261. if (RT_EOK != err)
  262. {
  263. LOG_E("%s bus register failed.", spi_config[spi_index].ra_spi_handle_t->bus_name);
  264. return -RT_ERROR;
  265. }
  266. }
  267. if (RT_EOK != rt_event_init(&complete_event, "ra_spi", RT_IPC_FLAG_PRIO))
  268. {
  269. LOG_E("SPI transfer event init fail!");
  270. return -RT_ERROR;
  271. }
  272. return RT_EOK;
  273. }
  274. INIT_DEVICE_EXPORT(ra_hw_spi_init);
  275. #endif
  276. /**
  277. * Attach the spi device to SPI bus, this function must be used after initialization.
  278. */
  279. rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_base_t cs_pin)
  280. {
  281. RT_ASSERT(bus_name != RT_NULL);
  282. RT_ASSERT(device_name != RT_NULL);
  283. rt_err_t result;
  284. struct rt_spi_device *spi_device;
  285. /* attach the device to spi bus*/
  286. spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
  287. RT_ASSERT(spi_device != RT_NULL);
  288. result = rt_spi_bus_attach_device_cspin(spi_device, device_name, bus_name, cs_pin, RT_NULL);
  289. if (result != RT_EOK)
  290. {
  291. LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result);
  292. }
  293. RT_ASSERT(result == RT_EOK);
  294. LOG_D("%s attach to %s done", device_name, bus_name);
  295. return result;
  296. }
  297. #endif /* BSP_USING_SPI */