dvk_spi.c 9.6 KB

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