drv_spi.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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-03-04 stevetong459 first version
  9. */
  10. #include "drv_spi.h"
  11. #define LOG_TAG "drv.spi"
  12. #define DBG_LVL DBG_INFO
  13. #include <rtdbg.h>
  14. #if defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) || defined(BSP_USING_SPI3)
  15. static rt_err_t _spi_configure(struct rt_spi_device *spi_drv, struct rt_spi_configuration *cfg)
  16. {
  17. RT_ASSERT(spi_drv != RT_NULL);
  18. RT_ASSERT(cfg != RT_NULL);
  19. SPI_Config_T hw_spi_config;
  20. SPI_T *spi = (SPI_T *)spi_drv->bus->parent.user_data;
  21. uint32_t hw_spi_apb_clock;
  22. #if (DBG_LVL == DBG_LOG)
  23. uint32_t hw_spi_sys_clock = RCM_ReadSYSCLKFreq();
  24. #endif
  25. hw_spi_config.mode = (cfg->mode & RT_SPI_SLAVE) ? SPI_MODE_SLAVE : SPI_MODE_MASTER;
  26. hw_spi_config.direction = (cfg->mode & RT_SPI_3WIRE) ? SPI_DIRECTION_1LINE_RX : SPI_DIRECTION_2LINES_FULLDUPLEX;
  27. hw_spi_config.phase = (cfg->mode & RT_SPI_CPHA) ? SPI_CLKPHA_2EDGE : SPI_CLKPHA_1EDGE;
  28. hw_spi_config.polarity = (cfg->mode & RT_SPI_CPOL) ? SPI_CLKPOL_HIGH : SPI_CLKPOL_LOW;
  29. hw_spi_config.nss = (cfg->mode & RT_SPI_NO_CS) ? SPI_NSS_HARD : SPI_NSS_SOFT;
  30. hw_spi_config.firstBit = (cfg->mode & RT_SPI_MSB) ? SPI_FIRSTBIT_MSB : SPI_FIRSTBIT_LSB;
  31. if (cfg->data_width == 8)
  32. {
  33. hw_spi_config.length = SPI_DATA_LENGTH_8B;
  34. }
  35. else if (cfg->data_width == 16)
  36. {
  37. hw_spi_config.length = SPI_DATA_LENGTH_16B;
  38. }
  39. else
  40. {
  41. return RT_EIO;
  42. }
  43. RCM_ReadPCLKFreq(NULL, &hw_spi_apb_clock);
  44. if (cfg->max_hz >= hw_spi_apb_clock / 2)
  45. {
  46. hw_spi_config.baudrateDiv = SPI_BAUDRATE_DIV_2;
  47. }
  48. else if (cfg->max_hz >= hw_spi_apb_clock / 4)
  49. {
  50. hw_spi_config.baudrateDiv = SPI_BAUDRATE_DIV_4;
  51. }
  52. else if (cfg->max_hz >= hw_spi_apb_clock / 8)
  53. {
  54. hw_spi_config.baudrateDiv = SPI_BAUDRATE_DIV_8;
  55. }
  56. else if (cfg->max_hz >= hw_spi_apb_clock / 16)
  57. {
  58. hw_spi_config.baudrateDiv = SPI_BAUDRATE_DIV_16;
  59. }
  60. else if (cfg->max_hz >= hw_spi_apb_clock / 32)
  61. {
  62. hw_spi_config.baudrateDiv = SPI_BAUDRATE_DIV_32;
  63. }
  64. else if (cfg->max_hz >= hw_spi_apb_clock / 64)
  65. {
  66. hw_spi_config.baudrateDiv = SPI_BAUDRATE_DIV_64;
  67. }
  68. else if (cfg->max_hz >= hw_spi_apb_clock / 128)
  69. {
  70. hw_spi_config.baudrateDiv = SPI_BAUDRATE_DIV_128;
  71. }
  72. else
  73. {
  74. /* min prescaler 256 */
  75. hw_spi_config.baudrateDiv = SPI_BAUDRATE_DIV_256;
  76. }
  77. LOG_D("sys freq: %d, pclk2 freq: %d, SPI limiting freq: %d, BaudRatePrescaler: %d",
  78. hw_spi_sys_clock, hw_spi_apb_clock, cfg->max_hz, hw_spi_config.baudrateDiv);
  79. SPI_Config(spi, &hw_spi_config);
  80. SPI_Enable(spi);
  81. return RT_EOK;
  82. }
  83. static rt_uint32_t _spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  84. {
  85. RT_ASSERT(device != NULL);
  86. RT_ASSERT(message != NULL);
  87. rt_base_t cs_pin = (rt_base_t)device->parent.user_data;
  88. SPI_T *spi = (SPI_T *)device->bus->parent.user_data;
  89. struct rt_spi_configuration *config = &device->config;
  90. /* take CS */
  91. if (message->cs_take)
  92. {
  93. rt_pin_write(cs_pin, PIN_LOW);
  94. LOG_D("spi take cs\n");
  95. }
  96. if (config->data_width <= 8)
  97. {
  98. const rt_uint8_t *send_ptr = message->send_buf;
  99. rt_uint8_t *recv_ptr = message->recv_buf;
  100. rt_uint32_t size = message->length;
  101. LOG_D("spi poll transfer start: %d\n", size);
  102. while (size--)
  103. {
  104. rt_uint8_t data = 0xFF;
  105. if (send_ptr != RT_NULL)
  106. {
  107. data = *send_ptr++;
  108. }
  109. /* Wait until the transmit buffer is empty */
  110. while (SPI_I2S_ReadStatusFlag(spi, SPI_FLAG_TXBE) == RESET);
  111. SPI_I2S_TxData(spi, data);
  112. /* Wait until a data is received */
  113. while (SPI_I2S_ReadStatusFlag(spi, SPI_FLAG_RXBNE) == RESET);
  114. data = SPI_I2S_RxData(spi);
  115. if (recv_ptr != RT_NULL)
  116. {
  117. *recv_ptr++ = data;
  118. }
  119. }
  120. LOG_D("spi poll transfer finsh\n");
  121. }
  122. else if (config->data_width <= 16)
  123. {
  124. const rt_uint16_t *send_ptr = message->send_buf;
  125. rt_uint16_t *recv_ptr = message->recv_buf;
  126. rt_uint32_t size = message->length;
  127. while (size--)
  128. {
  129. rt_uint16_t data = 0xFF;
  130. if (send_ptr != RT_NULL)
  131. {
  132. data = *send_ptr++;
  133. }
  134. /*Wait until the transmit buffer is empty */
  135. while (SPI_I2S_ReadStatusFlag(spi, SPI_FLAG_TXBE) == RESET);
  136. /* Send the byte */
  137. SPI_I2S_TxData(spi, data);
  138. /*Wait until a data is received */
  139. while (SPI_I2S_ReadStatusFlag(spi, SPI_FLAG_RXBNE) == RESET);
  140. /* Get the received data */
  141. data = SPI_I2S_RxData(spi);
  142. if (recv_ptr != RT_NULL)
  143. {
  144. *recv_ptr++ = data;
  145. }
  146. }
  147. }
  148. /* release CS */
  149. if (message->cs_release)
  150. {
  151. rt_pin_write(cs_pin, PIN_HIGH);
  152. LOG_D("spi release cs\n");
  153. }
  154. return message->length;
  155. };
  156. static const struct rt_spi_ops _spi_ops =
  157. {
  158. _spi_configure,
  159. _spi_xfer
  160. };
  161. static int rt_hw_spi_init(void)
  162. {
  163. int result = 0;
  164. GPIO_Config_T gpio_config;
  165. #ifdef BSP_USING_SPI1
  166. static struct rt_spi_bus spi_bus1;
  167. spi_bus1.parent.user_data = (void *)SPI1;
  168. result = rt_spi_bus_register(&spi_bus1, "spi1", &_spi_ops);
  169. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA);
  170. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_SPI1);
  171. /* SPI1_SCK(PA5) SPI1_MOSI(PA7) */
  172. gpio_config.mode = GPIO_MODE_AF_PP;
  173. gpio_config.speed = GPIO_SPEED_50MHz;
  174. gpio_config.pin = (GPIO_PIN_5 | GPIO_PIN_7);
  175. GPIO_Config(GPIOA, &gpio_config);
  176. /* SPI1_MISO(PA6) */
  177. gpio_config.mode = GPIO_MODE_IN_FLOATING;
  178. gpio_config.speed = GPIO_SPEED_50MHz;
  179. gpio_config.pin = GPIO_PIN_6;
  180. GPIO_Config(GPIOA, &gpio_config);
  181. #endif
  182. #ifdef BSP_USING_SPI2
  183. static struct rt_spi_bus spi_bus2;
  184. spi_bus2.parent.user_data = (void *)SPI2;
  185. result = rt_spi_bus_register(&spi_bus2, "spi2", &_spi_ops);
  186. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOB);
  187. RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_SPI2);
  188. /* SPI2_SCK(PB13) SPI2_MOSI(PB15) */
  189. gpio_config.mode = GPIO_MODE_AF_PP;
  190. gpio_config.speed = GPIO_SPEED_50MHz;
  191. gpio_config.pin = (GPIO_PIN_13 | GPIO_PIN_15);
  192. GPIO_Config(GPIOB, &gpio_config);
  193. /* SPI2_MISO(PB14) */
  194. gpio_config.mode = GPIO_MODE_IN_FLOATING;
  195. gpio_config.speed = GPIO_SPEED_50MHz;
  196. gpio_config.pin = GPIO_PIN_14;
  197. GPIO_Config(GPIOB, &gpio_config);
  198. #endif
  199. #ifdef BSP_USING_SPI3
  200. static struct rt_spi_bus spi_bus3;
  201. spi_bus3.parent.user_data = (void *)SPI3;
  202. result = rt_spi_bus_register(&spi_bus3, "spi3", &_spi_ops);
  203. RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOB);
  204. RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_SPI3);
  205. /* SPI3_SCK(PB3) SPI3_MOSI(PB5) */
  206. gpio_config.mode = GPIO_MODE_AF_PP;
  207. gpio_config.speed = GPIO_SPEED_50MHz;
  208. gpio_config.pin = (GPIO_PIN_3 | GPIO_PIN_5);
  209. GPIO_Config(GPIOB, &gpio_config);
  210. /* SPI3_MISO(PB4) */
  211. gpio_config.mode = GPIO_MODE_IN_FLOATING;
  212. gpio_config.speed = GPIO_SPEED_50MHz;
  213. gpio_config.pin = GPIO_PIN_4;
  214. GPIO_Config(GPIOB, &gpio_config);
  215. #endif
  216. return result;
  217. }
  218. INIT_BOARD_EXPORT(rt_hw_spi_init);
  219. #endif /* RT_USING_SPI */