dvk_spi.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /**************************************************************************//**
  2. * @file
  3. * @brief SPI implementation of Board Control interface
  4. * This implementation use the USART2 SPI interface to control board
  5. * control registers. It works
  6. * @author Energy Micro AS
  7. * @version 1.7.3
  8. ******************************************************************************
  9. * @section License
  10. * <b>(C) Copyright 2010 Energy Micro AS, http://www.energymicro.com</b>
  11. ******************************************************************************
  12. *
  13. * This source code is the property of Energy Micro AS. The source and compiled
  14. * code may only be used on Energy Micro "EFM32" microcontrollers.
  15. *
  16. * This copyright notice may not be removed from the source code nor changed.
  17. *
  18. * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
  19. * obligation to support this Software. Energy Micro AS is providing the
  20. * Software "AS IS", with no express or implied warranties of any kind,
  21. * including, but not limited to, any implied warranties of merchantability
  22. * or fitness for any particular purpose or warranties against infringement
  23. * of any proprietary rights of a third party.
  24. *
  25. * Energy Micro AS will not be liable for any consequential, incidental, or
  26. * special damages, or any other relief, or for any claim by any third party,
  27. * arising from your use of this Software.
  28. *
  29. *****************************************************************************/
  30. /***************************************************************************//**
  31. * @addtogroup BSP
  32. * @{
  33. ******************************************************************************/
  34. #include <stdio.h>
  35. #include "efm32.h"
  36. #include "efm32_usart.h"
  37. #include "efm32_gpio.h"
  38. #include "efm32_cmu.h"
  39. #include "dvk.h"
  40. #include "dvk_bcregisters.h"
  41. #ifdef _EFM32_TINY_FAMILY
  42. /* USART used for SPI access */
  43. #define USART_USED USART0
  44. #define USART_CLK cmuClock_USART0
  45. /* GPIO pins used, please refer to DVK user guide. */
  46. #define PIN_SPIBUS_CONNECT 13
  47. #define PORT_SPIBUS_CONNECT gpioPortC
  48. #define PIN_SPI_TX 10
  49. #define PORT_SPI_TX gpioPortE
  50. #define PIN_SPI_RX 11
  51. #define PORT_SPI_RX gpioPortE
  52. #define PIN_SPI_CLK 12
  53. #define PORT_SPI_CLK gpioPortE
  54. #define PIN_SPI_CS 13
  55. #define PORT_SPI_CS gpioPortE
  56. #else
  57. /* USART used for SPI access */
  58. #define USART_USED USART2
  59. #define USART_CLK cmuClock_USART2
  60. /* GPIO pins used, please refer to DVK user guide. */
  61. #define PIN_SPIBUS_CONNECT 13
  62. #define PORT_SPIBUS_CONNECT gpioPortC
  63. #define PIN_EBIBUS_CONNECT 12
  64. #define PORT_EBIBUS_CONNECT gpioPortC
  65. #define PIN_SPI_TX 2
  66. #define PORT_SPI_TX gpioPortC
  67. #define PIN_SPI_RX 3
  68. #define PORT_SPI_RX gpioPortC
  69. #define PIN_SPI_CLK 4
  70. #define PORT_SPI_CLK gpioPortC
  71. #define PIN_SPI_CS 5
  72. #define PORT_SPI_CS gpioPortC
  73. #endif
  74. static volatile uint16_t *lastAddr = NULL;
  75. /**************************************************************************//**
  76. * @brief Initializes SPI interface for access to FPGA registers
  77. * for board control
  78. *****************************************************************************/
  79. static void spiInit(void)
  80. {
  81. USART_InitSync_TypeDef init = USART_INITSYNC_DEFAULT;
  82. /* Enable module clocks */
  83. CMU_ClockEnable(cmuClock_GPIO, true);
  84. CMU_ClockEnable(cmuClock_HFPER, true);
  85. CMU_ClockEnable(USART_CLK, true);
  86. /* Configure SPI bus connect pins, DOUT set to 0, disable EBI */
  87. GPIO_PinModeSet(PORT_SPIBUS_CONNECT, PIN_SPIBUS_CONNECT, gpioModePushPull, 0);
  88. GPIO_PinModeSet(PORT_EBIBUS_CONNECT, PIN_EBIBUS_CONNECT, gpioModePushPull, 1);
  89. /* Configure SPI pins */
  90. GPIO_PinModeSet(PORT_SPI_TX, PIN_SPI_TX, gpioModePushPull, 0);
  91. GPIO_PinModeSet(PORT_SPI_RX, PIN_SPI_RX, gpioModePushPull, 0);
  92. GPIO_PinModeSet(PORT_SPI_CLK, PIN_SPI_CLK, gpioModePushPull, 0);
  93. /* Keep CS high to not activate slave */
  94. GPIO_PinModeSet(PORT_SPI_CS, PIN_SPI_CS, gpioModePushPull, 1);
  95. /* Configure to use SPI master with manual CS */
  96. /* For now, configure SPI for worst case 32MHz clock in order to work for all */
  97. /* configurations. */
  98. init.refFreq = 32000000;
  99. init.baudrate = 7000000;
  100. USART_InitSync(USART_USED, &init);
  101. /* Enable pins at default location */
  102. USART_USED->ROUTE = USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_CLKPEN;
  103. }
  104. /**************************************************************************//**
  105. * @brief Disables GPIO pins and USART from FPGA register access
  106. *****************************************************************************/
  107. static void spiDisable(void)
  108. {
  109. USART_Reset(USART_USED);
  110. /* Disable LCD_SELECT */
  111. GPIO_PinModeSet(gpioPortD, 13, gpioModeDisabled, 0);
  112. /* Disable SPI pins */
  113. GPIO_PinModeSet(PORT_SPIBUS_CONNECT, 13, gpioModeDisabled, 0);
  114. GPIO_PinModeSet(PORT_SPIBUS_CONNECT, 12, gpioModeDisabled, 0);
  115. GPIO_PinModeSet(PORT_SPI_TX, PIN_SPI_TX, gpioModeDisabled, 0);
  116. GPIO_PinModeSet(PORT_SPI_RX, PIN_SPI_RX, gpioModeDisabled, 0);
  117. GPIO_PinModeSet(PORT_SPI_CLK, PIN_SPI_CLK, gpioModeDisabled, 0);
  118. GPIO_PinModeSet(PORT_SPI_CS, PIN_SPI_CS, gpioModeDisabled, 0);
  119. /* Disable USART clock - we can't disable GPIO or HFPER as we don't know who else
  120. * might be using it */
  121. CMU_ClockEnable(USART_CLK, false);
  122. }
  123. /**************************************************************************//**
  124. * @brief Perform SPI Transfer
  125. *****************************************************************************/
  126. static uint16_t spiAccess(uint8_t spiaddr, uint8_t rw, uint16_t spidata)
  127. {
  128. uint16_t tmp;
  129. GPIO_PinOutClear(PORT_SPI_CS, PIN_SPI_CS);
  130. /* For every byte sent, one is received */
  131. /* Write SPI address */
  132. USART_Tx(USART_USED, (spiaddr & 0x3) | rw << 3);
  133. /* Just ignore data read back */
  134. USART_Rx(USART_USED);
  135. /* SPI data LSB */
  136. USART_Tx(USART_USED, spidata & 0xFF);
  137. tmp = (uint16_t)USART_Rx(USART_USED);
  138. /* SPI data MSB */
  139. USART_Tx(USART_USED, spidata >> 8);
  140. tmp |= (uint16_t)USART_Rx(USART_USED) << 8;
  141. GPIO_PinOutSet(PORT_SPI_CS, PIN_SPI_CS);
  142. return tmp;
  143. }
  144. /**************************************************************************//**
  145. * @brief Performs SPI write to FPGA register
  146. * @param spiadr Address of register
  147. * @param spidata Data to write
  148. *****************************************************************************/
  149. static void spiWrite(uint8_t spiadr, uint16_t spidata)
  150. {
  151. spiAccess(spiadr, 0, spidata);
  152. }
  153. /**************************************************************************//**
  154. * @brief Performs SPI read from FPGA register
  155. * @param spiadr Address of register
  156. * @param spidata Dummy data
  157. *****************************************************************************/
  158. static uint16_t spiRead(uint8_t spiadr, uint16_t spidata)
  159. {
  160. return spiAccess(spiadr, 1, spidata);
  161. }
  162. /**************************************************************************//**
  163. * @brief Initializes DVK register access
  164. * @return true on success, false on failure
  165. *****************************************************************************/
  166. bool DVK_SPI_init(void)
  167. {
  168. uint16_t spiMagic;
  169. spiInit();
  170. /* Read "board control Magic" register to verify SPI is up and running */
  171. /* if not FPGA is configured to be in EBI mode */
  172. spiMagic = DVK_SPI_readRegister(BC_MAGIC);
  173. if(spiMagic != BC_MAGIC_VALUE)
  174. {
  175. return false;
  176. }
  177. else
  178. {
  179. return true;
  180. }
  181. }
  182. /**************************************************************************//**
  183. * @brief Disable and free up resources used by SPI board control access
  184. *****************************************************************************/
  185. void DVK_SPI_disable(void)
  186. {
  187. spiDisable();
  188. }
  189. /**************************************************************************//**
  190. * @brief Perform read from DVK board control register
  191. * @param addr Address of register to read from
  192. *****************************************************************************/
  193. uint16_t DVK_SPI_readRegister(volatile uint16_t *addr)
  194. {
  195. uint16_t data;
  196. if (addr != lastAddr)
  197. {
  198. spiWrite(0x00, 0xFFFF & ((uint32_t) addr)); /*LSBs of address*/
  199. spiWrite(0x01, 0xFF & ((uint32_t) addr >> 16)); /*MSBs of address*/
  200. spiWrite(0x02, (0x0C000000 & (uint32_t) addr) >> 26); /*Chip select*/
  201. }
  202. /* Read twice */
  203. data = spiRead(0x03, 0);
  204. data = spiRead(0x03, 0);
  205. lastAddr = addr;
  206. return data;
  207. }
  208. /**************************************************************************//**
  209. * @brief Perform write to DVK board control register
  210. * @param addr Address of register to write to
  211. * @param data 16-bit to write into register
  212. *****************************************************************************/
  213. void DVK_SPI_writeRegister(volatile uint16_t *addr, uint16_t data)
  214. {
  215. if (addr != lastAddr)
  216. {
  217. spiWrite(0x00, 0xFFFF & ((uint32_t) addr)); /*LSBs of address*/
  218. spiWrite(0x01, 0xFF & ((uint32_t) addr >> 16)); /*MSBs of address*/
  219. spiWrite(0x02, (0x0C000000 & (uint32_t) addr) >> 26); /*Chip select*/
  220. }
  221. spiWrite(0x03, data); /*Data*/
  222. lastAddr = addr;
  223. }
  224. /** @} (end group BSP) */