drv_spi.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*****************************************************************************
  2. * Copyright (c) 2019, Nations Technologies Inc.
  3. *
  4. * All rights reserved.
  5. * ****************************************************************************
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. *
  10. * - Redistributions of source code must retain the above copyright notice,
  11. * this list of conditions and the disclaimer below.
  12. *
  13. * Nations' name may not be used to endorse or promote products derived from
  14. * this software without specific prior written permission.
  15. *
  16. * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
  17. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  18. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
  19. * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
  20. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  21. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
  22. * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  23. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  24. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  25. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. * ****************************************************************************/
  27. /**
  28. * @file drv_spi.c
  29. * @author Nations
  30. * @version v1.0.0
  31. *
  32. * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
  33. */
  34. #include "drv_spi.h"
  35. #if defined(RT_USING_SPI) && defined(RT_USING_PIN)
  36. #include <rtdevice.h>
  37. #if defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) || \
  38. defined(BSP_USING_SPI3)
  39. /* #define DEBUG */
  40. #ifdef DEBUG
  41. #define DEBUG_PRINTF(...) rt_kprintf(__VA_ARGS__)
  42. #else
  43. #define DEBUG_PRINTF(...)
  44. #endif
  45. /* private rt-thread spi ops function */
  46. static rt_err_t configure(struct rt_spi_device* device, struct rt_spi_configuration* configuration)
  47. {
  48. SPI_InitType SPI_InitStructure;
  49. RCC_ClocksType RCC_ClockFreq;
  50. SPI_Module* spi_periph;
  51. RT_ASSERT(device != RT_NULL);
  52. RT_ASSERT(configuration != RT_NULL);
  53. RCC_GetClocksFreqValue(&RCC_ClockFreq);
  54. spi_periph = (SPI_Module*)device->bus->parent.user_data;
  55. if(spi_periph != SPI1 && spi_periph != SPI2 && spi_periph != SPI3)
  56. {
  57. return RT_EIO;
  58. }
  59. if(configuration->data_width <= 8)
  60. {
  61. SPI_InitStructure.DataLen = SPI_DATA_SIZE_8BITS;
  62. }
  63. else if(configuration->data_width <= 16)
  64. {
  65. SPI_InitStructure.DataLen = SPI_DATA_SIZE_16BITS;
  66. }
  67. else
  68. {
  69. return RT_EIO;
  70. }
  71. {
  72. rt_uint32_t spi_apb_clock;
  73. rt_uint32_t max_hz;
  74. max_hz = configuration->max_hz;
  75. DEBUG_PRINTF("sys freq: %d\n", RCC_ClockFreq.SysclkFreq);
  76. DEBUG_PRINTF("CK_APB2 freq: %d\n", RCC_ClockFreq.Pclk2Freq);
  77. DEBUG_PRINTF("max freq: %d\n", max_hz);
  78. if (spi_periph == SPI1)
  79. {
  80. spi_apb_clock = RCC_ClockFreq.Pclk2Freq;
  81. }
  82. else
  83. {
  84. spi_apb_clock = RCC_ClockFreq.Pclk1Freq;
  85. }
  86. if(max_hz >= spi_apb_clock/2)
  87. {
  88. SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_2;
  89. }
  90. else if (max_hz >= spi_apb_clock/4)
  91. {
  92. SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_4;
  93. }
  94. else if (max_hz >= spi_apb_clock/8)
  95. {
  96. SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_8;
  97. }
  98. else if (max_hz >= spi_apb_clock/16)
  99. {
  100. SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_16;
  101. }
  102. else if (max_hz >= spi_apb_clock/32)
  103. {
  104. SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_32;
  105. }
  106. else if (max_hz >= spi_apb_clock/64)
  107. {
  108. SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_64;
  109. }
  110. else if (max_hz >= spi_apb_clock/128)
  111. {
  112. SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_128;
  113. }
  114. else
  115. {
  116. /* min prescaler 256 */
  117. SPI_InitStructure.BaudRatePres = SPI_BR_PRESCALER_256;
  118. }
  119. } /* baudrate */
  120. switch(configuration->mode & RT_SPI_MODE_3)
  121. {
  122. case RT_SPI_MODE_0:
  123. SPI_InitStructure.CLKPOL = SPI_CLKPOL_LOW;
  124. SPI_InitStructure.CLKPHA = SPI_CLKPHA_FIRST_EDGE;
  125. break;
  126. case RT_SPI_MODE_1:
  127. SPI_InitStructure.CLKPOL = SPI_CLKPOL_LOW;
  128. SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE;
  129. break;
  130. case RT_SPI_MODE_2:
  131. SPI_InitStructure.CLKPOL = SPI_CLKPOL_HIGH;
  132. SPI_InitStructure.CLKPHA = SPI_CLKPHA_FIRST_EDGE;
  133. break;
  134. case RT_SPI_MODE_3:
  135. SPI_InitStructure.CLKPOL = SPI_CLKPOL_HIGH;
  136. SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE;
  137. break;
  138. }
  139. /* MSB or LSB */
  140. if(configuration->mode & RT_SPI_MSB)
  141. {
  142. SPI_InitStructure.FirstBit = SPI_FB_MSB;
  143. }
  144. else
  145. {
  146. SPI_InitStructure.FirstBit = SPI_FB_LSB;
  147. }
  148. /*!< SPI configuration */
  149. SPI_InitStructure.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
  150. SPI_InitStructure.SpiMode = SPI_MODE_MASTER;
  151. SPI_InitStructure.CLKPHA = SPI_CLKPHA_SECOND_EDGE;
  152. SPI_InitStructure.NSS = SPI_NSS_SOFT;
  153. SPI_InitStructure.CRCPoly = 7;
  154. SPI_Init(spi_periph, &SPI_InitStructure);
  155. /*!< Enable the sFLASH_SPI */
  156. SPI_Enable(spi_periph, ENABLE);
  157. return RT_EOK;
  158. }
  159. static rt_uint32_t xfer(struct rt_spi_device* device, struct rt_spi_message* message)
  160. {
  161. struct n32_spi_cs *cs_pin = device->parent.user_data;
  162. SPI_Module* spi_periph = (SPI_Module*)device->bus->parent.user_data;
  163. struct rt_spi_configuration * config = &device->config;
  164. RT_ASSERT(device != NULL);
  165. RT_ASSERT(message != NULL);
  166. /* take CS */
  167. if(message->cs_take)
  168. {
  169. rt_pin_write(cs_pin->GPIO_Pin, PIN_LOW);
  170. DEBUG_PRINTF("spi take cs\n");
  171. }
  172. {
  173. if(config->data_width <= 8)
  174. {
  175. const rt_uint8_t * send_ptr = message->send_buf;
  176. rt_uint8_t * recv_ptr = message->recv_buf;
  177. rt_uint32_t size = message->length;
  178. DEBUG_PRINTF("spi poll transfer start: %d\n", size);
  179. while(size--)
  180. {
  181. rt_uint8_t data = 0xA5;
  182. if(send_ptr != RT_NULL)
  183. {
  184. data = *send_ptr++;
  185. }
  186. /*!< Loop while DAT register in not emplty */
  187. while (SPI_I2S_GetStatus(spi_periph, SPI_I2S_TE_FLAG) == RESET);
  188. // Send the byte
  189. SPI_I2S_TransmitData(spi_periph, data);
  190. //Wait until a data is received
  191. while(SPI_I2S_GetStatus(spi_periph, SPI_I2S_RNE_FLAG) == RESET);
  192. // Get the received data
  193. data = SPI_I2S_ReceiveData(spi_periph);
  194. if(recv_ptr != RT_NULL)
  195. {
  196. *recv_ptr++ = data;
  197. }
  198. }
  199. DEBUG_PRINTF("spi poll transfer finsh\n");
  200. }
  201. else if(config->data_width <= 16)
  202. {
  203. const rt_uint16_t * send_ptr = message->send_buf;
  204. rt_uint16_t * recv_ptr = message->recv_buf;
  205. rt_uint32_t size = message->length;
  206. while(size--)
  207. {
  208. rt_uint16_t data = 0xFF;
  209. if(send_ptr != RT_NULL)
  210. {
  211. data = *send_ptr++;
  212. }
  213. /*!< Loop while DAT register in not emplty */
  214. while (SPI_I2S_GetStatus(spi_periph, SPI_I2S_TE_FLAG) == RESET);
  215. // Send the byte
  216. SPI_I2S_TransmitData(spi_periph, data);
  217. //Wait until a data is received
  218. while(RESET == SPI_I2S_GetStatus(spi_periph, SPI_I2S_RNE_FLAG));
  219. // Get the received data
  220. data = SPI_I2S_ReceiveData(spi_periph);
  221. if(recv_ptr != RT_NULL)
  222. {
  223. *recv_ptr++ = data;
  224. }
  225. }
  226. }
  227. }
  228. /* release CS */
  229. if(message->cs_release)
  230. {
  231. rt_pin_write(cs_pin->GPIO_Pin, PIN_HIGH);
  232. DEBUG_PRINTF("spi release cs\n");
  233. }
  234. return message->length;
  235. }
  236. static struct rt_spi_ops spi_ops =
  237. {
  238. configure,
  239. xfer
  240. };
  241. int rt_hw_spi_init(void)
  242. {
  243. int result = 0;
  244. #ifdef BSP_USING_SPI1
  245. static struct rt_spi_bus spi_bus1;
  246. spi_bus1.parent.user_data = (void *)SPI1;
  247. result = rt_spi_bus_register(&spi_bus1, "spi1", &spi_ops);
  248. RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
  249. RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_SPI1, ENABLE);
  250. /* SPI1_SCK(PA5), SPI1_MISO(PA6) and SPI1_MOSI(PA7) GPIO pin configuration */
  251. GPIOInit(SPI1_SCK_GPIO_PORT, GPIO_Mode_AF_PP, GPIO_Speed_50MHz, SPI1_SCK_PIN);
  252. GPIOInit(SPI1_MOSI_GPIO_PORT, GPIO_Mode_AF_PP, GPIO_Speed_50MHz, SPI1_MOSI_PIN);
  253. GPIOInit(SPI1_MISO_GPIO_PORT, GPIO_Mode_IN_FLOATING, GPIO_Speed_50MHz, SPI1_MISO_PIN);
  254. #endif
  255. #ifdef BSP_USING_SPI2
  256. static struct rt_spi_bus spi_bus2;
  257. spi_bus2.parent.user_data = (void *)SPI2;
  258. result = rt_spi_bus_register(&spi_bus2, "spi2", &spi_ops);
  259. RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_SPI2, ENABLE);
  260. /* SPI2_SCK(PB13), SPI2_MISO(PB14) and SPI2_MOSI(PB15) GPIO pin configuration */
  261. GPIOInit(SPI2_SCK_GPIO_PORT, GPIO_Mode_AF_PP, GPIO_Speed_50MHz, SPI2_SCK_PIN);
  262. GPIOInit(SPI2_MOSI_GPIO_PORT, GPIO_Mode_AF_PP, GPIO_Speed_50MHz, SPI2_MOSI_PIN);
  263. GPIOInit(SPI2_MISO_GPIO_PORT, GPIO_Mode_IN_FLOATING, GPIO_Speed_50MHz, SPI2_MISO_PIN);
  264. #endif
  265. #ifdef BSP_USING_SPI3
  266. static struct rt_spi_bus spi_bus3;
  267. spi_bus3.parent.user_data = (void *)SPI3;
  268. result = rt_spi_bus_register(&spi_bus3, "spi3", &spi_ops);
  269. /* Enable AFIO clock */
  270. RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
  271. GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_SW_ENABLE, ENABLE);
  272. RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_SPI3, ENABLE);
  273. /* SPI3_SCK(PB3), SPI3_MISO(PB4) and SPI3_MOSI(PB5) GPIO pin configuration */
  274. GPIOInit(SPI3_SCK_GPIO_PORT, GPIO_Mode_AF_PP, GPIO_Speed_50MHz, SPI3_SCK_PIN);
  275. GPIOInit(SPI3_MOSI_GPIO_PORT, GPIO_Mode_AF_PP, GPIO_Speed_50MHz, SPI3_MOSI_PIN);
  276. GPIOInit(SPI3_MISO_GPIO_PORT, GPIO_Mode_IN_FLOATING, GPIO_Speed_50MHz, SPI3_MISO_PIN);
  277. #endif
  278. return result;
  279. }
  280. INIT_BOARD_EXPORT(rt_hw_spi_init);
  281. #endif /* defined(BSP_USING_SPI1) || defined(BSP_USING_SPI2) || defined(BSP_USING_SPI3) */
  282. #endif