1 | #include "spi.h"
|
2 | #include "hw_config.h"
|
3 | #include "myassert.h"
|
4 | #include "nstdlib.h"
|
5 | #include "wallclock.h"
|
6 |
|
7 |
|
8 | /** Auswahl SPI, Ports und Pins */
|
9 | enum spi_hard_e
|
10 | {
|
11 | spi_hard_STM32F4XX_SPI1_PA5_PA6_PA7,
|
12 | spi_hard_STM32F4XX_SPI2_PB13_PB14_PB15,
|
13 | spi_hard_STM32F4XX_SPI3_PC10_PC11_PC12,
|
14 | };
|
15 |
|
16 |
|
17 | /* In hw_config.h : */
|
18 | #define SPI_HARD spi_hard_STM32F4XX_SPI1_PA5_PA6_PA7
|
19 | //#define SPI_HARD spi_hard_STM32F4XX_SPI3_PC10_PC11_PC12
|
20 |
|
21 |
|
22 | #if defined( STM32F4XX )
|
23 |
|
24 | #include "stm32f4xx_rcc.h"
|
25 | #include "stm32f4xx_spi.h"
|
26 |
|
27 |
|
28 | /** Globale Variablen *************************************************************************/
|
29 | /* - */
|
30 |
|
31 |
|
32 |
|
33 | /** Hardware-SPI fuer schnelle Anwendungen (z.B. GLCD)
|
34 | - duplex mode (RM0390 S. 850f.)
|
35 | - Steigende Flanke, Zweite Flanke -> CPHA=0, CPOL=0
|
36 | */
|
37 | void spi_hard_init(void)
|
38 | {
|
39 | SPI_InitTypeDef SPI_InitStructure;
|
40 | SPI_TypeDef* SPIx;
|
41 | GPIO_InitTypeDef GPIO_InitStructure;
|
42 | GPIO_TypeDef *SCK_GPIOx, *MISO_GPIOx, *MOSI_GPIOx;
|
43 | uint32_t SCK_Pin_x, MISO_Pin_x, MOSI_Pin_x;
|
44 | uint8_t SPIx_IRQn;
|
45 |
|
46 |
|
47 | switch( SPI_HARD )
|
48 | {
|
49 | case spi_hard_STM32F4XX_SPI1_PA5_PA6_PA7:
|
50 | /* Enable the SPI clock */
|
51 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
|
52 |
|
53 | SCK_GPIOx = GPIOA;
|
54 | SCK_Pin_x = GPIO_Pin_5;
|
55 | MISO_GPIOx = GPIOA;
|
56 | MISO_Pin_x = GPIO_Pin_6;
|
57 | MOSI_GPIOx = GPIOA;
|
58 | MOSI_Pin_x = GPIO_Pin_7;
|
59 |
|
60 | SPIx = SPI1;
|
61 | SPIx_IRQn = SPI1_IRQn;
|
62 |
|
63 | /* Connect SPI pins to AF5 */
|
64 | GPIO_PinAFConfig(SCK_GPIOx, GPIO_PinSource5, GPIO_AF_SPI1);
|
65 | GPIO_PinAFConfig(MISO_GPIOx, GPIO_PinSource6, GPIO_AF_SPI1);
|
66 | GPIO_PinAFConfig(MOSI_GPIOx, GPIO_PinSource7, GPIO_AF_SPI1);
|
67 |
|
68 | break;
|
69 |
|
70 | case spi_hard_STM32F4XX_SPI2_PB13_PB14_PB15:
|
71 | /* ungetestet */
|
72 |
|
73 | /* Enable the SPI clock */
|
74 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
|
75 |
|
76 | SCK_GPIOx = GPIOB;
|
77 | SCK_Pin_x = GPIO_Pin_13;
|
78 | MISO_GPIOx = GPIOB;
|
79 | MISO_Pin_x = GPIO_Pin_14;
|
80 | MOSI_GPIOx = GPIOB;
|
81 | MOSI_Pin_x = GPIO_Pin_15;
|
82 |
|
83 | SPIx = SPI2;
|
84 | SPIx_IRQn = SPI2_IRQn;
|
85 |
|
86 | /* Connect SPI pins to AF5 */
|
87 | GPIO_PinAFConfig(SCK_GPIOx, GPIO_PinSource13, GPIO_AF_SPI2);
|
88 | GPIO_PinAFConfig(MISO_GPIOx, GPIO_PinSource14, GPIO_AF_SPI2);
|
89 | GPIO_PinAFConfig(MOSI_GPIOx, GPIO_PinSource15, GPIO_AF_SPI2);
|
90 |
|
91 | break;
|
92 |
|
93 | case spi_hard_STM32F4XX_SPI3_PC10_PC11_PC12:
|
94 |
|
95 | /* Enable the SPI clock */
|
96 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
|
97 |
|
98 | SCK_GPIOx = GPIOC;
|
99 | SCK_Pin_x = GPIO_Pin_10;
|
100 | MISO_GPIOx = GPIOC;
|
101 | MISO_Pin_x = GPIO_Pin_11;
|
102 | MOSI_GPIOx = GPIOC;
|
103 | MOSI_Pin_x = GPIO_Pin_12;
|
104 |
|
105 | SPIx = SPI3;
|
106 | SPIx_IRQn = SPI3_IRQn;
|
107 |
|
108 | /* Connect SPI pins to AF 6 */
|
109 | GPIO_PinAFConfig(SCK_GPIOx, GPIO_PinSource10, GPIO_AF_SPI3);
|
110 | GPIO_PinAFConfig(MISO_GPIOx, GPIO_PinSource11, GPIO_AF_SPI3);
|
111 | GPIO_PinAFConfig(MOSI_GPIOx, GPIO_PinSource12, GPIO_AF_SPI3);
|
112 |
|
113 | break;
|
114 | default:
|
115 | error("Not implemented for other SPI");
|
116 | }
|
117 |
|
118 |
|
119 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
|
120 | GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
121 | GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
|
122 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
|
123 |
|
124 | /* SPI SCK pin configuration */
|
125 | GPIO_InitStructure.GPIO_Pin = SCK_Pin_x;
|
126 | GPIO_Init(SCK_GPIOx, &GPIO_InitStructure);
|
127 |
|
128 | /* SPI MISO pin configuration */
|
129 | GPIO_InitStructure.GPIO_Pin = MISO_Pin_x;
|
130 | GPIO_Init(MISO_GPIOx, &GPIO_InitStructure);
|
131 |
|
132 | /* SPI MISO pin configuration */
|
133 | GPIO_InitStructure.GPIO_Pin = MOSI_Pin_x;
|
134 | GPIO_Init(MOSI_GPIOx, &GPIO_InitStructure);
|
135 |
|
136 | SPI_I2S_DeInit(SPIx);
|
137 |
|
138 | /* SPI configuration */
|
139 | /* SPIx->CR1 RXONLY */
|
140 | /* SPIx->CR1.SSI=0 (active low) */
|
141 | SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
|
142 | SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
|
143 | SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
|
144 | SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
|
145 | SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
|
146 | SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; /* spaeter noch anpassen */
|
147 | SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
|
148 | SPI_InitStructure.SPI_CRCPolynomial = 7; /* unnoetig */
|
149 | SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
|
150 | SPI_Init(SPIx, &SPI_InitStructure);
|
151 |
|
152 |
|
153 | /* DMA Configuration - vorerst nur nur fuer SPI1 */
|
154 | /* DMA1 Clock */
|
155 | assert( SPIx == SPI1 );
|
156 | RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
|
157 |
|
158 | DMA_InitTypeDef DMA_InitStruct;
|
159 | DMA_StructInit(&DMA_InitStruct);
|
160 | DMA_InitStruct.DMA_Channel = DMA_Channel_3;
|
161 | DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR);
|
162 | DMA_InitStruct.DMA_Memory0BaseAddr = 0;
|
163 | DMA_InitStruct.DMA_BufferSize = 0;
|
164 | DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
165 | DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
166 | DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
167 | DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
168 | DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
169 | DMA_InitStruct.DMA_Mode = DMA_Mode_Normal;
|
170 | DMA_InitStruct.DMA_Priority = DMA_Priority_Medium;
|
171 | DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable;
|
172 | DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
|
173 | DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
174 | DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
175 | DMA_Init(DMA2_Stream3, &DMA_InitStruct);
|
176 |
|
177 | /* DMA-Interrupt wird erst behandelt, wenn Chip Select implementiert wird*/
|
178 | //DMA_ITConfig(DMA1_Stream6, DMA_IT_TC, ENABLE);
|
179 | DMA_Cmd(DMA2_Stream3, ENABLE);
|
180 |
|
181 |
|
182 | /* Configure the SPI interrupt priority */
|
183 | /* Interrupts 0, 1, 2 sind anderweitig belegt und werden auch aufgerufen */
|
184 | /*NVIC_SetPriority(SPIx_IRQn, 4); */
|
185 | /*NVIC_EnableIRQ(SPIx_IRQn); */
|
186 |
|
187 |
|
188 | /* Enable the Rx buffer not empty interrupt */
|
189 | /* SPI2->CR2 RXNEIE Bit wird gesetzt */
|
190 | SPI_I2S_ITConfig(SPIx, SPI_I2S_IT_RXNE, DISABLE);
|
191 |
|
192 |
|
193 | /* Enable the SPI peripheral */
|
194 | SPI_Cmd(SPIx, ENABLE);
|
195 | }
|
196 |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 | /** Abschalten
|
202 | *
|
203 | * @note Keine komplette Deinitialisierung noetig, sleep modi werden nicht benutzt */
|
204 | void spi_hard_deinit(void)
|
205 | {
|
206 | SPI_TypeDef* SPIx;
|
207 | switch( SPI_HARD )
|
208 | {
|
209 | case spi_hard_STM32F4XX_SPI1_PA5_PA6_PA7:
|
210 | SPIx = SPI1;
|
211 |
|
212 | case spi_hard_STM32F4XX_SPI2_PB13_PB14_PB15:
|
213 | SPIx = SPI2;
|
214 | break;
|
215 |
|
216 | case spi_hard_STM32F4XX_SPI3_PC10_PC11_PC12:
|
217 | SPIx = SPI3;
|
218 | break;
|
219 | }
|
220 | SPI_Cmd(SPIx, DISABLE);
|
221 | }
|
222 |
|
223 |
|
224 |
|
225 |
|
226 | /** Einzelnes Byte ueber SPI senden, nichts empfangen, MSB first */
|
227 | uint8_t spi_hard_sendbyte(uint8_t byte)
|
228 | {
|
229 | uint8_t in = 0;
|
230 |
|
231 | SPI_TypeDef* SPIx;
|
232 | switch( SPI_HARD )
|
233 | {
|
234 | case spi_hard_STM32F4XX_SPI1_PA5_PA6_PA7:
|
235 | SPIx = SPI1;
|
236 | break;
|
237 |
|
238 | case spi_hard_STM32F4XX_SPI2_PB13_PB14_PB15:
|
239 | SPIx = SPI2;
|
240 | break;
|
241 |
|
242 | case spi_hard_STM32F4XX_SPI3_PC10_PC11_PC12:
|
243 | SPIx = SPI3;
|
244 | break;
|
245 | }
|
246 |
|
247 | /*!< Loop while DR register in not empty */
|
248 | while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
|
249 |
|
250 | /*!< Send byte through the SPI1 peripheral */
|
251 | SPI_I2S_SendData(SPIx, byte);
|
252 |
|
253 | /*!< Wait to receive a byte */
|
254 | while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == RESET);
|
255 |
|
256 | /*!< Return the byte read from the SPI bus */
|
257 | in = SPI_I2S_ReceiveData(SPIx);
|
258 |
|
259 | return in;
|
260 | }
|
261 |
|
262 |
|
263 |
|
264 | /** Daten per DMA senden - bleibt immer stecken*/
|
265 | void spi_hard_senddma(uint8_t *data, size_t len)
|
266 | {
|
267 | static uint32_t cnt = 0;
|
268 | cnt++;
|
269 |
|
270 | DMA_Stream_TypeDef* DMAy_Streamx = DMA2_Stream3;
|
271 |
|
272 | /* Warten bis vorheriger Transfer abgeschlossen */
|
273 | while( DMAy_Streamx->NDTR != 0 );
|
274 |
|
275 | DMA_Cmd(DMAy_Streamx, DISABLE);
|
276 | //DMA_ITConfig(DMAy_Streamx, DMA_IT_TC, DISABLE);
|
277 |
|
278 | /* Neuen Block fuers Senden vorbereiten */
|
279 | DMAy_Streamx->M0AR = (uint32_t) data;
|
280 | DMA_SetCurrDataCounter(DMAy_Streamx, len);
|
281 |
|
282 | if( len )
|
283 | {
|
284 | //DMA_ITConfig(DMAy_Streamx, DMA_IT_TC, ENABLE);
|
285 | DMA_Cmd(DMAy_Streamx, ENABLE);
|
286 | }
|
287 | }
|