drv_spi.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*
  2. * Copyright (c) 2006-2018, Synwit Technology Co.,Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2018-05-31 ZYH first version
  9. * 2018-12-10 Zohar_Lee format file
  10. */
  11. #include <board.h>
  12. #include <rtthread.h>
  13. #include <rtdevice.h>
  14. #include <SWM320_port.h>
  15. #include <rthw.h>
  16. #include <drv_spi.h>
  17. #define SPIRXEVENT 0x01
  18. #define SPITXEVENT 0x02
  19. #define SPITIMEOUT 2
  20. #define SPICRCEN 0
  21. struct swm320_spi
  22. {
  23. SPI_TypeDef *swm320_spi;
  24. struct rt_spi_configuration *cfg;
  25. };
  26. static rt_err_t swm320_spi_init(SPI_TypeDef *spix,
  27. struct rt_spi_configuration *cfg)
  28. {
  29. SPI_InitStructure SPI_initStruct;
  30. if (cfg->mode & RT_SPI_SLAVE)
  31. {
  32. SPI_initStruct.Master = 0;
  33. }
  34. else
  35. {
  36. SPI_initStruct.Master = 1;
  37. }
  38. if (cfg->mode & RT_SPI_3WIRE)
  39. {
  40. return RT_EINVAL;
  41. }
  42. if (cfg->data_width == 8)
  43. {
  44. SPI_initStruct.WordSize = 8;
  45. }
  46. else if (cfg->data_width == 16)
  47. {
  48. SPI_initStruct.WordSize = 16;
  49. }
  50. else
  51. {
  52. return RT_EINVAL;
  53. }
  54. if (cfg->mode & RT_SPI_CPHA)
  55. {
  56. SPI_initStruct.SampleEdge = SPI_SECOND_EDGE;
  57. }
  58. else
  59. {
  60. SPI_initStruct.SampleEdge = SPI_FIRST_EDGE;
  61. }
  62. if (cfg->mode & RT_SPI_CPOL)
  63. {
  64. SPI_initStruct.IdleLevel = SPI_HIGH_LEVEL;
  65. }
  66. else
  67. {
  68. SPI_initStruct.IdleLevel = SPI_LOW_LEVEL;
  69. }
  70. if (cfg->max_hz >= SystemCoreClock / 4)
  71. {
  72. SPI_initStruct.clkDiv = SPI_CLKDIV_4;
  73. }
  74. else if (cfg->max_hz >= SystemCoreClock / 8)
  75. {
  76. SPI_initStruct.clkDiv = SPI_CLKDIV_8;
  77. }
  78. else if (cfg->max_hz >= SystemCoreClock / 16)
  79. {
  80. SPI_initStruct.clkDiv = SPI_CLKDIV_16;
  81. }
  82. else if (cfg->max_hz >= SystemCoreClock / 32)
  83. {
  84. SPI_initStruct.clkDiv = SPI_CLKDIV_32;
  85. }
  86. else if (cfg->max_hz >= SystemCoreClock / 64)
  87. {
  88. SPI_initStruct.clkDiv = SPI_CLKDIV_64;
  89. }
  90. else if (cfg->max_hz >= SystemCoreClock / 128)
  91. {
  92. SPI_initStruct.clkDiv = SPI_CLKDIV_128;
  93. }
  94. else if (cfg->max_hz >= SystemCoreClock / 256)
  95. {
  96. SPI_initStruct.clkDiv = SPI_CLKDIV_256;
  97. }
  98. else
  99. {
  100. /* min prescaler 512 */
  101. SPI_initStruct.clkDiv = SPI_CLKDIV_512;
  102. }
  103. SPI_initStruct.FrameFormat = SPI_FORMAT_SPI;
  104. SPI_initStruct.RXHFullIEn = 0;
  105. SPI_initStruct.TXEmptyIEn = 0;
  106. SPI_initStruct.TXCompleteIEn = 0;
  107. SPI_Init(spix, &SPI_initStruct);
  108. SPI_Open(spix);
  109. return RT_EOK;
  110. }
  111. #define SPISTEP(datalen) (((datalen) == 8) ? 1 : 2)
  112. #define SPISEND_1(reg, ptr, datalen) \
  113. do \
  114. { \
  115. if (datalen == 8) \
  116. { \
  117. (reg) = *(rt_uint8_t *)(ptr); \
  118. } \
  119. else \
  120. { \
  121. (reg) = *(rt_uint16_t *)(ptr); \
  122. } \
  123. } while (0)
  124. #define SPIRECV_1(reg, ptr, datalen) \
  125. do \
  126. { \
  127. if (datalen == 8) \
  128. { \
  129. *(rt_uint8_t *)(ptr) = (reg); \
  130. } \
  131. else \
  132. { \
  133. *(rt_uint16_t *)(ptr) = reg; \
  134. } \
  135. } while (0)
  136. static rt_err_t spitxrx1b(struct swm320_spi *hspi, void *rcvb, const void *sndb)
  137. {
  138. rt_uint32_t padrcv = 0;
  139. rt_uint32_t padsnd = 0xFF;
  140. if (!rcvb && !sndb)
  141. {
  142. return RT_ERROR;
  143. }
  144. if (!rcvb)
  145. {
  146. rcvb = &padrcv;
  147. }
  148. if (!sndb)
  149. {
  150. sndb = &padsnd;
  151. }
  152. while (SPI_IsTXFull(hspi->swm320_spi));
  153. SPISEND_1(hspi->swm320_spi->DATA, sndb, hspi->cfg->data_width);
  154. while (SPI_IsRXEmpty(hspi->swm320_spi));
  155. SPIRECV_1(hspi->swm320_spi->DATA, rcvb, hspi->cfg->data_width);
  156. return RT_EOK;
  157. }
  158. static rt_uint32_t swm320_spi_xfer(struct rt_spi_device *device,
  159. struct rt_spi_message *message)
  160. {
  161. rt_err_t res;
  162. struct swm320_spi *hspi = (struct swm320_spi *)device->bus->parent.user_data;
  163. struct swm320_spi_cs *cs = device->parent.user_data;
  164. const rt_uint8_t *sndb = message->send_buf;
  165. rt_uint8_t *rcvb = message->recv_buf;
  166. rt_int32_t length = message->length;
  167. RT_ASSERT(device != RT_NULL);
  168. RT_ASSERT(device->bus != RT_NULL);
  169. RT_ASSERT(device->bus->parent.user_data != RT_NULL);
  170. if (message->cs_take)
  171. {
  172. rt_pin_write(cs->pin, 0);
  173. }
  174. while (length)
  175. {
  176. res = spitxrx1b(hspi, rcvb, sndb);
  177. if (rcvb)
  178. {
  179. rcvb += SPISTEP(hspi->cfg->data_width);
  180. }
  181. if (sndb)
  182. {
  183. sndb += SPISTEP(hspi->cfg->data_width);
  184. }
  185. if (res != RT_EOK)
  186. {
  187. break;
  188. }
  189. length--;
  190. }
  191. /* Wait until Busy flag is reset before disabling SPI */
  192. while (!SPI_IsTXEmpty(hspi->swm320_spi) && !SPI_IsRXEmpty(hspi->swm320_spi));
  193. if (message->cs_release)
  194. {
  195. rt_pin_write(cs->pin, 1);
  196. }
  197. return message->length - length;
  198. }
  199. static rt_err_t swm320_spi_configure(struct rt_spi_device *device,
  200. struct rt_spi_configuration *configuration)
  201. {
  202. struct swm320_spi *hspi = (struct swm320_spi *)device->bus->parent.user_data;
  203. hspi->cfg = configuration;
  204. return swm320_spi_init(hspi->swm320_spi, configuration);
  205. }
  206. const static struct rt_spi_ops swm320_spi_ops =
  207. {
  208. .configure = swm320_spi_configure,
  209. .xfer = swm320_spi_xfer,
  210. };
  211. #ifdef BSP_USING_SPI0
  212. static struct rt_spi_bus swm320_spi_bus0;
  213. static struct swm320_spi swm320_spi0;
  214. #endif //BSP_USING_SPI0
  215. #ifdef BSP_USING_SPI1
  216. static struct rt_spi_bus swm320_spi_bus1;
  217. static struct swm320_spi swm320_spi1;
  218. #endif //BSP_USING_SPI1
  219. static int swm320_spi_register_bus(SPI_TypeDef *SPIx, const char *name)
  220. {
  221. struct rt_spi_bus *spi_bus;
  222. struct swm320_spi *swm320_spi;
  223. if (SPIx == SPI0)
  224. {
  225. PORT_Init(PORTC, PIN5, FUNMUX1_SPI0_SCLK, 0);
  226. PORT_Init(PORTC, PIN6, FUNMUX0_SPI0_MOSI, 0);
  227. PORT_Init(PORTC, PIN7, FUNMUX1_SPI0_MISO, 1);
  228. spi_bus = &swm320_spi_bus0;
  229. swm320_spi = &swm320_spi0;
  230. }
  231. else if (SPIx == SPI1)
  232. {
  233. PORT_Init(PORTM, PIN5, FUNMUX1_SPI1_SCLK, 0);
  234. PORT_Init(PORTC, PIN2, FUNMUX0_SPI1_MOSI, 0);
  235. PORT_Init(PORTC, PIN3, FUNMUX1_SPI1_MISO, 1);
  236. spi_bus = &swm320_spi_bus1;
  237. swm320_spi = &swm320_spi1;
  238. }
  239. else
  240. {
  241. return -1;
  242. }
  243. swm320_spi->swm320_spi = SPIx;
  244. spi_bus->parent.user_data = swm320_spi;
  245. return rt_spi_bus_register(spi_bus, name, &swm320_spi_ops);
  246. }
  247. //cannot be used before completion init
  248. static rt_err_t swm320_spi_bus_attach_device(rt_uint32_t pin,
  249. const char *bus_name,
  250. const char *device_name)
  251. {
  252. struct rt_spi_device *spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
  253. RT_ASSERT(spi_device != RT_NULL);
  254. struct swm320_spi_cs *cs_pin = (struct swm320_spi_cs *)rt_malloc(sizeof(struct swm320_spi_cs));
  255. RT_ASSERT(cs_pin != RT_NULL);
  256. cs_pin->pin = pin;
  257. rt_pin_mode(pin, PIN_MODE_OUTPUT);
  258. rt_pin_write(pin, 1);
  259. return rt_spi_bus_attach_device(spi_device,
  260. device_name,
  261. bus_name,
  262. (void *)cs_pin);
  263. }
  264. int rt_hw_spi_init(void)
  265. {
  266. int result = 0;
  267. #ifdef BSP_USING_SPI0
  268. result = swm320_spi_register_bus(SPI0, "spi0");
  269. #endif
  270. #ifdef BSP_USING_SPI1
  271. result = swm320_spi_register_bus(SPI1, "spi1");
  272. #endif
  273. return result;
  274. }
  275. INIT_BOARD_EXPORT(rt_hw_spi_init);