drv_spi_ch32f20x.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-01-21 charlown first version
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include <drivers/spi.h>
  13. #include "board.h"
  14. #include "drv_spi.h"
  15. #include "ch32f20x_spi.h"
  16. #include "ch32f20x_rcc.h"
  17. #ifdef BSP_USING_SPI
  18. #define LOG_TAG "drv.spi"
  19. #include "drv_log.h"
  20. #ifndef ITEM_NUM
  21. #define ITEM_NUM(items) sizeof(items) / sizeof(items[0])
  22. #endif
  23. struct spi_bus_device
  24. {
  25. struct rt_spi_bus parent;
  26. char *name;
  27. SPI_TypeDef *periph;
  28. rt_base_t cs_pin;
  29. struct rt_spi_device spi_device;
  30. };
  31. static struct spi_bus_device spi_bus_device_list[] = {
  32. #ifdef BSP_USING_SPI1
  33. {.periph = SPI1,
  34. .name = "spi1"},
  35. #endif
  36. #ifdef BSP_USING_SPI2
  37. {.periph = SPI2,
  38. .name = "spi2"},
  39. #endif
  40. #ifdef BSP_USING_SPI3
  41. {.periph = SPI3,
  42. .name = "spi3"},
  43. #endif
  44. };
  45. /**
  46. * Attach the spi device to SPI bus, this function must be used after initialization.
  47. */
  48. rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin)
  49. {
  50. rt_err_t result;
  51. struct rt_spi_bus *spi_bus;
  52. struct spi_bus_device *spi_bus_dev;
  53. RT_ASSERT(bus_name != RT_NULL);
  54. RT_ASSERT(device_name != RT_NULL);
  55. spi_bus = (struct rt_spi_bus *)rt_device_find(bus_name);
  56. RT_ASSERT(spi_bus != RT_NULL);
  57. spi_bus_dev = (struct spi_bus_device *)spi_bus;
  58. spi_bus_dev->cs_pin = pin;
  59. //often active low, output from master
  60. rt_pin_mode(spi_bus_dev->cs_pin, PIN_MODE_OUTPUT);
  61. rt_pin_write(spi_bus_dev->cs_pin, PIN_HIGH);
  62. result = rt_spi_bus_attach_device(&spi_bus_dev->spi_device, device_name, bus_name, RT_NULL);
  63. if (result != RT_EOK)
  64. {
  65. LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result);
  66. }
  67. LOG_D("%s attach to %s done", device_name, bus_name);
  68. return result;
  69. }
  70. static rt_err_t ch32f2_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
  71. {
  72. struct rt_spi_bus *spi_bus;
  73. struct spi_bus_device *spi_bus_dev;
  74. rt_uint32_t spi_clock;
  75. SPI_InitTypeDef SPI_InitStruct;
  76. RT_ASSERT(device != RT_NULL);
  77. RT_ASSERT(configuration != RT_NULL);
  78. //device is not RT_NULL, so spi_bus not need check
  79. spi_bus = (struct rt_spi_bus *)device->bus;
  80. spi_bus_dev = (struct spi_bus_device *)spi_bus;
  81. ch32f2_spi_clock_and_io_init(spi_bus_dev->periph);
  82. spi_clock = ch32f2_spi_clock_get(spi_bus_dev->periph);
  83. if (configuration->data_width <= 8)
  84. {
  85. SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
  86. }
  87. else if (configuration->data_width <= 16)
  88. {
  89. SPI_InitStruct.SPI_DataSize = SPI_DataSize_16b;
  90. }
  91. else
  92. {
  93. return RT_EIO;
  94. }
  95. if (configuration->max_hz >= spi_clock / 2)
  96. {
  97. SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
  98. }
  99. else if (configuration->max_hz >= spi_clock / 4)
  100. {
  101. SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
  102. }
  103. else if (configuration->max_hz >= spi_clock / 8)
  104. {
  105. SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;
  106. }
  107. else if (configuration->max_hz >= spi_clock / 16)
  108. {
  109. SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
  110. }
  111. else if (configuration->max_hz >= spi_clock / 32)
  112. {
  113. SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;
  114. }
  115. else if (configuration->max_hz >= spi_clock / 64)
  116. {
  117. SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
  118. }
  119. else if (configuration->max_hz >= spi_clock / 128)
  120. {
  121. SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
  122. }
  123. else
  124. {
  125. /* min prescaler 256 */
  126. SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
  127. }
  128. switch (configuration->mode & RT_SPI_MODE_3)
  129. {
  130. case RT_SPI_MODE_0:
  131. SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
  132. SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
  133. break;
  134. case RT_SPI_MODE_1:
  135. SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
  136. SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;
  137. break;
  138. case RT_SPI_MODE_2:
  139. SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;
  140. SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
  141. break;
  142. case RT_SPI_MODE_3:
  143. SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
  144. SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
  145. break;
  146. }
  147. /* MSB or LSB */
  148. if (configuration->mode & RT_SPI_MSB)
  149. {
  150. SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;
  151. }
  152. else
  153. {
  154. SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_LSB;
  155. }
  156. SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  157. SPI_InitStruct.SPI_Mode = SPI_Mode_Master;
  158. SPI_InitStruct.SPI_NSS = SPI_NSS_Soft;
  159. SPI_Init(spi_bus_dev->periph, &SPI_InitStruct);
  160. /* Enable SPI_MASTER */
  161. SPI_Cmd(spi_bus_dev->periph, ENABLE);
  162. return RT_EOK;
  163. };
  164. static rt_uint32_t ch32f2_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  165. {
  166. struct rt_spi_bus *spi_bus;
  167. struct spi_bus_device *spi_bus_dev;
  168. struct rt_spi_configuration *config;
  169. RT_ASSERT(device != NULL);
  170. RT_ASSERT(message != NULL);
  171. //device is not RT_NULL, so spi_bus not need check
  172. spi_bus = (struct rt_spi_bus *)device->bus;
  173. spi_bus_dev = (struct spi_bus_device *)spi_bus;
  174. config = &device->config;
  175. /* take CS */
  176. if (message->cs_take)
  177. {
  178. rt_pin_write(spi_bus_dev->cs_pin, PIN_LOW);
  179. LOG_D("spi take cs\n");
  180. }
  181. if (config->data_width <= 8)
  182. {
  183. const rt_uint8_t *send_ptr = message->send_buf;
  184. rt_uint8_t *recv_ptr = message->recv_buf;
  185. rt_uint32_t size = message->length;
  186. rt_uint8_t data;
  187. LOG_D("spi poll transfer start: %d\n", size);
  188. while (size--)
  189. {
  190. data = 0xFF;
  191. if (send_ptr != RT_NULL)
  192. {
  193. data = *send_ptr++;
  194. }
  195. //Wait until the transmit buffer is empty
  196. while (RESET == SPI_I2S_GetFlagStatus(spi_bus_dev->periph, SPI_I2S_FLAG_TXE))
  197. ;
  198. // Send the byte
  199. SPI_I2S_SendData(spi_bus_dev->periph, data);
  200. //Wait until a data is received
  201. while (RESET == SPI_I2S_GetFlagStatus(spi_bus_dev->periph, SPI_I2S_FLAG_RXNE))
  202. ;
  203. // Get the received data
  204. data = SPI_I2S_ReceiveData(spi_bus_dev->periph);
  205. if (recv_ptr != RT_NULL)
  206. {
  207. *recv_ptr++ = data;
  208. }
  209. }
  210. LOG_D("spi poll transfer finsh\n");
  211. }
  212. else if (config->data_width <= 16)
  213. {
  214. const rt_uint16_t *send_ptr = message->send_buf;
  215. rt_uint16_t *recv_ptr = message->recv_buf;
  216. rt_uint32_t size = message->length;
  217. rt_uint16_t data;
  218. while (size--)
  219. {
  220. data = 0xFF;
  221. if (send_ptr != RT_NULL)
  222. {
  223. data = *send_ptr++;
  224. }
  225. //Wait until the transmit buffer is empty
  226. while (RESET == SPI_I2S_GetFlagStatus(spi_bus_dev->periph, SPI_I2S_FLAG_TXE))
  227. ;
  228. // Send the byte
  229. SPI_I2S_SendData(spi_bus_dev->periph, data);
  230. //Wait until a data is received
  231. while (RESET == SPI_I2S_GetFlagStatus(spi_bus_dev->periph, SPI_I2S_FLAG_RXNE))
  232. ;
  233. // Get the received data
  234. data = SPI_I2S_ReceiveData(spi_bus_dev->periph);
  235. if (recv_ptr != RT_NULL)
  236. {
  237. *recv_ptr++ = data;
  238. }
  239. }
  240. }
  241. /* release CS */
  242. if (message->cs_release)
  243. {
  244. rt_pin_write(spi_bus_dev->cs_pin, PIN_HIGH);
  245. LOG_D("spi release cs\n");
  246. }
  247. return message->length;
  248. };
  249. static struct rt_spi_ops spi_ops = {
  250. .configure = ch32f2_spi_configure,
  251. .xfer = ch32f2_spi_xfer};
  252. int rt_hw_spi_init(void)
  253. {
  254. int index;
  255. for (index = 0; index < ITEM_NUM(spi_bus_device_list); index++)
  256. {
  257. rt_spi_bus_register(&spi_bus_device_list[index].parent, spi_bus_device_list[index].name, &spi_ops);
  258. }
  259. return RT_EOK;
  260. }
  261. INIT_BOARD_EXPORT(rt_hw_spi_init);
  262. #endif /* BSP_USING_SPI */