]> git.sur5r.net Git - freertos/blob - Demo/CORTEX_EFMG890F128_IAR/bsp/dvk_spi.c
Very first demo for the Energy Micro EFM32 added.
[freertos] / Demo / CORTEX_EFMG890F128_IAR / bsp / dvk_spi.c
1 /**************************************************************************//**\r
2  * @file\r
3  * @brief SPI implementation of Board Control interface\r
4  *        This implementation use the USART2 SPI interface to control board\r
5  *        control registers. It works\r
6  * @author Energy Micro AS\r
7  * @version 1.0.1\r
8  ******************************************************************************\r
9  * @section License\r
10  * <b>(C) Copyright 2009 Energy Micro AS, http://www.energymicro.com</b>\r
11  ******************************************************************************\r
12  *\r
13  * This source code is the property of Energy Micro AS. The source and compiled\r
14  * code may only be used on Energy Micro "EFM32" microcontrollers.\r
15  *\r
16  * This copyright notice may not be removed from the source code nor changed.\r
17  *\r
18  * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no\r
19  * obligation to support this Software. Energy Micro AS is providing the\r
20  * Software "AS IS", with no express or implied warranties of any kind,\r
21  * including, but not limited to, any implied warranties of merchantability\r
22  * or fitness for any particular purpose or warranties against infringement\r
23  * of any proprietary rights of a third party.\r
24  *\r
25  * Energy Micro AS will not be liable for any consequential, incidental, or\r
26  * special damages, or any other relief, or for any claim by any third party,\r
27  * arising from your use of this Software.\r
28  *\r
29  *****************************************************************************/\r
30 \r
31 #include "efm32.h"\r
32 #include "dvk.h"\r
33 #include "dvk_bcregisters.h"\r
34 \r
35 #define clear_bit(reg, bit)    (reg &= ~(1 << bit))\r
36 \r
37 static volatile uint16_t *lastAddr = 0;\r
38 \r
39 /**************************************************************************//**\r
40  * @brief  Initializes USART2 SPI interface for access to FPGA registers\r
41  *         for board control\r
42  *****************************************************************************/\r
43 static void spiInit(void)\r
44 {\r
45   USART_TypeDef  *usart = USART2;\r
46   GPIO_TypeDef   *gpio  = GPIO;\r
47   uint32_t       clk, spidiv;\r
48   const uint32_t baudrate = 7000000;\r
49   const uint32_t div      = (2 * baudrate / 256);\r
50 \r
51   /* Configure SPI bus connect pins */\r
52   gpio->P[2].MODEH &= ~(_GPIO_P_MODEH_MODE13_MASK);\r
53   gpio->P[2].MODEH |= (GPIO_P_MODEH_MODE13_PUSHPULL);\r
54   gpio->P[2].DOUT &= ~(1UL << 13);\r
55 \r
56   /* Configure SPI pins */\r
57   gpio->P[2].MODEL &= ~(_GPIO_P_MODEL_MODE2_MASK |\r
58                         _GPIO_P_MODEL_MODE3_MASK |\r
59                         _GPIO_P_MODEL_MODE4_MASK |\r
60                         _GPIO_P_MODEL_MODE5_MASK);\r
61   gpio->P[2].MODEL |= (GPIO_P_MODEL_MODE2_PUSHPULL |\r
62                        GPIO_P_MODEL_MODE3_PUSHPULL |\r
63                        GPIO_P_MODEL_MODE4_PUSHPULL |\r
64                        GPIO_P_MODEL_MODE5_PUSHPULL);\r
65   gpio->P[2].DOUT |= (1UL << 5);\r
66 \r
67   /* Configure USART2 as SPI master with manual CS */\r
68   /* Get peripheral clock - ensure updated SystemCoreClock */\r
69   SystemCoreClockUpdate();\r
70   clk = (SystemCoreClock >> ((CMU->HFPERCLKDIV & _CMU_HFPERCLKDIV_HFPERCLKDIV_MASK) >>\r
71                              _CMU_HFPERCLKDIV_HFPERCLKDIV_SHIFT));\r
72   /* Drive spi at max 7Mhz or half clockrate if core freq < 14Mhz */\r
73   if (clk < 14000000)\r
74   {\r
75     spidiv = 0;\r
76   }\r
77   else\r
78   {\r
79     spidiv = (clk) / (div) - 256;\r
80   }\r
81 \r
82   /* Never allow higher frequency than specified, round up 1/4 div */\r
83   if (spidiv & 0x3f) spidiv += 0x40;\r
84 \r
85   usart->CLKDIV = spidiv;\r
86   usart->CTRL   = USART_CTRL_SYNC;\r
87   usart->CMD    = USART_CMD_CLEARRX | USART_CMD_CLEARTX;\r
88   usart->ROUTE  = USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_CLKPEN;\r
89   usart->CMD    = USART_CMD_MASTEREN | USART_CMD_TXEN | USART_CMD_RXEN;\r
90 }\r
91 \r
92 /**************************************************************************//**\r
93  * @brief  Disables GPIO pins and USART2 from FPGA register access\r
94  *****************************************************************************/\r
95 static void spiDisable(void)\r
96 {\r
97   USART_TypeDef *usart = USART2;\r
98   GPIO_TypeDef  *gpio  = GPIO;\r
99 \r
100   /* Disable USART2 */\r
101   usart->CTRL  = _USART_CTRL_RESETVALUE;\r
102   usart->ROUTE = _USART_ROUTE_RESETVALUE;\r
103   usart->CMD   = USART_CMD_MASTERDIS | USART_CMD_TXDIS | USART_CMD_RXDIS;\r
104 \r
105   /* Disable SPI pins */\r
106   gpio->P[2].MODEH &= ~(_GPIO_P_MODEH_MODE13_MASK);\r
107   gpio->P[2].MODEL &= ~(_GPIO_P_MODEL_MODE2_MASK |\r
108                         _GPIO_P_MODEL_MODE3_MASK |\r
109                         _GPIO_P_MODEL_MODE4_MASK |\r
110                         _GPIO_P_MODEL_MODE5_MASK);\r
111 }\r
112 \r
113 /**************************************************************************//**\r
114  * @brief  Performs USART2 SPI Transfer\r
115  *****************************************************************************/\r
116 static uint16_t spiAccess(uint8_t spiadr, uint8_t rw, uint16_t spidata)\r
117 {\r
118   USART_TypeDef *usart = USART2;\r
119   GPIO_TypeDef  *gpio  = GPIO;\r
120   uint16_t      tmp;\r
121 \r
122   clear_bit(gpio->P[2].DOUT, 5);\r
123 \r
124   /* SPI address */\r
125   usart->TXDATA = (spiadr & 0x3) | rw << 3;\r
126   while (!(usart->STATUS & USART_STATUS_TXC)) ;\r
127   tmp = (usart->RXDATA) << 0;\r
128 \r
129   /* SPI data LSB */\r
130   usart->TXDATA = spidata & 0xFF;\r
131   while (!(usart->STATUS & USART_STATUS_TXC)) ;\r
132   tmp = (usart->RXDATA);\r
133 \r
134   /* SPI data MSB */\r
135   usart->TXDATA = spidata >> 8;\r
136   while (!(usart->STATUS & USART_STATUS_TXC)) ;\r
137   tmp |= (usart->RXDATA) << 8;\r
138 \r
139   gpio->P[2].DOUT |= (1 << 5);\r
140 \r
141   return tmp;\r
142 }\r
143 \r
144 /**************************************************************************//**\r
145  * @brief  Performs USART2 SPI write to FPGA register\r
146  * @param spiadr Address of register\r
147  * @param spidata Data to write\r
148  *****************************************************************************/\r
149 static void spiWrite(uint8_t spiadr, uint16_t spidata)\r
150 {\r
151   spiAccess(spiadr, 0, spidata);\r
152 }\r
153 \r
154 /**************************************************************************//**\r
155  * @brief  Performs USART2 SPI read from FPGA register\r
156  * @param spiadr Address of register\r
157  * @param spidata Dummy data\r
158  *****************************************************************************/\r
159 static uint16_t spiRead(uint8_t spiadr, uint16_t spidata)\r
160 {\r
161   return spiAccess(spiadr, 1, spidata);\r
162 }\r
163 \r
164 /**************************************************************************//**\r
165  * @brief  Initializes DVK register access\r
166  *****************************************************************************/\r
167 void DVK_SPI_init(void)\r
168 {\r
169   uint16_t spiMagic;\r
170 \r
171   spiInit();\r
172   /* Read "board control Magic" register to verify SPI is up and running */\r
173   /*  if not FPGA is configured to be in EBI mode  */\r
174 \r
175   spiMagic = DVK_SPI_readRegister(BC_MAGIC);\r
176   if (spiMagic != BC_MAGIC_VALUE)\r
177   {\r
178     /* Development Kit is configured to use EBI mode, restart of kit required */\r
179     /* to use USART2-SPI for configuration */\r
180     spiDisable();\r
181     while (1) ;\r
182   }\r
183 }\r
184 \r
185 /**************************************************************************//**\r
186  * @brief  Disable and free up resources used by SPI board control access\r
187  *****************************************************************************/\r
188 void DVK_SPI_disable(void)\r
189 {\r
190   spiDisable();\r
191 }\r
192 \r
193 /**************************************************************************//**\r
194  * @brief  Perform read from DVK board control register\r
195  * @param  addr Address of register to read from\r
196  *****************************************************************************/\r
197 uint16_t DVK_SPI_readRegister(volatile uint16_t *addr)\r
198 {\r
199   uint16_t data;\r
200 \r
201   if (addr != lastAddr)\r
202   {\r
203     spiWrite(0x00, 0xFFFF & ((uint32_t) addr));             /*LSBs of address*/\r
204     spiWrite(0x01, 0xFF & ((uint32_t) addr >> 16));         /*MSBs of address*/\r
205     spiWrite(0x02, (0x0C000000 & (uint32_t) addr) >> 26);   /*Chip select*/\r
206   }\r
207   /* Read twice */\r
208   data     = spiRead(0x03, 0);\r
209   data     = spiRead(0x03, 0);\r
210   lastAddr = addr;\r
211   return data;\r
212 }\r
213 \r
214 /**************************************************************************//**\r
215  * @brief  Perform write to DVK board control register\r
216  * @param addr Address of register to write to\r
217  * @param data 16-bit to  write into register\r
218  *****************************************************************************/\r
219 void DVK_SPI_writeRegister(volatile uint16_t *addr, uint16_t data)\r
220 {\r
221   if (addr != lastAddr)\r
222   {\r
223     spiWrite(0x00, 0xFFFF & ((uint32_t) addr));             /*LSBs of address*/\r
224     spiWrite(0x01, 0xFF & ((uint32_t) addr >> 16));         /*MSBs of address*/\r
225     spiWrite(0x02, (0x0C000000 & (uint32_t) addr) >> 26);   /*Chip select*/\r
226   }\r
227   spiWrite(0x03, data);                                     /*Data*/\r
228   lastAddr = addr;\r
229 }\r