drv_spi.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*
  2. * Copyright (c) 2006-2022, 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. * 2020-07-10 lik format file
  11. */
  12. #include "drv_spi.h"
  13. #ifdef RT_USING_SPI
  14. #ifdef BSP_USING_SPI
  15. //#define DRV_DEBUG
  16. #define LOG_TAG "drv.spi"
  17. #include <drv_log.h>
  18. #if !defined(BSP_USING_SPI0) && !defined(BSP_USING_SPI1)
  19. #error "Please define at least one BSP_USING_SPIx"
  20. /* this driver can be disabled at menuconfig ? RT-Thread Components ? Device Drivers */
  21. #endif
  22. struct swm_spi_cs
  23. {
  24. GPIO_TypeDef *GPIOx;
  25. uint32_t gpio_pin;
  26. };
  27. struct swm_spi_cfg
  28. {
  29. const char *name;
  30. SPI_TypeDef *SPIx;
  31. SPI_InitStructure spi_initstruct;
  32. };
  33. /* swm spi dirver class */
  34. struct swm_spi_device
  35. {
  36. struct swm_spi_cfg *spi_cfg;
  37. struct rt_spi_configuration *configure;
  38. struct rt_spi_bus spi_bus;
  39. };
  40. #ifdef BSP_USING_SPI0
  41. #ifndef SPI0_BUS_CONFIG
  42. #define SPI0_BUS_CONFIG \
  43. { \
  44. .name = "spi0", \
  45. .SPIx = SPI0, \
  46. .spi_initstruct.clkDiv = SPI_CLKDIV_32, \
  47. .spi_initstruct.FrameFormat = SPI_FORMAT_SPI, \
  48. .spi_initstruct.SampleEdge = SPI_SECOND_EDGE, \
  49. .spi_initstruct.IdleLevel = SPI_HIGH_LEVEL, \
  50. .spi_initstruct.WordSize = 8, \
  51. .spi_initstruct.Master = 1, \
  52. .spi_initstruct.RXHFullIEn = 0, \
  53. .spi_initstruct.TXEmptyIEn = 0, \
  54. .spi_initstruct.TXCompleteIEn = 0, \
  55. }
  56. #endif /* SPI0_BUS_CONFIG */
  57. #endif /* BSP_USING_SPI0 */
  58. #ifdef BSP_USING_SPI1
  59. #ifndef SPI1_BUS_CONFIG
  60. #define SPI1_BUS_CONFIG \
  61. { \
  62. .name = "spi1", \
  63. .SPIx = SPI1, \
  64. .spi_initstruct.clkDiv = SPI_CLKDIV_32, \
  65. .spi_initstruct.FrameFormat = SPI_FORMAT_SPI, \
  66. .spi_initstruct.SampleEdge = SPI_SECOND_EDGE, \
  67. .spi_initstruct.IdleLevel = SPI_HIGH_LEVEL, \
  68. .spi_initstruct.WordSize = 8, \
  69. .spi_initstruct.Master = 1, \
  70. .spi_initstruct.RXHFullIEn = 0, \
  71. .spi_initstruct.TXEmptyIEn = 0, \
  72. .spi_initstruct.TXCompleteIEn = 0, \
  73. }
  74. #endif /* SPI1_BUS_CONFIG */
  75. #endif /* BSP_USING_SPI1 */
  76. static struct swm_spi_cfg swm_spi_cfg[] =
  77. {
  78. #ifdef BSP_USING_SPI0
  79. SPI0_BUS_CONFIG,
  80. #endif
  81. #ifdef BSP_USING_SPI1
  82. SPI1_BUS_CONFIG,
  83. #endif
  84. };
  85. static struct swm_spi_device spi_bus_obj[sizeof(swm_spi_cfg) / sizeof(swm_spi_cfg[0])] = {0};
  86. static rt_err_t swm_spi_configure(struct rt_spi_device *device,
  87. struct rt_spi_configuration *configure)
  88. {
  89. RT_ASSERT(device != RT_NULL);
  90. RT_ASSERT(configure != RT_NULL);
  91. struct swm_spi_device *spi_drv = rt_container_of(device->bus, struct swm_spi_device, spi_bus);
  92. spi_drv->configure = configure;
  93. struct swm_spi_cfg *spi_cfg = spi_drv->spi_cfg;
  94. if (configure->mode & RT_SPI_SLAVE)
  95. {
  96. spi_cfg->spi_initstruct.Master = 0;
  97. }
  98. else
  99. {
  100. spi_cfg->spi_initstruct.Master = 1;
  101. }
  102. if (configure->mode & RT_SPI_3WIRE)
  103. {
  104. return -RT_EINVAL;
  105. }
  106. if (configure->data_width == 8)
  107. {
  108. spi_cfg->spi_initstruct.WordSize = 8;
  109. }
  110. else if (configure->data_width == 16)
  111. {
  112. spi_cfg->spi_initstruct.WordSize = 16;
  113. }
  114. else
  115. {
  116. return -RT_EIO;
  117. }
  118. if (configure->mode & RT_SPI_CPHA)
  119. {
  120. spi_cfg->spi_initstruct.SampleEdge = SPI_SECOND_EDGE;
  121. }
  122. else
  123. {
  124. spi_cfg->spi_initstruct.SampleEdge = SPI_FIRST_EDGE;
  125. }
  126. if (configure->mode & RT_SPI_CPOL)
  127. {
  128. spi_cfg->spi_initstruct.IdleLevel = SPI_HIGH_LEVEL;
  129. }
  130. else
  131. {
  132. spi_cfg->spi_initstruct.IdleLevel = SPI_LOW_LEVEL;
  133. }
  134. if (configure->max_hz >= SystemCoreClock / 4)
  135. {
  136. spi_cfg->spi_initstruct.clkDiv = SPI_CLKDIV_4;
  137. }
  138. else if (configure->max_hz >= SystemCoreClock / 8)
  139. {
  140. spi_cfg->spi_initstruct.clkDiv = SPI_CLKDIV_8;
  141. }
  142. else if (configure->max_hz >= SystemCoreClock / 16)
  143. {
  144. spi_cfg->spi_initstruct.clkDiv = SPI_CLKDIV_16;
  145. }
  146. else if (configure->max_hz >= SystemCoreClock / 32)
  147. {
  148. spi_cfg->spi_initstruct.clkDiv = SPI_CLKDIV_32;
  149. }
  150. else if (configure->max_hz >= SystemCoreClock / 64)
  151. {
  152. spi_cfg->spi_initstruct.clkDiv = SPI_CLKDIV_64;
  153. }
  154. else if (configure->max_hz >= SystemCoreClock / 128)
  155. {
  156. spi_cfg->spi_initstruct.clkDiv = SPI_CLKDIV_128;
  157. }
  158. else if (configure->max_hz >= SystemCoreClock / 256)
  159. {
  160. spi_cfg->spi_initstruct.clkDiv = SPI_CLKDIV_256;
  161. }
  162. else
  163. {
  164. /* min prescaler 512 */
  165. spi_cfg->spi_initstruct.clkDiv = SPI_CLKDIV_512;
  166. }
  167. SPI_Init(spi_cfg->SPIx, &(spi_cfg->spi_initstruct));
  168. SPI_Open(spi_cfg->SPIx);
  169. LOG_D("%s init done", spi_cfg->name);
  170. return RT_EOK;
  171. }
  172. #define SPISTEP(datalen) (((datalen) == 8) ? 1 : 2)
  173. #define SPISEND_1(reg, ptr, datalen) \
  174. do \
  175. { \
  176. if (datalen == 8) \
  177. { \
  178. (reg) = *(rt_uint8_t *)(ptr); \
  179. } \
  180. else \
  181. { \
  182. (reg) = *(rt_uint16_t *)(ptr); \
  183. } \
  184. } while (0)
  185. #define SPIRECV_1(reg, ptr, datalen) \
  186. do \
  187. { \
  188. if (datalen == 8) \
  189. { \
  190. *(rt_uint8_t *)(ptr) = (reg); \
  191. } \
  192. else \
  193. { \
  194. *(rt_uint16_t *)(ptr) = reg; \
  195. } \
  196. } while (0)
  197. static rt_err_t swm_spi_txrx1b(struct swm_spi_device *spi_drv, void *rcvb, const void *sndb)
  198. {
  199. rt_uint32_t padrcv = 0;
  200. rt_uint32_t padsnd = 0xFF;
  201. if (!rcvb && !sndb)
  202. {
  203. return -RT_ERROR;
  204. }
  205. if (!rcvb)
  206. {
  207. rcvb = &padrcv;
  208. }
  209. if (!sndb)
  210. {
  211. sndb = &padsnd;
  212. }
  213. while (SPI_IsTXFull(spi_drv->spi_cfg->SPIx))
  214. ;
  215. SPISEND_1(spi_drv->spi_cfg->SPIx->DATA, sndb, spi_drv->spi_cfg->spi_initstruct.WordSize);
  216. while (SPI_IsRXEmpty(spi_drv->spi_cfg->SPIx))
  217. ;
  218. SPIRECV_1(spi_drv->spi_cfg->SPIx->DATA, rcvb, spi_drv->spi_cfg->spi_initstruct.WordSize);
  219. return RT_EOK;
  220. }
  221. static rt_uint32_t swm_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
  222. {
  223. rt_err_t res;
  224. RT_ASSERT(device != RT_NULL);
  225. RT_ASSERT(device->bus != RT_NULL);
  226. RT_ASSERT(device->bus->parent.user_data != RT_NULL);
  227. RT_ASSERT(message != RT_NULL);
  228. struct swm_spi_device *spi_drv = rt_container_of(device->bus, struct swm_spi_device, spi_bus);
  229. struct swm_spi_cfg *spi_cfg = spi_drv->spi_cfg;
  230. struct swm_spi_cs *cs = device->parent.user_data;
  231. if (message->cs_take)
  232. {
  233. GPIO_ClrBit(cs->GPIOx, cs->gpio_pin);
  234. }
  235. LOG_D("%s transfer prepare and start", spi_cfg->name);
  236. LOG_D("%s sendbuf: %X, recvbuf: %X, length: %d",
  237. spi_cfg->name, (uint32_t)message->send_buf, (uint32_t)message->recv_buf, message->length);
  238. const rt_uint8_t *sndb = message->send_buf;
  239. rt_uint8_t *rcvb = message->recv_buf;
  240. rt_int32_t length = message->length;
  241. while (length)
  242. {
  243. res = swm_spi_txrx1b(spi_drv, rcvb, sndb);
  244. if (rcvb)
  245. {
  246. rcvb += SPISTEP(spi_cfg->spi_initstruct.WordSize);
  247. }
  248. if (sndb)
  249. {
  250. sndb += SPISTEP(spi_cfg->spi_initstruct.WordSize);
  251. }
  252. if (res != RT_EOK)
  253. {
  254. break;
  255. }
  256. length--;
  257. }
  258. /* Wait until Busy flag is reset before disabling SPI */
  259. while (!SPI_IsTXEmpty(spi_cfg->SPIx) && !SPI_IsRXEmpty(spi_cfg->SPIx))
  260. ;
  261. if (message->cs_release)
  262. {
  263. GPIO_SetBit(cs->GPIOx, cs->gpio_pin);
  264. }
  265. return message->length - length;
  266. }
  267. const static struct rt_spi_ops swm_spi_ops =
  268. {
  269. .configure = swm_spi_configure,
  270. .xfer = swm_spi_xfer,
  271. };
  272. //cannot be used before completion init
  273. rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, GPIO_TypeDef *cs_gpiox, uint32_t cs_gpio_pin)
  274. {
  275. RT_ASSERT(bus_name != RT_NULL);
  276. RT_ASSERT(device_name != RT_NULL);
  277. rt_err_t result;
  278. struct rt_spi_device *spi_device;
  279. struct swm_spi_cs *cs_pin;
  280. GPIO_Init(cs_gpiox, cs_gpio_pin, 1, 0, 0);
  281. GPIO_SetBit(cs_gpiox, cs_gpio_pin);
  282. spi_device = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
  283. RT_ASSERT(spi_device != RT_NULL);
  284. cs_pin = (struct swm_spi_cs *)rt_malloc(sizeof(struct swm_spi_cs));
  285. RT_ASSERT(cs_pin != RT_NULL);
  286. cs_pin->GPIOx = cs_gpiox;
  287. cs_pin->gpio_pin = cs_gpio_pin;
  288. result = rt_spi_bus_attach_device(spi_device, device_name, bus_name, (void *)cs_pin);
  289. if (result != RT_EOK)
  290. {
  291. LOG_E("%s attach to %s faild, %d\n", device_name, bus_name, result);
  292. }
  293. RT_ASSERT(result == RT_EOK);
  294. LOG_D("%s attach to %s done", device_name, bus_name);
  295. return result;
  296. }
  297. int swm_spi_init(void)
  298. {
  299. rt_err_t result;
  300. #ifdef BSP_USING_SPI0
  301. PORT_Init(PORTP, PIN23, FUNMUX1_SPI0_SCLK, 0);
  302. PORT_Init(PORTP, PIN18, FUNMUX0_SPI0_MOSI, 0);
  303. PORT_Init(PORTP, PIN19, FUNMUX1_SPI0_MISO, 1);
  304. #endif //BSP_USING_SPI0
  305. #ifdef BSP_USING_SPI1
  306. PORT_Init(PORTB, PIN1, FUNMUX1_SPI1_SCLK, 0);
  307. PORT_Init(PORTB, PIN2, FUNMUX0_SPI1_MOSI, 0);
  308. PORT_Init(PORTB, PIN3, FUNMUX1_SPI1_MISO, 1);
  309. #endif //BSP_USING_SPI1
  310. for (int i = 0; i < sizeof(swm_spi_cfg) / sizeof(swm_spi_cfg[0]); i++)
  311. {
  312. spi_bus_obj[i].spi_cfg = &swm_spi_cfg[i];
  313. spi_bus_obj[i].spi_bus.parent.user_data = &swm_spi_cfg[i];
  314. result = rt_spi_bus_register(&spi_bus_obj[i].spi_bus, swm_spi_cfg[i].name, &swm_spi_ops);
  315. if (result != RT_EOK)
  316. {
  317. LOG_E("%s bus register fail.", swm_spi_cfg[i].name);
  318. }
  319. else
  320. {
  321. LOG_D("%s bus register success.", swm_spi_cfg[i].name);
  322. }
  323. }
  324. return result;
  325. }
  326. INIT_BOARD_EXPORT(swm_spi_init);
  327. #endif /* BSP_USING_SPI */
  328. #endif /* RT_USING_SPI */