spi.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. */
  9. #include "LPC17xx.h" /* LPC17xx definitions */
  10. #include "spi.h"
  11. /* bit definitions for register SSPCR0. */
  12. #define SSPCR0_DSS 0
  13. #define SSPCR0_CPOL 6
  14. #define SSPCR0_CPHA 7
  15. #define SSPCR0_SCR 8
  16. /* bit definitions for register SSPCR1. */
  17. #define SSPCR1_SSE 1
  18. /* bit definitions for register SSPSR. */
  19. #define SSPSR_TFE 0
  20. #define SSPSR_TNF 1
  21. #define SSPSR_RNE 2
  22. #define SSPSR_RFF 3
  23. #define SSPSR_BSY 4
  24. /* Local functions */
  25. static uint8_t LPC17xx_SPI_SendRecvByte (uint8_t byte_s);
  26. /* Initialize the SSP0, SSP0_PCLK=CCLK=72MHz */
  27. void LPC17xx_SPI_Init (void)
  28. {
  29. uint32_t dummy;
  30. dummy = dummy; // avoid warning
  31. #if 0
  32. /* Initialize and enable the SSP0 Interface module. */
  33. LPC_SC->PCONP |= (1 << 21); /* Enable power to SSPI0 block */
  34. /* SSEL is GPIO, output set to high. */
  35. LPC_GPIO0->FIODIR |= (1<<16); /* P0.16 is output */
  36. LPC_PINCON->PINSEL1 &= ~(3<<0); /* P0.16 SSEL (used as GPIO) */
  37. LPC17xx_SPI_DeSelect (); /* set P0.16 high (SSEL inactiv) */
  38. /* SCK, MISO, MOSI are SSP pins. */
  39. LPC_PINCON->PINSEL0 &= ~(3UL<<30); /* P0.15 cleared */
  40. LPC_PINCON->PINSEL0 |= (2UL<<30); /* P0.15 SCK0 */
  41. LPC_PINCON->PINSEL1 &= ~((3<<2) | (3<<4)); /* P0.17, P0.18 cleared */
  42. LPC_PINCON->PINSEL1 |= ((2<<2) | (2<<4)); /* P0.17 MISO0, P0.18 MOSI0 */
  43. #else
  44. LPC_SC->PCONP |= (1 << 21); /* Enable power to SSPI0 block */
  45. /* SSEL is GPIO, output set to high. */
  46. LPC_GPIO1->FIODIR |= (1<<21); /* P1.21 is output */
  47. LPC_GPIO1->FIOPIN |= (1<<21); /* set P1.21 high (SSEL inact.)*/
  48. LPC_PINCON->PINSEL3 &= ~(0<<10); /* P1.21 SSEL (used as GPIO) */
  49. /* P3.26 is SD Card Power Supply Enable Pin */
  50. LPC_GPIO3->FIODIR |= (1<<26); /* P3.26 is output */
  51. LPC_GPIO3->FIOPIN &= ~(1<<26); /* set P3.26 low(enable power) */
  52. /* SCK, MISO, MOSI are SSP pins. */
  53. LPC_PINCON->PINSEL3 &= ~(3UL<<8); /* P1.20 cleared */
  54. LPC_PINCON->PINSEL3 |= (3UL<<8); /* P1.20 SCK0 */
  55. LPC_PINCON->PINSEL3 &= ~((3<<14) | (3<<16)); /* P1.23, P1.24 cleared */
  56. LPC_PINCON->PINSEL3 |= ((3<<14) | (3<<16)); /* P1.23 MISO0, P1.24 MOSI0 */
  57. #endif
  58. /* PCLK_SSP0=CCLK */
  59. LPC_SC->PCLKSEL1 &= ~(3<<10); /* PCLKSP0 = CCLK/4 (18MHz) */
  60. LPC_SC->PCLKSEL1 |= (1<<10); /* PCLKSP0 = CCLK (72MHz) */
  61. LPC_SSP0->CR0 = 0x0007; /* 8Bit, CPOL=0, CPHA=0 */
  62. LPC_SSP0->CR1 = 0x0002; /* SSP0 enable, master */
  63. LPC17xx_SPI_SetSpeed (SPI_SPEED_400kHz);
  64. /* wait for busy gone */
  65. while( LPC_SSP0->SR & ( 1 << SSPSR_BSY ) );
  66. /* drain SPI RX FIFO */
  67. while( LPC_SSP0->SR & ( 1 << SSPSR_RNE ) )
  68. {
  69. dummy = LPC_SSP0->DR;
  70. }
  71. }
  72. /* Close SSP0 */
  73. void LPC17xx_SPI_DeInit( void )
  74. {
  75. // disable SPI
  76. LPC_SSP0->CR1 = 0;
  77. #if 0
  78. // Pins to GPIO
  79. LPC_PINCON->PINSEL0 &= ~(3UL<<30);
  80. LPC_PINCON->PINSEL1 &= ~((3<<2) | (3<<4));
  81. #else
  82. LPC_PINCON->PINSEL3 &= ~(3UL<<8); /* P1.20 cleared */
  83. LPC_PINCON->PINSEL3 &= ~((3<<14) | (3<<16)); /* P1.23, P1.24 cleared */
  84. #endif
  85. // disable SSP power
  86. LPC_SC->PCONP &= ~(1 << 21);
  87. }
  88. /* Set a SSP0 clock speed to desired value. */
  89. void LPC17xx_SPI_SetSpeed (uint8_t speed)
  90. {
  91. speed &= 0xFE;
  92. if ( speed < 2 ) {
  93. speed = 2 ;
  94. }
  95. LPC_SSP0->CPSR = speed;
  96. }
  97. /* SSEL: low */
  98. void LPC17xx_SPI_Select ()
  99. {
  100. #if 0
  101. LPC_GPIO0->FIOPIN &= ~(1<<16);
  102. #else
  103. LPC_GPIO1->FIOPIN &= ~(1<<21); /* SSEL is GPIO, set to high. */
  104. #endif
  105. }
  106. /* SSEL: high */
  107. void LPC17xx_SPI_DeSelect ()
  108. {
  109. #if 0
  110. LPC_GPIO0->FIOPIN |= (1<<16);
  111. #else
  112. LPC_GPIO1->FIOPIN |= (1<<21); /* SSEL is GPIO, set to high. */
  113. #endif
  114. }
  115. /* Send one byte then recv one byte of response. */
  116. static uint8_t LPC17xx_SPI_SendRecvByte (uint8_t byte_s)
  117. {
  118. uint8_t byte_r;
  119. LPC_SSP0->DR = byte_s;
  120. while (LPC_SSP0->SR & (1 << SSPSR_BSY) /*BSY*/); /* Wait for transfer to finish */
  121. byte_r = LPC_SSP0->DR;
  122. return byte_r; /* Return received value */
  123. }
  124. /* Send one byte */
  125. void LPC17xx_SPI_SendByte (uint8_t data)
  126. {
  127. LPC17xx_SPI_SendRecvByte (data);
  128. }
  129. /* Recv one byte */
  130. uint8_t LPC17xx_SPI_RecvByte ()
  131. {
  132. return LPC17xx_SPI_SendRecvByte (0xFF);
  133. }
  134. /* Release SSP0 */
  135. void LPC17xx_SPI_Release (void)
  136. {
  137. LPC17xx_SPI_DeSelect ();
  138. LPC17xx_SPI_RecvByte ();
  139. }
  140. #if USE_FIFO
  141. /* on LPC17xx the FIFOs have 8 elements which each can hold up to 16 bits */
  142. #define FIFO_ELEM 8
  143. /* Receive btr (must be multiple of 4) bytes of data and store in buff. */
  144. void LPC17xx_SPI_RecvBlock_FIFO (uint8_t *buff, uint32_t btr)
  145. {
  146. uint32_t hwtr, startcnt, i, rec;
  147. hwtr = btr/2; /* byte number in unit of short */
  148. if ( btr < FIFO_ELEM ) {
  149. startcnt = hwtr;
  150. } else {
  151. startcnt = FIFO_ELEM;
  152. }
  153. LPC_SSP0 -> CR0 |= 0x0f; /* DSS to 16 bit */
  154. for ( i = startcnt; i; i-- ) {
  155. LPC_SSP0 -> DR = 0xffff; /* fill TX FIFO, prepare clk for receive */
  156. }
  157. do {
  158. while ( !(LPC_SSP0->SR & ( 1 << SSPSR_RNE ) ) ) {
  159. // wait for data in RX FIFO (RNE set)
  160. }
  161. rec = LPC_SSP0->DR;
  162. if ( i < ( hwtr - startcnt ) ) {
  163. LPC_SSP0->DR = 0xffff; /* fill TX FIFO, prepare clk for receive */
  164. }
  165. *buff++ = (uint8_t)(rec>>8);
  166. *buff++ = (uint8_t)(rec);
  167. i++;
  168. } while ( i < hwtr );
  169. LPC_SSP0->CR0 &= ~0x08; /* DSS to 8 bit */
  170. }
  171. /* Send 512 bytes of data block (stored in buff). */
  172. void LPC17xx_SPI_SendBlock_FIFO (const uint8_t *buff)
  173. {
  174. uint32_t cnt;
  175. uint16_t data;
  176. LPC_SSP0->CR0 |= 0x0f; /* DSS to 16 bit */
  177. /* fill the FIFO unless it is full */
  178. for ( cnt = 0; cnt < ( 512 / 2 ); cnt++ )
  179. {
  180. /* wait for TX FIFO not full (TNF) */
  181. while ( !( LPC_SSP0->SR & ( 1 << SSPSR_TNF ) ) );
  182. data = (*buff++) << 8;
  183. data |= *buff++;
  184. LPC_SSP0->DR = data;
  185. }
  186. /* wait for BSY gone */
  187. while ( LPC_SSP0->SR & ( 1 << SSPSR_BSY ) );
  188. /* drain receive FIFO */
  189. while ( LPC_SSP0->SR & ( 1 << SSPSR_RNE ) ) {
  190. data = LPC_SSP0->DR;
  191. }
  192. LPC_SSP0->CR0 &= ~0x08; /* DSS to 8 bit */
  193. }
  194. #endif /* USE_FIFO */