tdc_spi_drv.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. #include "board.h"
  2. #define TDC_SPI_CR2_BSC ((0<<6) | /* RXNEIE, RX not empty interrupt 0:off; 1:on; */ \
  3. (0<<5) | /* TXEIE, TX empty interrupt 0:off; 1:on; */ \
  4. (0<<4) | /* HDMATX, hard DMA TX 0:off; 1:on; */ \
  5. (0<<3) | /* HDMARX, hard DMA RX 0:off; 1:on; */ \
  6. (0<<2) | /* INT_EN, SPI interrupt 0:off; 1:on; */ \
  7. (3<<0)) /* 2 RSV bits */
  8. #define TDC_DMA_CONFA_BSC ((0u<<29) | /* ST, 0:no soft start DMA; 1:soft start DMA */ \
  9. (0x42u<<22) | /* TRI_SEL, 0x40:SPI0 RX; 0x42:SPI1 RX */ \
  10. (0u<<16)) /* BC, one trigger require 0:one; 1:two; ... 15:sixteen data(8/16/32 bits per data) */
  11. uint8_t tdc_spi_rbuf[5];
  12. // 4-wire SPI (2.5V)
  13. // fclk <= 15M
  14. // Pulse width >= 30 ns
  15. // CPOL = 0 (SCK is low when idle)
  16. // CPHA = 1 (capture data at falling edge of SCK)
  17. // assert SSN at least 40ns before SCLK rising
  18. // deassert SSN at least 40ns after SCLK falling
  19. // MSB first
  20. void tdc_spi_init(void)
  21. {
  22. // SPI GPIO Configuration
  23. // PC02 : SPI1_MISO
  24. GpioInit(PC02_SPI1_MISO, GPIO_DIG_IN_NONEUP_PULLDOWN);
  25. PeriClk_MutEnable(PeriClk_Spi1);
  26. M0P_SPI1->CR = (0<<7) | // SPR2
  27. (0<<6) | // SPEN, 0:off; 1:on;
  28. (1<<4) | // MSTR, 0:slave; 1:master;
  29. (0<<3) | // CPOL, when idle 0:SCK is low; 1:SCK is high;
  30. (1<<2) | // CPHA, 0:1st; 1:2nd; SCK edge sample data
  31. (0<<0); // [SPR1:SPR0], 0:PCLK/2; 1:PCLK/4;
  32. M0P_SPI1->CR2 = TDC_SPI_CR2_BSC;
  33. M0P_SPI1->SSN = 1;
  34. M0P_SPI1->CR_f.SPEN = 1;
  35. PeriClk_MutDisable(PeriClk_Spi1);
  36. // SPI GPIO Configuration
  37. // PD00 : SPI1_CS
  38. // PD01 : SPI1_SCK
  39. // PC03 : SPI1_MOSI
  40. GpioInit(PD00_SPI1_CS, GPIO_DIG_OUT_STRN_PUSH_NONEUP_NONEDOWN);
  41. GpioInit(PD01_SPI1_SCK, GPIO_DIG_OUT_STRN_PUSH_NONEUP_NONEDOWN);
  42. GpioInit(PC03_SPI1_MOSI, GPIO_DIG_OUT_STRN_PUSH_NONEUP_NONEDOWN);
  43. DMA_ReqClkOn();
  44. M0P_DMAC->CONF = (1u<<31) | // EN, 0:DMAC off; 1:DMAC on;
  45. (0u<<28) | // PRIO, 0:priority of CH0 higher than CH1; 1:round-robin between CH0 and CH1;
  46. (0u<<24); // HALT, 0:not halt; others:halt all CH;
  47. M0P_DMAC->CONFB0 = (0u<<28) | // MODE, 0:Block; 1:Burst(non interruptible between TC+1 Trigger);
  48. (0u<<26) | // WIDTH, 0:8 bits; 1:16 bits; 2:32 bits;
  49. (1u<<25) | // FS, source address 0:inc; 1:fixed;
  50. (0u<<24) | // FD, destination address 0:inc; 1:fixed;
  51. (0u<<20) | // ERR_IE, interrupt 0:off; 1:on; when DMA error
  52. (0u<<19) | // FIS_IE, interrupt 0:off; 1:on; after DMA done
  53. (0u<<0); // MSK, 0:clear ENS 1:keep ENS; after DMA done
  54. M0P_DMAC->SRCADR0 = (uint32_t)&(M0P_SPI1->DATA);
  55. M0P_DMAC->DSTADR0 = (uint32_t)&(tdc_spi_rbuf[0]);
  56. DMA_ReqClkOff();
  57. }
  58. void spi1_wr_byte(uint8_t byte)
  59. {
  60. while(M0P_SPI1->STAT_f.TXE==0x0u){
  61. // loop wait until tx buffer is empty
  62. }
  63. M0P_SPI1->DATA = byte;
  64. }
  65. uint8_t spi1_rd_byte(void)
  66. {
  67. M0P_SPI1->DATA = 0x00u; // write any data
  68. while(M0P_SPI1->STAT_f.TXE==0x0u){
  69. // loop wait until tx buffer is empty
  70. }
  71. while(M0P_SPI1->STAT_f.BUSY){ // more reliable than RXNE
  72. // loop wait until not busy
  73. }
  74. return(M0P_SPI1->DATA);
  75. }
  76. void spi1_wait_busy(void)
  77. {
  78. while(M0P_SPI1->STAT_f.BUSY){ // more reliable than RXNE
  79. // loop wait until not busy
  80. }
  81. }
  82. void tdc_spi_wr_d32(uint8_t code, uint32_t data)
  83. {
  84. uint8_t i;
  85. // assert CSN
  86. M0P_SPI1->SSN = 0; // 0:SPI_CS low; 1:SPI_CS high
  87. M0P_SPI1->DATA = code;
  88. for(i=0;i<4;i++){
  89. while(M0P_SPI1->STAT_f.TXE==0x0u){
  90. // loop wait until tx buffer is empty
  91. }
  92. M0P_SPI1->DATA = data>>24; // MSB first
  93. data = data<<8;
  94. }
  95. while(M0P_SPI1->STAT_f.TXE==0x0u){
  96. // loop wait until tx buffer is empty
  97. }
  98. while(M0P_SPI1->STAT_f.BUSY){
  99. // loop wait until not busy
  100. }
  101. // deassert CSN and clear RXN(hardwareE)
  102. M0P_SPI1->SSN = 1; // 0:SPI_CS low; 1:SPI_CS high
  103. // M0P_SPI1->ICLR = 0x0; // clr RX flag(rising of SSN clear rx flag automatically)
  104. }
  105. void tdc_spi_wr_code(uint8_t code)
  106. {
  107. // assert CSN
  108. M0P_SPI1->SSN = 0; // 0:SPI_CS low; 1:SPI_CS high
  109. M0P_SPI1->DATA = code;
  110. while(M0P_SPI1->STAT_f.TXE==0x0u){
  111. // loop wait until tx buffer is empty
  112. }
  113. while(M0P_SPI1->STAT_f.BUSY){
  114. // loop wait until not busy
  115. }
  116. // deassert CSN and clear RXNE(hardware)
  117. M0P_SPI1->SSN = 1; // 0:SPI_CS low; 1:SPI_CS high
  118. // M0P_SPI1->ICLR = 0x0; // clr RX flag(rising of SSN clear rx flag automatically)
  119. }
  120. uint32_t tdc_spi_rd_d32(uint8_t code)
  121. {
  122. uint8_t i;
  123. uint32_t data;
  124. // assert CSN
  125. M0P_SPI1->SSN = 0; // 0:SPI_CS low; 1:SPI_CS high
  126. // enable DMAR of SPI
  127. M0P_SPI1->CR2 = TDC_SPI_CR2_BSC |
  128. (1<<3); // HDMARX, hard DMA RX 0:off; 1:on;
  129. // reload DSTADR because INC
  130. M0P_DMAC->DSTADR0 = (uint32_t)&(tdc_spi_rbuf[0]);
  131. // enable DMA channel
  132. M0P_DMAC->CONFA0 = TDC_DMA_CONFA_BSC |
  133. (1u<<31) | /* ENS, 0:CHx off; 1:CHx on; */
  134. ((5-1)<<0); /* TC = Len - 1, close DAM after (TC+1)*(BC+1) */
  135. M0P_SPI1->DATA = code;
  136. for(i=0;i<4;i++){
  137. while(M0P_SPI1->STAT_f.TXE==0x0u){
  138. // loop wait until tx buffer is empty
  139. }
  140. M0P_SPI1->DATA = 0x00;
  141. // __asm volatile("nop"); // adding "NOP" maybe decrease checking TXFE rounds
  142. // __asm volatile("nop");
  143. // __asm volatile("nop");
  144. }
  145. while(M0P_DMAC->CONFA0 & (0x1u<<31)){
  146. // wait until DMA ch0 full done
  147. }
  148. // disable DMAR of SPI
  149. M0P_SPI1->CR2 = TDC_SPI_CR2_BSC;
  150. data = tdc_spi_rbuf[1];
  151. data = data<<8;
  152. data |= tdc_spi_rbuf[2];
  153. data = data<<8;
  154. data |= tdc_spi_rbuf[3];
  155. data = data<<8;
  156. data |= tdc_spi_rbuf[4];
  157. // deassert CSN
  158. M0P_SPI1->SSN = 1; // 0:SPI_CS low; 1:SPI_CS high
  159. return(data);
  160. }
  161. uint16_t tdc_spi_rd_d16(uint8_t code)
  162. {
  163. uint8_t i;
  164. uint16_t data;
  165. // assert CSN
  166. M0P_SPI1->SSN = 0; // 0:SPI_CS low; 1:SPI_CS high
  167. // enable DMAR of SPI
  168. M0P_SPI1->CR2 = TDC_SPI_CR2_BSC |
  169. (1<<3); // HDMARX, hard DMA RX 0:off; 1:on;
  170. // reload DSTADR because INC
  171. M0P_DMAC->DSTADR0 = (uint32_t)&(tdc_spi_rbuf[0]);
  172. // enable DMA channel
  173. M0P_DMAC->CONFA0 = TDC_DMA_CONFA_BSC |
  174. (1u<<31) | /* ENS, 0:CHx off; 1:CHx on; */
  175. ((3-1)<<0); /* TC = Len - 1, close DAM after (TC+1)*(BC+1) */
  176. M0P_SPI1->DATA = code; // more faster, if send one byte before start DMA enable
  177. for(i=0;i<2;i++){
  178. while(M0P_SPI1->STAT_f.TXE==0x0u){
  179. // loop wait until tx buffer is empty
  180. }
  181. M0P_SPI1->DATA = 0x00;
  182. // __asm volatile("nop"); // adding "NOP" maybe decrease checking TXFE rounds
  183. // __asm volatile("nop");
  184. // __asm volatile("nop");
  185. }
  186. while(M0P_DMAC->CONFA0 & (0x1u<<31)){
  187. // wait until DMA ch0 full done
  188. }
  189. // disable DMAR of SPI
  190. M0P_SPI1->CR2 = TDC_SPI_CR2_BSC;
  191. data = tdc_spi_rbuf[1];
  192. data = data<<8;
  193. data |= tdc_spi_rbuf[2];
  194. // deassert CSN
  195. M0P_SPI1->SSN = 1; // 0:SPI_CS low; 1:SPI_CS high
  196. return(data);
  197. }
  198. //uint16_t tdc_spi_rd_d16(uint8_t code)
  199. //{
  200. // uint16_t data;
  201. //
  202. // // assert CSN
  203. // M0P_SPI1->SSN = 0; // 0:SPI_CS low; 1:SPI_CS high
  204. //
  205. // M0P_SPI1->DATA = code; // more faster, if send one byte before start DMA enable
  206. //
  207. // while(M0P_SPI1->STAT_f.TXE==0x0u){
  208. // // loop wait until tx buffer is empty
  209. // }
  210. // M0P_SPI1->DATA = 0x00;
  211. //
  212. // while(M0P_SPI1->STAT_f.TXE==0x0u){
  213. // // loop wait until tx buffer is empty
  214. // }
  215. // while(M0P_SPI1->STAT_f.BUSY){
  216. // // loop wait until not busy
  217. // }
  218. // data = M0P_SPI1->DATA;
  219. //
  220. // M0P_SPI1->DATA = 0x00;
  221. //
  222. // while(M0P_SPI1->STAT_f.TXE==0x0u){
  223. // // loop wait until tx buffer is empty
  224. // }
  225. // while(M0P_SPI1->STAT_f.BUSY){
  226. // // loop wait until not busy
  227. // }
  228. // data <<= 8;
  229. // data |= M0P_SPI1->DATA & 0xFF;
  230. //
  231. // // deassert CSN
  232. // M0P_SPI1->SSN = 1; // 0:SPI_CS low; 1:SPI_CS high
  233. //
  234. // return(data);
  235. //}
  236. uint8_t tdc_spi_rd_d8(uint8_t code)
  237. {
  238. uint8_t data;
  239. // assert CSN
  240. M0P_SPI1->SSN = 0; // 0:SPI_CS low; 1:SPI_CS high
  241. M0P_SPI1->DATA = code; // more faster, if send one byte before start DMA enable
  242. while(M0P_SPI1->STAT_f.TXE==0x0u){
  243. // loop wait until tx buffer is empty
  244. }
  245. M0P_SPI1->DATA = 0x00;
  246. while(M0P_SPI1->STAT_f.TXE==0x0u){
  247. // loop wait until tx buffer is empty
  248. }
  249. while(M0P_SPI1->STAT_f.BUSY){
  250. // loop wait until not busy
  251. }
  252. data = M0P_SPI1->DATA;
  253. // deassert CSN
  254. M0P_SPI1->SSN = 1; // 0:SPI_CS low; 1:SPI_CS high
  255. return(data);
  256. }