drv_spi.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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-04-08 QT-one first version
  9. */
  10. #include <rtdbg.h>
  11. #include "drv_spi.h"
  12. #ifdef RT_USING_SPI
  13. #if !defined(BSP_USING_SPI0) && !defined(BSP_USING_SPI1)
  14. #error "Please define at least one BSP_USING_SPIx"
  15. #endif
  16. struct ht32_spi_config
  17. {
  18. HT_SPI_TypeDef *spi_x;
  19. const char *spi_name;
  20. IRQn_Type irq;
  21. };
  22. struct ht32_spi
  23. {
  24. struct ht32_spi_config *config;
  25. struct rt_spi_bus spi_bus;
  26. };
  27. struct ht32_spi_cs
  28. {
  29. HT_GPIO_TypeDef *gpio_x;
  30. uint32_t gpio_pin;
  31. };
  32. enum
  33. {
  34. #ifdef BSP_USING_SPI0
  35. SPI0_INDEX,
  36. #endif
  37. #ifdef BSP_USING_SPI1
  38. SPI1_INDEX,
  39. #endif
  40. };
  41. static struct ht32_spi_config spi_config[] =
  42. {
  43. #ifdef BSP_USING_SPI0
  44. {
  45. .spi_x = HT_SPI0,
  46. .spi_name = BSP_USING_SPI0_NAME,
  47. .irq = SPI0_IRQn
  48. },
  49. #endif
  50. #ifdef BSP_USING_SPI1
  51. {
  52. .spi_x = HT_SPI1,
  53. .spi_name = BSP_USING_SPI1_NAME,
  54. .irq = SPI1_IRQn
  55. },
  56. #endif
  57. };
  58. static struct ht32_spi spis[sizeof(spi_config) / sizeof(spi_config[0])] = {0};
  59. /* attach the spi device to spi bus, this function must be used after initialization */
  60. rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, HT_GPIO_TypeDef *cs_gpiox, uint16_t cs_gpio_pin)
  61. {
  62. CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
  63. RT_ASSERT(bus_name != RT_NULL);
  64. RT_ASSERT(device_name != RT_NULL);
  65. rt_err_t result;
  66. struct rt_spi_device *spi_device;
  67. struct ht32_spi_cs *cs_pin;
  68. if ((cs_gpiox) == HT_GPIOA)
  69. {
  70. CKCUClock.Bit.PA = 1;
  71. CKCU_PeripClockConfig(CKCUClock, ENABLE);
  72. AFIO_GPxConfig(GPIO_PA, cs_gpio_pin, AFIO_FUN_GPIO);
  73. }
  74. else if ((cs_gpiox) == HT_GPIOB)
  75. {
  76. CKCUClock.Bit.PB = 1;
  77. CKCU_PeripClockConfig(CKCUClock, ENABLE);
  78. AFIO_GPxConfig(GPIO_PB, cs_gpio_pin, AFIO_FUN_GPIO);
  79. }
  80. #if defined(HT_GPIOC)
  81. else if ((cs_gpiox) == HT_GPIOC)
  82. {
  83. CKCUClock.Bit.PC = 1;
  84. CKCU_PeripClockConfig(CKCUClock, ENABLE);
  85. AFIO_GPxConfig(GPIO_PC, cs_gpio_pin, AFIO_FUN_GPIO);
  86. }
  87. #endif
  88. #if defined(HT_GPIOD)
  89. else if ((cs_gpiox) == HT_GPIOD)
  90. {
  91. CKCUClock.Bit.PD = 1;
  92. CKCU_PeripClockConfig(CKCUClock, ENABLE);
  93. AFIO_GPxConfig(GPIO_PD, cs_gpio_pin, AFIO_FUN_GPIO);
  94. }
  95. #endif
  96. #if defined(HT_GPIOE)
  97. else if ((cs_gpiox) == HT_GPIOE)
  98. {
  99. CKCUClock.Bit.PE = 1;
  100. CKCU_PeripClockConfig(CKCUClock, ENABLE);
  101. AFIO_GPxConfig(GPIO_PE, cs_gpio_pin, AFIO_FUN_GPIO);
  102. }
  103. #endif
  104. #if defined(HT_GPIOF)
  105. else if ((cs_gpiox) == HT_GPIOF)
  106. {
  107. CKCUClock.Bit.PF = 1;
  108. CKCU_PeripClockConfig(CKCUClock, ENABLE);
  109. AFIO_GPxConfig(GPIO_PF, cs_gpio_pin, AFIO_FUN_GPIO);
  110. }
  111. #endif
  112. GPIO_PullResistorConfig(cs_gpiox, cs_gpio_pin, GPIO_PR_DISABLE);
  113. GPIO_WriteOutBits(cs_gpiox, cs_gpio_pin, SET);
  114. GPIO_DirectionConfig(cs_gpiox, cs_gpio_pin, GPIO_DIR_OUT);
  115. /* attach the device to spi bus */
  116. spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
  117. RT_ASSERT(spi_device != RT_NULL);
  118. cs_pin = (struct ht32_spi_cs *)rt_malloc(sizeof(struct ht32_spi_cs));
  119. RT_ASSERT(cs_pin != RT_NULL);
  120. cs_pin->gpio_x = cs_gpiox;
  121. cs_pin->gpio_pin = cs_gpio_pin;
  122. result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
  123. if (result != RT_EOK)
  124. {
  125. LOG_D("%s attach to %s faild, %d\n", device_name, bus_name, result);
  126. }
  127. RT_ASSERT(result == RT_EOK);
  128. LOG_D("%s attach to %s done", device_name, bus_name);
  129. return result;
  130. }
  131. static rt_err_t ht32_configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration)
  132. {
  133. struct rt_spi_bus *spi_bus = (struct rt_spi_bus *)device->bus;
  134. struct ht32_spi *spi_instance = (struct ht32_spi *)spi_bus->parent.user_data;
  135. SPI_InitTypeDef SPI_InitStructure;
  136. CKCU_PeripClockConfig_TypeDef CKCUClock = {{0}};
  137. RT_ASSERT(device != RT_NULL);
  138. RT_ASSERT(configuration != RT_NULL);
  139. #ifdef BSP_USING_SPI0
  140. if (HT_SPI0 == spi_instance->config->spi_x)
  141. {
  142. CKCUClock.Bit.SPI0 = 1;
  143. }
  144. #endif
  145. #ifdef BSP_USING_SPI1
  146. if (HT_SPI1 == spi_instance->config->spi_x)
  147. {
  148. CKCUClock.Bit.SPI1 = 1;
  149. }
  150. #endif
  151. CKCUClock.Bit.AFIO = 1;
  152. CKCU_PeripClockConfig(CKCUClock, ENABLE);
  153. ht32_spi_gpio_init(spi_instance->config->spi_x);
  154. /* data_width */
  155. if (configuration->data_width <= 8)
  156. {
  157. SPI_InitStructure.SPI_DataLength = SPI_DATALENGTH_8;
  158. }
  159. else if (configuration->data_width <= 16)
  160. {
  161. SPI_InitStructure.SPI_DataLength = SPI_DATALENGTH_16;
  162. }
  163. else
  164. {
  165. return -RT_ERROR;
  166. }
  167. /* Set the polarity and phase of the SPI */
  168. switch (configuration->mode & RT_SPI_MODE_3)
  169. {
  170. case RT_SPI_MODE_0:
  171. SPI_InitStructure.SPI_CPOL = SPI_CPOL_LOW;
  172. SPI_InitStructure.SPI_CPHA = SPI_CPHA_FIRST;
  173. break;
  174. case RT_SPI_MODE_1:
  175. SPI_InitStructure.SPI_CPOL = SPI_CPOL_LOW;
  176. SPI_InitStructure.SPI_CPHA = SPI_CPHA_SECOND;
  177. break;
  178. case RT_SPI_MODE_2:
  179. SPI_InitStructure.SPI_CPOL = SPI_CPOL_HIGH;
  180. SPI_InitStructure.SPI_CPHA = SPI_CPHA_FIRST;
  181. break;
  182. case RT_SPI_MODE_3:
  183. SPI_InitStructure.SPI_CPOL = SPI_CPOL_HIGH;
  184. SPI_InitStructure.SPI_CPHA = SPI_CPHA_SECOND;
  185. break;
  186. }
  187. /* Set the SPI as a master or slave */
  188. SPI_InitStructure.SPI_Mode = (configuration->mode & RT_SPI_SLAVE) ? (SPI_SLAVE) : (SPI_MASTER);
  189. /* Set the data high or low first */
  190. SPI_InitStructure.SPI_FirstBit = (configuration->mode & RT_SPI_MSB) ? (SPI_FIRSTBIT_MSB) : (SPI_FIRSTBIT_LSB);
  191. /* SEL uses software by default */
  192. SPI_InitStructure.SPI_SELMode = SPI_SEL_SOFTWARE;
  193. /* SEL effective level */
  194. SPI_InitStructure.SPI_SELPolarity = (configuration->mode & RT_SPI_CS_HIGH) ? (SPI_SELPOLARITY_HIGH) : (SPI_SELPOLARITY_LOW);
  195. /* Configure the SCK clock frequency of the SPI */
  196. if (configuration->max_hz < 0xFFFF)
  197. {
  198. SPI_InitStructure.SPI_ClockPrescaler = ((configuration->max_hz) & 0xFFFF);
  199. }
  200. else
  201. {
  202. return -RT_ERROR;
  203. }
  204. SPI_InitStructure.SPI_FIFO = SPI_FIFO_DISABLE;
  205. SPI_InitStructure.SPI_RxFIFOTriggerLevel = 0;
  206. SPI_InitStructure.SPI_TxFIFOTriggerLevel = 0;
  207. SPI_Init(spi_instance->config->spi_x, &SPI_InitStructure);
  208. #if (!LIBCFG_SPI_NO_MULTI_MASTER)
  209. SPI_SELOutputCmd(spi_instance->config->spi_x, ENABLE);
  210. #endif
  211. SPI_Cmd(spi_instance->config->spi_x, ENABLE);
  212. return RT_EOK;
  213. }
  214. static rt_ssize_t ht32_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  215. {
  216. struct rt_spi_bus *ht32_spi_bus = (struct rt_spi_bus *)device->bus;
  217. struct ht32_spi *spi_instance = (struct ht32_spi *)ht32_spi_bus->parent.user_data;
  218. struct rt_spi_configuration *config = &device->config;
  219. struct ht32_spi_cs *ht32_spi_cs = device->parent.user_data;
  220. RT_ASSERT(device != NULL);
  221. RT_ASSERT(message != NULL);
  222. /* take cs */
  223. if (message->cs_take)
  224. {
  225. GPIO_ClearOutBits(ht32_spi_cs->gpio_x, ht32_spi_cs->gpio_pin);
  226. LOG_D("spi take cs\n");
  227. }
  228. if (config->data_width <= 8)
  229. {
  230. const rt_uint8_t *send_ptr = message->send_buf;
  231. rt_uint8_t *recv_ptr = message->recv_buf;
  232. rt_uint32_t size = message->length;
  233. LOG_D("spi poll transfer start: %d\n", size);
  234. while (size--)
  235. {
  236. rt_uint8_t data = 0xFF;
  237. if (send_ptr != RT_NULL)
  238. {
  239. data = *send_ptr++;
  240. }
  241. /* wait until the transmit buffer is empty */
  242. while (SPI_GetFlagStatus(spi_instance->config->spi_x, SPI_FLAG_TXE) == RESET);
  243. /* send the byte */
  244. SPI_SendData(spi_instance->config->spi_x, data);
  245. /* wait until a data is received */
  246. while (SPI_GetFlagStatus(spi_instance->config->spi_x, SPI_INT_RXBNE) == RESET);
  247. /* get the received data */
  248. data = SPI_ReceiveData(spi_instance->config->spi_x);
  249. if (recv_ptr != RT_NULL)
  250. {
  251. *recv_ptr++ = data;
  252. }
  253. }
  254. LOG_D("spi poll transfer finsh\n");
  255. }
  256. else if (config->data_width <= 16)
  257. {
  258. const rt_uint16_t *send_ptr = message->send_buf;
  259. rt_uint16_t *recv_ptr = message->recv_buf;
  260. rt_uint32_t size = message->length;
  261. while (size--)
  262. {
  263. rt_uint16_t data = 0xFF;
  264. if (send_ptr != RT_NULL)
  265. {
  266. data = *send_ptr++;
  267. }
  268. /* wait until the transmit buffer is empty */
  269. while (SPI_GetFlagStatus(spi_instance->config->spi_x, SPI_FLAG_TXE) == RESET);
  270. /* send the byte */
  271. SPI_SendData(spi_instance->config->spi_x, data);
  272. /* wait until a data is received */
  273. while (SPI_GetFlagStatus(spi_instance->config->spi_x, SPI_INT_RXBNE) == RESET);
  274. /* get the received data */
  275. data = SPI_ReceiveData(spi_instance->config->spi_x);
  276. if (recv_ptr != RT_NULL)
  277. {
  278. *recv_ptr++ = data;
  279. }
  280. }
  281. }
  282. /* release cs */
  283. if (message->cs_release)
  284. {
  285. GPIO_SetOutBits(ht32_spi_cs->gpio_x, ht32_spi_cs->gpio_pin);
  286. LOG_D("spi release cs\n");
  287. }
  288. return message->length;
  289. }
  290. static struct rt_spi_ops ht32_spi_ops =
  291. {
  292. .configure = ht32_configure,
  293. .xfer = ht32_xfer
  294. };
  295. int rt_hw_spi_init(void)
  296. {
  297. int i;
  298. rt_err_t result;
  299. rt_size_t obj_num = sizeof(spis) / sizeof(struct ht32_spi);
  300. for (i = 0; i < obj_num; i++)
  301. {
  302. spis[i].config = &spi_config[i];
  303. spis[i].spi_bus.parent.user_data = (void *)&spis[i];
  304. result = rt_spi_bus_register(&spis[i].spi_bus, spis[i].config->spi_name, &ht32_spi_ops);
  305. }
  306. return result;
  307. }
  308. INIT_BOARD_EXPORT(rt_hw_spi_init);
  309. #endif /* RT_USING_SPI */