spi_test.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. #include "system/includes.h"
  2. /* #include "media/includes.h" */
  3. #include "asm/spi.h"
  4. #include "generic/log.h"
  5. #if 0
  6. /*
  7. [[[ README ]]]
  8. 1. 本spi测试demo提供了spi.c的API使用例程,测试方式为两个spi的环回测试。
  9. spi1设置为主机模式,spi2设置为从机模式,spi1发送数据到spi2,然后接收spi2
  10. 原样返回的数据,然后比较发送出去的数据与接收的数据是否一致,一致则说明
  11. 验证通过。
  12. 2. 本demo涉及BYTE收发测试及DMA收发测试,通过宏SPI_TEST_MODE选择。另外
  13. demo还涉及到spi中断中调用可用于中断的spi API的使用。
  14. 3. spi.c的API不包含CS引脚,CS由API以外控制。
  15. 4. 请在board_xxx.c中定义配置结构体,例如用到spi1,需要定义spi1_p_data,
  16. 否则编译出错。
  17. 5. spi的DMA地址需要4字节对齐。
  18. 6. 虽然spi.c的API带有spi0,但在有挂spi flash的芯片上使用可能会出问题,
  19. 避免使用spi0。
  20. */
  21. #define SPI1_CS_OUT() \
  22. do { \
  23. JL_PORTB->DIR &= ~BIT(4); \
  24. JL_PORTB->DIE |= BIT(4); \
  25. JL_PORTB->PU &= ~BIT(4); \
  26. JL_PORTB->PD &= ~BIT(4); \
  27. } while(0)
  28. #define SPI1_CS_L() (JL_PORTB->OUT &= ~BIT(4))
  29. #define SPI1_CS_H() (JL_PORTB->OUT |= BIT(4))
  30. #define SPI2_CS_IN() \
  31. do { \
  32. JL_PORTA->DIR |= BIT(3); \
  33. JL_PORTA->DIE |= BIT(3); \
  34. JL_PORTA->PU &= ~BIT(3); \
  35. JL_PORTA->PD &= ~BIT(3); \
  36. } while (0)
  37. #define SPI2_READ_CS() (JL_PORTA->IN & BIT(3))
  38. static u8 slave_dir = 1;
  39. static u8 spi1_send_buf[100] __attribute__((aligned(4)));
  40. static u8 spi1_recv_buf[100] __attribute__((aligned(4)));
  41. static u8 spi2_send_buf[100] __attribute__((aligned(4)));
  42. static u8 spi2_recv_buf[100] __attribute__((aligned(4)));
  43. static spi_dev spi1_hdl = 1;
  44. static spi_dev spi2_hdl = 2;
  45. #define SPI_TEST_BYTE_MODE 0x01
  46. #define SPI_TEST_DMA_MODE 0x02
  47. //测试模式选择
  48. #define SPI_TEST_MODE SPI_TEST_BYTE_MODE
  49. static void my_put_u8hex(u8 b)
  50. {
  51. u8 dat;
  52. dat = b / 16;
  53. if (dat >= 0 && dat <= 9) {
  54. putchar('0' + dat);
  55. } else {
  56. putchar('A' + dat - 10);
  57. }
  58. dat = b % 16;
  59. if (dat >= 0 && dat <= 9) {
  60. putchar('0' + dat);
  61. } else {
  62. putchar('A' + dat - 10);
  63. }
  64. putchar(' ');
  65. }
  66. //中断函数,需以下特殊声明
  67. __attribute__((interrupt("")))
  68. static void spi2_isr()
  69. {
  70. static int i = 0;
  71. if (spi_get_pending(spi2_hdl)) {
  72. spi_clear_pending(spi2_hdl);
  73. if (SPI2_READ_CS()) {
  74. return;
  75. }
  76. #if SPI_TEST_MODE == SPI_TEST_BYTE_MODE
  77. if (slave_dir == 1) {
  78. spi2_recv_buf[i] = spi_recv_byte_for_isr(spi2_hdl);
  79. spi_send_byte_for_isr(spi2_hdl, spi2_recv_buf[i]);
  80. i >= 100 ? i = 0 : i++;
  81. slave_dir = 0;
  82. } else {
  83. slave_dir = 1;
  84. }
  85. #elif SPI_TEST_MODE == SPI_TEST_DMA_MODE
  86. if (slave_dir == 1) {
  87. spi_dma_set_addr_for_isr(spi2_hdl, spi2_recv_buf, 100, 0);
  88. slave_dir = 0;
  89. } else {
  90. slave_dir = 1;
  91. }
  92. #endif
  93. }
  94. }
  95. #if 1 //仅用于spi demo,正式工程请放到board_xxx.c文件中
  96. const struct spi_platform_data spi1_p_data = {
  97. .port = {
  98. IO_PORTB_06, //CLK
  99. IO_PORTB_07, //DO
  100. IO_PORTB_05, //DI
  101. },
  102. .mode = SPI_MODE_BIDIR_1BIT,
  103. .clk = 1000000,
  104. .role = SPI_ROLE_MASTER,
  105. };
  106. const struct spi_platform_data spi2_p_data = {
  107. .port = {
  108. IO_PORTB_02, //CLK
  109. IO_PORTB_03, //DO
  110. IO_PORTB_01, //DI
  111. },
  112. .mode = SPI_MODE_BIDIR_1BIT,
  113. .clk = 1000000,
  114. .role = SPI_ROLE_SLAVE,
  115. };
  116. #endif
  117. void spi_test_main()
  118. {
  119. int i;
  120. int err;
  121. spi_open(spi1_hdl);
  122. spi_open(spi2_hdl);
  123. spi_set_ie(spi2_hdl, 1);
  124. //配置中断优先级,中断函数
  125. request_irq(IRQ_SPI2_IDX, 3, spi2_isr, 0);
  126. SPI1_CS_OUT();
  127. SPI2_CS_IN();
  128. SPI1_CS_H();
  129. for (i = 0; i < 100; i++) {
  130. spi1_send_buf[i] = i % 26 + 'A';
  131. spi1_recv_buf[i] = 0;
  132. }
  133. puts(">>> spi test start\n");
  134. #if SPI_TEST_MODE == SPI_TEST_BYTE_MODE
  135. SPI1_CS_L();
  136. for (i = 0; i < 100; i++) {
  137. err = spi_send_byte(spi1_hdl, spi1_send_buf[i]);
  138. if (err) {
  139. puts("spi1 byte send timeout\n");
  140. break;
  141. }
  142. delay(100);
  143. spi1_recv_buf[i] = spi_recv_byte(spi1_hdl, &err);
  144. if (err) {
  145. puts("spi1 byte recv timeout\n");
  146. break;
  147. }
  148. delay(100);
  149. }
  150. SPI1_CS_H();
  151. #elif SPI_TEST_MODE == SPI_TEST_DMA_MODE
  152. spi_dma_set_addr_for_isr(spi2_hdl, spi2_recv_buf, 100, 1);
  153. SPI1_CS_L();
  154. err = spi_dma_send(spi1_hdl, spi1_send_buf, 100);
  155. if (err < 0) {
  156. puts("spi1 dma send timeout\n");
  157. goto __out_dma;
  158. }
  159. //delay(100);
  160. err = spi_dma_recv(spi1_hdl, spi1_recv_buf, 100);
  161. if (err < 0) {
  162. puts("spi1 dma recv timeout\n");
  163. goto __out_dma;
  164. }
  165. //delay(100);
  166. __out_dma:
  167. SPI1_CS_H();
  168. #endif
  169. puts("<<< spi test end\n");
  170. puts("\nspi master receivce buffer:\n");
  171. for (i = 0; i < 100; i++) {
  172. //my_put_u8hex(spi1_recv_buf[i]);
  173. putchar(spi1_recv_buf[i]), putchar(0x20);
  174. if (i % 16 == 15) {
  175. putchar('\n');
  176. }
  177. }
  178. if (i % 16) {
  179. putchar('\n');
  180. }
  181. if (!memcmp(spi1_send_buf, spi1_recv_buf, 100)) {
  182. puts("\nspi test pass\n");
  183. } else {
  184. puts("\nspi test fail\n");
  185. }
  186. spi_close(spi1_hdl);
  187. spi_close(spi2_hdl);
  188. }
  189. #else
  190. #if 0
  191. /* 配置要使用的 CS 脚 */
  192. /* 为了省IO其实可以不用CS脚也能被ellisys分辨出来,或者在ellisys端将CS脚接地 */
  193. #define SPI1_PORT JL_PORTA
  194. #define SPI1_PORT_BIT 1
  195. #define SPI1_CS_OUT() \
  196. do { \
  197. SPI1_PORT->DIR &= ~BIT(SPI1_PORT_BIT); \
  198. SPI1_PORT->DIE |= BIT(SPI1_PORT_BIT); \
  199. SPI1_PORT->PU &= ~BIT(SPI1_PORT_BIT); \
  200. SPI1_PORT->PD &= ~BIT(SPI1_PORT_BIT); \
  201. } while(0)
  202. #define SPI1_CS_L() (SPI1_PORT->DIR &= ~BIT(SPI1_PORT_BIT),SPI1_PORT->OUT &= ~BIT(SPI1_PORT_BIT))
  203. #define SPI1_CS_H() (SPI1_PORT->DIR &= ~BIT(SPI1_PORT_BIT),SPI1_PORT->OUT |= BIT(SPI1_PORT_BIT))
  204. typedef const int spi_dev;
  205. extern int spi_open(spi_dev spi);
  206. extern int spi_dma_send(spi_dev spi, const void *buf, u32 len);
  207. const struct spi_platform_data spi2_p_data = {
  208. .port = {
  209. IO_PORTA_02, //CLK
  210. IO_PORTA_03, //DO
  211. IO_PORTA_01, //DI
  212. },
  213. .mode = SPI_MODE_BIDIR_1BIT,
  214. .clk = 5000000,
  215. .role = SPI_ROLE_MASTER,
  216. };
  217. const struct spi_platform_data spi1_p_data = {
  218. .port = {
  219. /* IO_PORTC_00, // CLK */
  220. /* IO_PORTC_01, // DO,对应ellisys的DI */
  221. /* IO_PORTC_02, // DI,对应ellisys的DO */
  222. IO_PORTA_06, //
  223. IO_PORTA_07, //
  224. IO_PORTA_08, //
  225. },
  226. .mode = SPI_MODE_BIDIR_1BIT,
  227. .clk = 5000000, /* 经测试 ellisys 能分辨到这个速度 */
  228. .role = SPI_ROLE_MASTER,
  229. };
  230. static spi_dev spi1_hdl = 1;
  231. static u8 spi1_send_buf[512] ALIGNED(4);
  232. void bb_spi_init(void)
  233. {
  234. r_printf("spi_open:%08x\n", spi_open);
  235. spi_open(spi1_hdl);
  236. /* SPI1_CS_OUT(); */
  237. /* SPI1_CS_H(); */
  238. }
  239. void bb_spi_send(const void const *buf, size_t len)
  240. {
  241. memcpy(spi1_send_buf, buf, len);
  242. /* SPI1_CS_L(); */
  243. spi_dma_send(spi1_hdl, spi1_send_buf, len);
  244. /* SPI1_CS_H(); */
  245. }
  246. #endif
  247. #endif