drv_spi.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-01-09 shelton first version
  9. */
  10. #include <board.h>
  11. #include "drv_spi.h"
  12. #ifdef RT_USING_SPI
  13. #if !defined(BSP_USING_SPI1) && !defined(BSP_USING_SPI2) && \
  14. !defined(BSP_USING_SPI3) && !defined(BSP_USING_SPI4)
  15. #error "Please define at least one SPIx"
  16. #endif
  17. //#define DEBUG
  18. #define ARR_LEN(__N) (sizeof(__N) / sizeof(__N[0]))
  19. #ifdef DEBUG
  20. #define DEBUG_PRINTF(...) rt_kprintf(__VA_ARGS__)
  21. #else
  22. #define DEBUG_PRINTF(...)
  23. #endif
  24. /* private rt-thread spi ops function */
  25. static rt_err_t configure(struct rt_spi_device* device, struct rt_spi_configuration* configuration);
  26. static rt_uint32_t xfer(struct rt_spi_device* device, struct rt_spi_message* message);
  27. static struct rt_spi_ops at32_spi_ops =
  28. {
  29. configure,
  30. xfer
  31. };
  32. /**
  33. * Attach the spi device to SPI bus, this function must be used after initialization.
  34. */
  35. rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, GPIO_Type *cs_gpiox, uint16_t cs_gpio_pin)
  36. {
  37. RT_ASSERT(bus_name != RT_NULL);
  38. RT_ASSERT(device_name != RT_NULL);
  39. rt_err_t result;
  40. struct rt_spi_device *spi_device;
  41. struct at32_spi_cs *cs_pin;
  42. /* initialize the cs pin && select the slave*/
  43. GPIO_InitType GPIO_InitStruct;
  44. GPIO_InitStruct.GPIO_Pins = cs_gpio_pin;
  45. GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT_PP;
  46. GPIO_InitStruct.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
  47. GPIO_Init(cs_gpiox, &GPIO_InitStruct);
  48. GPIO_SetBits(cs_gpiox, cs_gpio_pin);
  49. /* attach the device to spi bus*/
  50. spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
  51. RT_ASSERT(spi_device != RT_NULL);
  52. cs_pin = (struct at32_spi_cs *)rt_malloc(sizeof(struct at32_spi_cs));
  53. RT_ASSERT(cs_pin != RT_NULL);
  54. cs_pin->GPIOx = cs_gpiox;
  55. cs_pin->GPIO_Pin = cs_gpio_pin;
  56. result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
  57. if (result != RT_EOK)
  58. {
  59. DEBUG_PRINTF("%s attach to %s faild, %d\n", device_name, bus_name, result);
  60. }
  61. RT_ASSERT(result == RT_EOK);
  62. DEBUG_PRINTF("%s attach to %s done", device_name, bus_name);
  63. return result;
  64. }
  65. static rt_err_t configure(struct rt_spi_device* device,
  66. struct rt_spi_configuration* configuration)
  67. {
  68. struct rt_spi_bus * spi_bus = (struct rt_spi_bus *)device->bus;
  69. struct at32_spi *spi_instance = (struct at32_spi *)spi_bus->parent.user_data;
  70. SPI_InitType SPI_InitStruct;
  71. RT_ASSERT(device != RT_NULL);
  72. RT_ASSERT(configuration != RT_NULL);
  73. at32_msp_spi_init(spi_instance->config->spix);
  74. /* data_width */
  75. if(configuration->data_width <= 8)
  76. {
  77. SPI_InitStruct.SPI_FrameSize = SPI_FRAMESIZE_8BIT;
  78. }
  79. else if(configuration->data_width <= 16)
  80. {
  81. SPI_InitStruct.SPI_FrameSize = SPI_FRAMESIZE_16BIT;
  82. }
  83. else
  84. {
  85. return RT_EIO;
  86. }
  87. /* baudrate */
  88. {
  89. uint32_t spi_apb_clock;
  90. uint32_t max_hz;
  91. RCC_ClockType RCC_Clocks;
  92. max_hz = configuration->max_hz;
  93. RCC_GetClocksFreq(&RCC_Clocks);
  94. DEBUG_PRINTF("sys freq: %d\n", RCC_Clocks.SYSCLK_Freq);
  95. DEBUG_PRINTF("max freq: %d\n", max_hz);
  96. if (spi_instance->config->spix == SPI1)
  97. {
  98. spi_apb_clock = RCC_Clocks.APB2CLK_Freq;
  99. DEBUG_PRINTF("pclk2 freq: %d\n", RCC_Clocks.APB2CLK_Freq);
  100. }
  101. else
  102. {
  103. spi_apb_clock = RCC_Clocks.APB1CLK_Freq;
  104. DEBUG_PRINTF("pclk1 freq: %d\n", RCC_Clocks.APB1CLK_Freq);
  105. }
  106. if(max_hz >= spi_apb_clock/2)
  107. {
  108. SPI_InitStruct.SPI_MCLKP = SPI_MCLKP_2;
  109. }
  110. else if (max_hz >= spi_apb_clock/4)
  111. {
  112. SPI_InitStruct.SPI_MCLKP = SPI_MCLKP_4;
  113. }
  114. else if (max_hz >= spi_apb_clock/8)
  115. {
  116. SPI_InitStruct.SPI_MCLKP = SPI_MCLKP_8;
  117. }
  118. else if (max_hz >= spi_apb_clock/16)
  119. {
  120. SPI_InitStruct.SPI_MCLKP = SPI_MCLKP_16;
  121. }
  122. else if (max_hz >= spi_apb_clock/32)
  123. {
  124. SPI_InitStruct.SPI_MCLKP = SPI_MCLKP_32;
  125. }
  126. else if (max_hz >= spi_apb_clock/64)
  127. {
  128. SPI_InitStruct.SPI_MCLKP = SPI_MCLKP_64;
  129. }
  130. else if (max_hz >= spi_apb_clock/128)
  131. {
  132. SPI_InitStruct.SPI_MCLKP = SPI_MCLKP_128;
  133. }
  134. else
  135. {
  136. /* min prescaler 256 */
  137. SPI_InitStruct.SPI_MCLKP = SPI_MCLKP_256;
  138. }
  139. } /* baudrate */
  140. switch(configuration->mode & RT_SPI_MODE_3)
  141. {
  142. case RT_SPI_MODE_0:
  143. SPI_InitStruct.SPI_CPHA = SPI_CPHA_1EDGE;
  144. SPI_InitStruct.SPI_CPOL = SPI_CPOL_LOW;
  145. break;
  146. case RT_SPI_MODE_1:
  147. SPI_InitStruct.SPI_CPHA = SPI_CPHA_2EDGE;
  148. SPI_InitStruct.SPI_CPOL = SPI_CPOL_LOW;
  149. break;
  150. case RT_SPI_MODE_2:
  151. SPI_InitStruct.SPI_CPHA = SPI_CPHA_1EDGE;
  152. SPI_InitStruct.SPI_CPOL = SPI_CPOL_HIGH;
  153. break;
  154. case RT_SPI_MODE_3:
  155. SPI_InitStruct.SPI_CPHA = SPI_CPHA_2EDGE;
  156. SPI_InitStruct.SPI_CPOL = SPI_CPOL_HIGH;
  157. break;
  158. }
  159. /* MSB or LSB */
  160. if(configuration->mode & RT_SPI_MSB)
  161. {
  162. SPI_InitStruct.SPI_FirstBit = SPI_FIRSTBIT_MSB;
  163. }
  164. else
  165. {
  166. SPI_InitStruct.SPI_FirstBit = SPI_FIRSTBIT_LSB;
  167. }
  168. SPI_InitStruct.SPI_TransMode = SPI_TRANSMODE_FULLDUPLEX;
  169. SPI_InitStruct.SPI_Mode = SPI_MODE_MASTER;
  170. SPI_InitStruct.SPI_NSSSEL = SPI_NSSSEL_SOFT;
  171. /* init SPI */
  172. SPI_Init(spi_instance->config->spix, &SPI_InitStruct);
  173. /* Enable SPI_MASTER */
  174. SPI_Enable(spi_instance->config->spix, ENABLE);
  175. SPI_CRCEN(spi_instance->config->spix, DISABLE);
  176. return RT_EOK;
  177. };
  178. static rt_uint32_t xfer(struct rt_spi_device* device, struct rt_spi_message* message)
  179. {
  180. struct rt_spi_bus * at32_spi_bus = (struct rt_spi_bus *)device->bus;
  181. struct at32_spi *spi_instance = (struct at32_spi *)at32_spi_bus->parent.user_data;
  182. struct rt_spi_configuration * config = &device->config;
  183. struct at32_spi_cs * at32_spi_cs = device->parent.user_data;
  184. RT_ASSERT(device != NULL);
  185. RT_ASSERT(message != NULL);
  186. /* take CS */
  187. if(message->cs_take)
  188. {
  189. GPIO_ResetBits(at32_spi_cs->GPIOx, at32_spi_cs->GPIO_Pin);
  190. DEBUG_PRINTF("spi take cs\n");
  191. }
  192. {
  193. if(config->data_width <= 8)
  194. {
  195. const rt_uint8_t * send_ptr = message->send_buf;
  196. rt_uint8_t * recv_ptr = message->recv_buf;
  197. rt_uint32_t size = message->length;
  198. DEBUG_PRINTF("spi poll transfer start: %d\n", size);
  199. while(size--)
  200. {
  201. rt_uint8_t data = 0xFF;
  202. if(send_ptr != RT_NULL)
  203. {
  204. data = *send_ptr++;
  205. }
  206. // Todo: replace register read/write by at32 lib
  207. //Wait until the transmit buffer is empty
  208. while(RESET == SPI_I2S_GetFlagStatus(spi_instance->config->spix, SPI_I2S_FLAG_TE));
  209. // Send the byte
  210. SPI_I2S_TxData(spi_instance->config->spix, data);
  211. //Wait until a data is received
  212. while(RESET == SPI_I2S_GetFlagStatus(spi_instance->config->spix, SPI_I2S_FLAG_RNE));
  213. // Get the received data
  214. data = SPI_I2S_RxData(spi_instance->config->spix);
  215. if(recv_ptr != RT_NULL)
  216. {
  217. *recv_ptr++ = data;
  218. }
  219. }
  220. DEBUG_PRINTF("spi poll transfer finsh\n");
  221. }
  222. else if(config->data_width <= 16)
  223. {
  224. const rt_uint16_t * send_ptr = message->send_buf;
  225. rt_uint16_t * recv_ptr = message->recv_buf;
  226. rt_uint32_t size = message->length;
  227. while(size--)
  228. {
  229. rt_uint16_t data = 0xFF;
  230. if(send_ptr != RT_NULL)
  231. {
  232. data = *send_ptr++;
  233. }
  234. //Wait until the transmit buffer is empty
  235. while(RESET == SPI_I2S_GetFlagStatus(spi_instance->config->spix, SPI_I2S_FLAG_TE));
  236. // Send the byte
  237. SPI_I2S_TxData(spi_instance->config->spix, data);
  238. //Wait until a data is received
  239. while(RESET == SPI_I2S_GetFlagStatus(spi_instance->config->spix, SPI_I2S_FLAG_RNE));
  240. // Get the received data
  241. data = SPI_I2S_RxData(spi_instance->config->spix);
  242. if(recv_ptr != RT_NULL)
  243. {
  244. *recv_ptr++ = data;
  245. }
  246. }
  247. }
  248. }
  249. /* release CS */
  250. if(message->cs_release)
  251. {
  252. GPIO_SetBits(at32_spi_cs->GPIOx, at32_spi_cs->GPIO_Pin);
  253. DEBUG_PRINTF("spi release cs\n");
  254. }
  255. return message->length;
  256. };
  257. static struct at32_spi_config configs[] = {
  258. #ifdef BSP_USING_SPI1
  259. {SPI1, "spi1"},
  260. #endif
  261. #ifdef BSP_USING_SPI2
  262. {SPI2, "spi2"},
  263. #endif
  264. #ifdef BSP_USING_SPI3
  265. {SPI3, "spi3"},
  266. #endif
  267. #ifdef BSP_USING_SPI4
  268. {SPI4, "spi4"},
  269. #endif
  270. };
  271. static struct at32_spi spis[sizeof(configs) / sizeof(configs[0])] = {0};
  272. /** \brief init and register at32 spi bus.
  273. *
  274. * \param SPI: at32 SPI, e.g: SPI1,SPI2,SPI3.
  275. * \param spi_bus_name: spi bus name, e.g: "spi1"
  276. * \return
  277. *
  278. */
  279. int rt_hw_spi_init(void)
  280. {
  281. int i;
  282. rt_err_t result;
  283. rt_size_t obj_num = sizeof(spis) / sizeof(struct at32_spi);
  284. for (i = 0; i < obj_num; i++)
  285. {
  286. spis[i].config = &configs[i];
  287. spis[i].spi_bus.parent.user_data = (void *)&spis[i];
  288. result = rt_spi_bus_register(&(spis[i].spi_bus), spis[i].config->spi_name, &at32_spi_ops);
  289. }
  290. return result;
  291. }
  292. INIT_BOARD_EXPORT(rt_hw_spi_init);
  293. #endif