drv_spi.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. /*
  2. * Copyright (c) 2006-2020, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-05-28 hqfang first implementation.
  9. */
  10. #include "drv_spi.h"
  11. #ifdef RT_USING_SPI
  12. #if !defined(BSP_USING_SPI0) && !defined(BSP_USING_SPI1) && !defined(BSP_USING_SPI2)
  13. #error "Please define at least one BSP_USING_SPIx"
  14. /* this driver can be disabled at menuconfig -> Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable SPI */
  15. #endif
  16. static struct gd32_spi_config spi_config[] =
  17. {
  18. #ifdef BSP_USING_SPI0
  19. {
  20. "spi0",
  21. SPI0,
  22. },
  23. #endif
  24. #ifdef BSP_USING_SPI1
  25. {
  26. "spi1",
  27. SPI1,
  28. },
  29. #endif
  30. #ifdef BSP_USING_SPI2
  31. {
  32. "spi2",
  33. SPI2,
  34. },
  35. #endif
  36. };
  37. static struct gd32_spi spi_obj[sizeof(spi_config) / sizeof(spi_config[0])] = {0};
  38. static rt_err_t gd32_spi_init(rt_uint32_t spi_periph, struct rt_spi_configuration *cfg)
  39. {
  40. spi_parameter_struct spicfg;
  41. uint32_t apbfreq;
  42. uint32_t scale;
  43. RT_ASSERT(cfg != RT_NULL);
  44. spi_struct_para_init(&spicfg);
  45. if (cfg->data_width != 8 && cfg->data_width != 16)
  46. {
  47. return (-RT_EINVAL);
  48. }
  49. switch (spi_periph)
  50. {
  51. case SPI0:
  52. apbfreq = rcu_clock_freq_get(CK_APB2);
  53. break;
  54. default:
  55. apbfreq = rcu_clock_freq_get(CK_APB1);
  56. break;
  57. }
  58. scale = apbfreq / cfg->max_hz;
  59. if (scale <= 2)
  60. {
  61. spicfg.prescale = SPI_PSC_2;
  62. }
  63. else if (scale <= 4)
  64. {
  65. spicfg.prescale = SPI_PSC_4;
  66. }
  67. else if (scale <= 8)
  68. {
  69. spicfg.prescale = SPI_PSC_8;
  70. }
  71. else if (scale <= 16)
  72. {
  73. spicfg.prescale = SPI_PSC_16;
  74. }
  75. else if (scale <= 32)
  76. {
  77. spicfg.prescale = SPI_PSC_32;
  78. }
  79. else if (scale <= 64)
  80. {
  81. spicfg.prescale = SPI_PSC_64;
  82. }
  83. else if (scale <= 128)
  84. {
  85. spicfg.prescale = SPI_PSC_128;
  86. }
  87. else if (scale <= 256)
  88. {
  89. spicfg.prescale = SPI_PSC_256;
  90. }
  91. else
  92. {
  93. spicfg.prescale = SPI_PSC_256;
  94. }
  95. if (cfg->data_width == 8)
  96. {
  97. spicfg.frame_size = SPI_FRAMESIZE_8BIT;
  98. }
  99. else
  100. {
  101. spicfg.frame_size = SPI_FRAMESIZE_16BIT;
  102. }
  103. if (cfg->mode & RT_SPI_MSB)
  104. {
  105. spicfg.endian = SPI_ENDIAN_MSB;
  106. }
  107. else
  108. {
  109. spicfg.endian = SPI_ENDIAN_LSB;
  110. }
  111. spicfg.clock_polarity_phase = 0;
  112. if (cfg->mode & RT_SPI_CPHA)
  113. {
  114. spicfg.clock_polarity_phase |= SPI_CTL0_CKPH;
  115. }
  116. if (cfg->mode & RT_SPI_CPOL)
  117. {
  118. spicfg.clock_polarity_phase |= SPI_CTL0_CKPL;
  119. }
  120. if (cfg->mode & RT_SPI_SLAVE)
  121. {
  122. spicfg.device_mode = SPI_SLAVE;
  123. }
  124. else
  125. {
  126. spicfg.device_mode = SPI_MASTER;
  127. }
  128. spicfg.nss = SPI_NSS_SOFT;
  129. spicfg.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
  130. spi_init(spi_periph, &spicfg);
  131. /* set crc polynomial */
  132. spi_crc_polynomial_set(spi_periph, 7);
  133. return RT_EOK;
  134. }
  135. static rt_err_t gd32_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
  136. {
  137. rt_err_t ret = RT_EOK;
  138. RT_ASSERT(device != RT_NULL);
  139. struct gd32_spi *spi_obj = (struct gd32_spi *)(device->bus->parent.user_data);
  140. struct gd32_spi_config *spi_cfg = (struct gd32_spi_config *)(spi_obj->config);
  141. ret = gd32_spi_init(spi_cfg->spi_periph, cfg);
  142. /* enable SPI */
  143. spi_enable(spi_cfg->spi_periph);
  144. return ret;
  145. }
  146. /**
  147. * Attach the spi device to SPI bus, this function must be used after initialization.
  148. */
  149. rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_uint32_t pin)
  150. {
  151. rt_err_t ret = RT_EOK;
  152. struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
  153. RT_ASSERT(spi_device != RT_NULL);
  154. struct gd32_spi_cs *cs_pin = (struct gd32_spi_cs *)rt_malloc(sizeof(struct gd32_spi_cs));
  155. RT_ASSERT(cs_pin != RT_NULL);
  156. cs_pin->pin = pin;
  157. rt_pin_mode(pin, PIN_MODE_OUTPUT);
  158. rt_pin_write(pin, PIN_HIGH);
  159. ret = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
  160. return ret;
  161. }
  162. rt_size_t gd32_spi_transmit(rt_uint32_t spi_periph, const void *send_buf, void *recv_buf, rt_size_t length)
  163. {
  164. uint8_t *send_buf_8b = (uint8_t *)send_buf;
  165. uint8_t *recv_buf_8b = (uint8_t *)recv_buf;
  166. uint8_t sndbyte = 0xFF, rcvbyte;
  167. rt_size_t idx = 0;
  168. while (idx < length)
  169. {
  170. while (RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE));
  171. if (send_buf_8b)
  172. {
  173. sndbyte = send_buf_8b[idx];
  174. }
  175. spi_i2s_data_transmit(spi_periph, sndbyte);
  176. while (RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE));
  177. rcvbyte = spi_i2s_data_receive(spi_periph);
  178. if (recv_buf_8b)
  179. {
  180. recv_buf_8b[idx] = rcvbyte;
  181. }
  182. idx ++;
  183. }
  184. return length;
  185. }
  186. static rt_uint32_t gd32_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  187. {
  188. rt_uint32_t total_length = 0;
  189. rt_err_t ret = RT_EOK;
  190. RT_ASSERT(device != RT_NULL);
  191. struct gd32_spi *spi_obj = (struct gd32_spi *)(device->bus->parent.user_data);
  192. struct gd32_spi_config *spi_cfg = (struct gd32_spi_config *)(spi_obj->config);
  193. RT_ASSERT(spi_cfg != RT_NULL);
  194. struct gd32_spi_cs *cs = (struct gd32_spi_cs *)(device->parent.user_data);
  195. if (message && message->cs_take)
  196. {
  197. rt_pin_write(cs->pin, PIN_LOW);
  198. }
  199. if (message && message->length)
  200. {
  201. total_length += gd32_spi_transmit(spi_cfg->spi_periph, message->send_buf, \
  202. message->recv_buf, message->length);
  203. }
  204. if (message && message->cs_release)
  205. {
  206. rt_pin_write(cs->pin, PIN_HIGH);
  207. }
  208. return total_length;
  209. }
  210. static const struct rt_spi_ops spi_ops =
  211. {
  212. gd32_spi_configure,
  213. gd32_spi_xfer
  214. };
  215. int rt_hw_spi_init(void)
  216. {
  217. rt_size_t obj_num;
  218. int index;
  219. rt_err_t result = 0;
  220. #ifdef BSP_USING_SPI0
  221. rcu_periph_clock_enable(RCU_SPI0);
  222. #endif
  223. #ifdef BSP_USING_SPI1
  224. rcu_periph_clock_enable(RCU_SPI1);
  225. #endif
  226. #ifdef BSP_USING_SPI2
  227. rcu_periph_clock_enable(RCU_SPI2);
  228. #endif
  229. obj_num = sizeof(spi_obj) / sizeof(struct gd32_spi);
  230. for (index = 0; index < obj_num; index++)
  231. {
  232. /* init spi object */
  233. spi_obj[index].config = &spi_config[index];
  234. spi_obj[index].bus.parent.user_data = &spi_obj[index];
  235. /* register spi device */
  236. result = rt_spi_bus_register(&spi_obj[index].bus,
  237. spi_obj[index].config->name,
  238. &spi_ops);
  239. RT_ASSERT(result == RT_EOK);
  240. }
  241. return 0;
  242. }
  243. INIT_DEVICE_EXPORT(rt_hw_spi_init);
  244. #endif
  245. /* end of spi driver */