dev_soft_spi.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. * Copyright (c) 2006-2025 RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2025-01-23 CYFS first version
  9. */
  10. #include <rthw.h>
  11. #include <rtdevice.h>
  12. #include <dev_spi_bit_ops.h>
  13. #ifdef RT_USING_SOFT_SPI
  14. #if !defined(RT_USING_SOFT_SPI0) &&\
  15. !defined(RT_USING_SOFT_SPI1) && !defined(RT_USING_SOFT_SPI2) &&\
  16. !defined(RT_USING_SOFT_SPI3) && !defined(RT_USING_SOFT_SPI4) &&\
  17. !defined(RT_USING_SOFT_SPI5) && !defined(RT_USING_SOFT_SPI6)
  18. #error "Please define at least one RT_USING_SOFT_SPIx"
  19. /*
  20. This driver can be disabled at:
  21. menuconfig -> RT-Thread Components -> Device Drivers -> Using I2C device drivers
  22. */
  23. #endif
  24. #define DBG_ENABLE
  25. #define DBG_TAG "SPI_S"
  26. #ifdef RT_SPI_BITOPS_DEBUG
  27. #define DBG_LEVEL DBG_LOG
  28. #endif
  29. #include <rtdbg.h>
  30. /* spi config class */
  31. struct rt_soft_spi_config
  32. {
  33. rt_base_t sck;
  34. rt_base_t miso;
  35. rt_base_t mosi;
  36. rt_uint32_t timing_delay;
  37. const char *bus_name;
  38. };
  39. /* spi dirver class */
  40. struct rt_soft_spi
  41. {
  42. struct rt_spi_bit_obj spi;
  43. struct rt_spi_bit_ops ops;
  44. struct rt_soft_spi_config *cfg;
  45. };
  46. static struct rt_soft_spi_config soft_spi_config[] =
  47. {
  48. #ifdef RT_USING_SOFT_SPI0
  49. {
  50. .sck = RT_SOFT_SPI0_SCK_PIN,
  51. .miso = RT_SOFT_SPI0_MISO_PIN,
  52. .mosi = RT_SOFT_SPI0_MOSI_PIN,
  53. .timing_delay = RT_SOFT_SPI0_TIMING_DELAY,
  54. .bus_name = RT_SOFT_SPI0_BUS_NAME,
  55. },
  56. #endif /*RT_USING_SOFT_SPI0*/
  57. #ifdef RT_USING_SOFT_SPI1
  58. {
  59. .sck = RT_SOFT_SPI1_SCK_PIN,
  60. .miso = RT_SOFT_SPI1_MISO_PIN,
  61. .mosi = RT_SOFT_SPI1_MOSI_PIN,
  62. .timing_delay = RT_SOFT_SPI1_TIMING_DELAY,
  63. .bus_name = RT_SOFT_SPI1_BUS_NAME,
  64. },
  65. #endif /*RT_USING_SOFT_SPI1*/
  66. #ifdef RT_USING_SOFT_SPI2
  67. {
  68. .sck = RT_SOFT_SPI2_SCK_PIN,
  69. .miso = RT_SOFT_SPI2_MISO_PIN,
  70. .mosi = RT_SOFT_SPI2_MOSI_PIN,
  71. .timing_delay = RT_SOFT_SPI2_TIMING_DELAY,
  72. .bus_name = RT_SOFT_SPI2_BUS_NAME,
  73. },
  74. #endif /*RT_USING_SOFT_SPI2*/
  75. #ifdef RT_USING_SOFT_SPI3
  76. {
  77. .sck = RT_SOFT_SPI3_SCK_PIN,
  78. .miso = RT_SOFT_SPI3_MISO_PIN,
  79. .mosi = RT_SOFT_SPI3_MOSI_PIN,
  80. .timing_delay = RT_SOFT_SPI3_TIMING_DELAY,
  81. .bus_name = RT_SOFT_SPI3_BUS_NAME,
  82. },
  83. #endif /*RT_USING_SOFT_SPI3*/
  84. #ifdef RT_USING_SOFT_SPI4
  85. {
  86. .sck = RT_SOFT_SPI4_SCK_PIN,
  87. .miso = RT_SOFT_SPI4_MISO_PIN,
  88. .mosi = RT_SOFT_SPI4_MOSI_PIN,
  89. .timing_delay = RT_SOFT_SPI4_TIMING_DELAY,
  90. .bus_name = RT_SOFT_SPI4_BUS_NAME,
  91. },
  92. #endif /*RT_USING_SOFT_SPI4*/
  93. #ifdef RT_USING_SOFT_SPI5
  94. {
  95. .sck = RT_SOFT_SPI5_SCK_PIN,
  96. .miso = RT_SOFT_SPI5_MISO_PIN,
  97. .mosi = RT_SOFT_SPI5_MOSI_PIN,
  98. .timing_delay = RT_SOFT_SPI5_TIMING_DELAY,
  99. .bus_name = RT_SOFT_SPI5_BUS_NAME,
  100. },
  101. #endif /*RT_USING_SOFT_SPI5*/
  102. #ifdef RT_USING_SOFT_SPI6
  103. {
  104. .sck = RT_SOFT_SPI6_SCK_PIN,
  105. .miso = RT_SOFT_SPI6_MISO_PIN,
  106. .mosi = RT_SOFT_SPI6_MOSI_PIN,
  107. .timing_delay = RT_SOFT_SPI6_TIMING_DELAY,
  108. .bus_name = RT_SOFT_SPI6_BUS_NAME,
  109. },
  110. #endif /*RT_USING_SOFT_SPI6*/
  111. };
  112. static struct rt_soft_spi spi_obj[sizeof(soft_spi_config) / sizeof(soft_spi_config[0])];
  113. static void spi_soft_pin_init(struct rt_soft_spi * soft_spi)
  114. {
  115. struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)soft_spi->cfg;
  116. rt_pin_mode(cfg->sck, PIN_MODE_OUTPUT);
  117. rt_pin_mode(cfg->miso, PIN_MODE_INPUT);
  118. rt_pin_mode(cfg->mosi, PIN_MODE_OUTPUT);
  119. rt_pin_write(cfg->miso, PIN_HIGH);
  120. rt_pin_write(cfg->sck, PIN_HIGH);
  121. rt_pin_write(cfg->mosi, PIN_HIGH);
  122. }
  123. static void spi_soft_tog_sclk(void *data)
  124. {
  125. struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
  126. if(rt_pin_read(cfg->sck) == PIN_HIGH)
  127. {
  128. rt_pin_write(cfg->sck, PIN_LOW);
  129. }
  130. else
  131. {
  132. rt_pin_write(cfg->sck, PIN_HIGH);
  133. }
  134. }
  135. static void spi_soft_set_sclk(void *data, rt_int32_t state)
  136. {
  137. struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
  138. if (state)
  139. {
  140. rt_pin_write(cfg->sck, PIN_HIGH);
  141. }
  142. else
  143. {
  144. rt_pin_write(cfg->sck, PIN_LOW);
  145. }
  146. }
  147. static void spi_soft_set_mosi(void *data, rt_int32_t state)
  148. {
  149. struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
  150. if (state)
  151. {
  152. rt_pin_write(cfg->mosi, PIN_HIGH);
  153. }
  154. else
  155. {
  156. rt_pin_write(cfg->mosi, PIN_LOW);
  157. }
  158. }
  159. static void spi_soft_set_miso(void *data, rt_int32_t state)
  160. {
  161. struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
  162. if (state)
  163. {
  164. rt_pin_write(cfg->miso, PIN_HIGH);
  165. }
  166. else
  167. {
  168. rt_pin_write(cfg->miso, PIN_LOW);
  169. }
  170. }
  171. static rt_int32_t spi_soft_get_sclk(void *data)
  172. {
  173. struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
  174. return rt_pin_read(cfg->sck);
  175. }
  176. static rt_int32_t spi_soft_get_mosi(void *data)
  177. {
  178. struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
  179. return rt_pin_read(cfg->mosi);
  180. }
  181. static rt_int32_t spi_soft_get_miso(void *data)
  182. {
  183. struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
  184. return rt_pin_read(cfg->miso);
  185. }
  186. static void spi_soft_dir_mosi(void *data, rt_int32_t state)
  187. {
  188. struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
  189. if (state)
  190. {
  191. rt_pin_mode(cfg->mosi, PIN_MODE_INPUT);
  192. }
  193. else
  194. {
  195. rt_pin_mode(cfg->mosi, PIN_MODE_OUTPUT);
  196. }
  197. }
  198. static void spi_soft_dir_miso(void *data, rt_int32_t state)
  199. {
  200. struct rt_soft_spi_config *cfg = (struct rt_soft_spi_config *)data;
  201. if (state)
  202. {
  203. rt_pin_mode(cfg->miso, PIN_MODE_INPUT);
  204. }
  205. else
  206. {
  207. rt_pin_mode(cfg->miso, PIN_MODE_OUTPUT);
  208. }
  209. }
  210. static struct rt_spi_bit_ops soft_spi_ops=
  211. {
  212. .data = RT_NULL,
  213. .pin_init = RT_NULL,
  214. .tog_sclk = spi_soft_tog_sclk,
  215. .set_sclk = spi_soft_set_sclk,
  216. .set_mosi = spi_soft_set_mosi,
  217. .set_miso = spi_soft_set_miso,
  218. .get_sclk = spi_soft_get_sclk,
  219. .get_mosi = spi_soft_get_mosi,
  220. .get_miso = spi_soft_get_miso,
  221. .dir_mosi = spi_soft_dir_mosi,
  222. .dir_miso = spi_soft_dir_miso,
  223. .udelay = rt_hw_us_delay,
  224. };
  225. /* Soft SPI initialization function */
  226. int rt_soft_spi_init(void)
  227. {
  228. rt_size_t obj_num = sizeof(spi_obj) / sizeof(struct rt_soft_spi);
  229. rt_err_t result;
  230. for (rt_size_t i = 0; i < obj_num; i++)
  231. {
  232. rt_memcpy(&spi_obj[i].ops, &soft_spi_ops, sizeof(struct rt_spi_bit_ops));
  233. spi_obj[i].ops.data = (void *)&soft_spi_config[i];
  234. spi_obj[i].spi.ops = &soft_spi_ops;
  235. spi_obj[i].cfg = (void *)&soft_spi_config[i];
  236. spi_soft_pin_init(&spi_obj[i]);
  237. spi_obj[i].spi.ops->delay_us = soft_spi_config[i].timing_delay;
  238. result = rt_spi_bit_add_bus(&spi_obj[i].spi, soft_spi_config[i].bus_name, &spi_obj[i].ops);
  239. RT_ASSERT(result == RT_EOK);
  240. }
  241. return RT_EOK;
  242. }
  243. INIT_PREV_EXPORT(rt_soft_spi_init);
  244. #endif /* RT_USING_SOFT_SPI */