drv_spi_ch32f10x.c 8.1 KB

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