1 /*****************************************************************************
2 * Copyright (c) 2019, Nations Technologies Inc.
3 *
4 * All rights reserved.
5 * ****************************************************************************
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the disclaimer below.
12 *
13 * Nations' name may not be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
19 * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
22 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * ****************************************************************************/
27
28 /**
29 * @file n32wb452_spi.c
30 * @author Nations
31 * @version v1.0.0
32 *
33 * @copyright Copyright (c) 2019, Nations Technologies Inc. All rights reserved.
34 */
35 #include "n32wb452_spi.h"
36 #include "n32wb452_rcc.h"
37
38 /** @addtogroup N32WB452_StdPeriph_Driver
39 * @{
40 */
41
42 /** @addtogroup SPI
43 * @brief SPI driver modules
44 * @{
45 */
46
47 /** @addtogroup SPI_Private_TypesDefinitions
48 * @{
49 */
50
51 /**
52 * @}
53 */
54
55 /** @addtogroup SPI_Private_Defines
56 * @{
57 */
58
59 /* SPI SPE mask */
60 #define CTRL1_SPIEN_ENABLE ((uint16_t)0x0040)
61 #define CTRL1_SPIEN_DISABLE ((uint16_t)0xFFBF)
62
63 /* I2S I2SE mask */
64 #define I2SCFG_I2SEN_ENABLE ((uint16_t)0x0400)
65 #define I2SCFG_I2SEN_DISABLE ((uint16_t)0xFBFF)
66
67 /* SPI CRCNext mask */
68 #define CTRL1_CRCNEXT_ENABLE ((uint16_t)0x1000)
69
70 /* SPI CRCEN mask */
71 #define CTRL1_CRCEN_ENABLE ((uint16_t)0x2000)
72 #define CTRL1_CRCEN_DISABLE ((uint16_t)0xDFFF)
73
74 /* SPI SSOE mask */
75 #define CTRL2_SSOEN_ENABLE ((uint16_t)0x0004)
76 #define CTRL2_SSOEN_DISABLE ((uint16_t)0xFFFB)
77
78 /* SPI registers Masks */
79 #define CTRL1_CLR_MASK ((uint16_t)0x3040)
80 #define I2SCFG_CLR_MASK ((uint16_t)0xF040)
81
82 /* SPI or I2S mode selection masks */
83 #define SPI_MODE_ENABLE ((uint16_t)0xF7FF)
84 #define I2S_MODE_ENABLE ((uint16_t)0x0800)
85
86 /* I2S clock source selection masks */
87 #define I2S2_CLKSRC ((uint32_t)(0x00020000))
88 #define I2S3_CLKSRC ((uint32_t)(0x00040000))
89 #define I2S_MUL_MASK ((uint32_t)(0x0000F000))
90 #define I2S_DIV_MASK ((uint32_t)(0x000000F0))
91
92 /**
93 * @}
94 */
95
96 /** @addtogroup SPI_Private_Macros
97 * @{
98 */
99
100 /**
101 * @}
102 */
103
104 /** @addtogroup SPI_Private_Variables
105 * @{
106 */
107
108 /**
109 * @}
110 */
111
112 /** @addtogroup SPI_Private_FunctionPrototypes
113 * @{
114 */
115
116 /**
117 * @}
118 */
119
120 /** @addtogroup SPI_Private_Functions
121 * @{
122 */
123
124 /**
125 * @brief Deinitializes the SPIx peripheral registers to their default
126 * reset values (Affects also the I2Ss).
127 * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral.
128 */
SPI_I2S_DeInit(SPI_Module * SPIx)129 void SPI_I2S_DeInit(SPI_Module* SPIx)
130 {
131 /* Check the parameters */
132 assert_param(IS_SPI_PERIPH(SPIx));
133
134 if (SPIx == SPI1)
135 {
136 /* Enable SPI1 reset state */
137 RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_SPI1, ENABLE);
138 /* Release SPI1 from reset state */
139 RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_SPI1, DISABLE);
140 }
141 else if (SPIx == SPI2)
142 {
143 /* Enable SPI2 reset state */
144 RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_SPI2, ENABLE);
145 /* Release SPI2 from reset state */
146 RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_SPI2, DISABLE);
147 }
148 else
149 {
150 if (SPIx == SPI3)
151 {
152 /* Enable SPI3 reset state */
153 RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_SPI3, ENABLE);
154 /* Release SPI3 from reset state */
155 RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_SPI3, DISABLE);
156 }
157 }
158 }
159
160 /**
161 * @brief Initializes the SPIx peripheral according to the specified
162 * parameters in the SPI_InitStruct.
163 * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral.
164 * @param SPI_InitStruct pointer to a SPI_InitType structure that
165 * contains the configuration information for the specified SPI peripheral.
166 */
SPI_Init(SPI_Module * SPIx,SPI_InitType * SPI_InitStruct)167 void SPI_Init(SPI_Module* SPIx, SPI_InitType* SPI_InitStruct)
168 {
169 uint16_t tmpregister = 0;
170
171 /* check the parameters */
172 assert_param(IS_SPI_PERIPH(SPIx));
173
174 /* Check the SPI parameters */
175 assert_param(IS_SPI_DIR_MODE(SPI_InitStruct->DataDirection));
176 assert_param(IS_SPI_MODE(SPI_InitStruct->SpiMode));
177 assert_param(IS_SPI_DATASIZE(SPI_InitStruct->DataLen));
178 assert_param(IS_SPI_CLKPOL(SPI_InitStruct->CLKPOL));
179 assert_param(IS_SPI_CLKPHA(SPI_InitStruct->CLKPHA));
180 assert_param(IS_SPI_NSS(SPI_InitStruct->NSS));
181 assert_param(IS_SPI_BR_PRESCALER(SPI_InitStruct->BaudRatePres));
182 assert_param(IS_SPI_FIRST_BIT(SPI_InitStruct->FirstBit));
183 assert_param(IS_SPI_CRC_POLYNOMIAL(SPI_InitStruct->CRCPoly));
184
185 /*---------------------------- SPIx CTRL1 Configuration ------------------------*/
186 /* Get the SPIx CTRL1 value */
187 tmpregister = SPIx->CTRL1;
188 /* Clear BIDIMode, BIDIOE, RxONLY, SSM, SSI, LSBFirst, BR, MSTR, CPOL and CPHA bits */
189 tmpregister &= CTRL1_CLR_MASK;
190 /* Configure SPIx: direction, NSS management, first transmitted bit, BaudRate prescaler
191 master/salve mode, CPOL and CPHA */
192 /* Set BIDImode, BIDIOE and RxONLY bits according to DataDirection value */
193 /* Set SSM, SSI and MSTR bits according to SpiMode and NSS values */
194 /* Set LSBFirst bit according to FirstBit value */
195 /* Set BR bits according to BaudRatePres value */
196 /* Set CPOL bit according to CLKPOL value */
197 /* Set CPHA bit according to CLKPHA value */
198 tmpregister |= (uint16_t)((uint32_t)SPI_InitStruct->DataDirection | SPI_InitStruct->SpiMode
199 | SPI_InitStruct->DataLen | SPI_InitStruct->CLKPOL | SPI_InitStruct->CLKPHA
200 | SPI_InitStruct->NSS | SPI_InitStruct->BaudRatePres | SPI_InitStruct->FirstBit);
201 /* Write to SPIx CTRL1 */
202 SPIx->CTRL1 = tmpregister;
203
204 /* Activate the SPI mode (Reset I2SMOD bit in I2SCFG register) */
205 SPIx->I2SCFG &= SPI_MODE_ENABLE;
206
207 /*---------------------------- SPIx CRCPOLY Configuration --------------------*/
208 /* Write to SPIx CRCPOLY */
209 SPIx->CRCPOLY = SPI_InitStruct->CRCPoly;
210 }
211
212 /**
213 * @brief Initializes the SPIx peripheral according to the specified
214 * parameters in the I2S_InitStruct.
215 * @param SPIx where x can be 2 or 3 to select the SPI peripheral
216 * (configured in I2S mode).
217 * @param I2S_InitStruct pointer to an I2S_InitType structure that
218 * contains the configuration information for the specified SPI peripheral
219 * configured in I2S mode.
220 * @note
221 * The function calculates the optimal prescaler needed to obtain the most
222 * accurate audio frequency (depending on the I2S clock source, the PLL values
223 * and the product configuration). But in case the prescaler value is greater
224 * than 511, the default value (0x02) will be configured instead. *
225 */
I2S_Init(SPI_Module * SPIx,I2S_InitType * I2S_InitStruct)226 void I2S_Init(SPI_Module* SPIx, I2S_InitType* I2S_InitStruct)
227 {
228 uint16_t tmpregister = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1;
229 uint32_t tmp = 0;
230 RCC_ClocksType RCC_Clocks;
231 uint32_t sourceclock = 0;
232
233 /* Check the I2S parameters */
234 assert_param(IS_SPI_2OR3_PERIPH(SPIx));
235 assert_param(IS_I2S_MODE(I2S_InitStruct->I2sMode));
236 assert_param(IS_I2S_STANDARD(I2S_InitStruct->Standard));
237 assert_param(IS_I2S_DATA_FMT(I2S_InitStruct->DataFormat));
238 assert_param(IS_I2S_MCLK_ENABLE(I2S_InitStruct->MCLKEnable));
239 assert_param(IS_I2S_AUDIO_FREQ(I2S_InitStruct->AudioFrequency));
240 assert_param(IS_I2S_CLKPOL(I2S_InitStruct->CLKPOL));
241
242 /*----------------------- SPIx I2SCFG & I2SPREDIV Configuration -----------------*/
243 /* Clear I2SMOD, I2SE, MODCFG, PCMSYNC, STDSEL, CKPOL, TDATLEN and CHLEN bits */
244 SPIx->I2SCFG &= I2SCFG_CLR_MASK;
245 SPIx->I2SPREDIV = 0x0002;
246
247 /* Get the I2SCFG register value */
248 tmpregister = SPIx->I2SCFG;
249
250 /* If the default value has to be written, reinitialize i2sdiv and i2sodd*/
251 if (I2S_InitStruct->AudioFrequency == I2S_AUDIO_FREQ_DEFAULT)
252 {
253 i2sodd = (uint16_t)0;
254 i2sdiv = (uint16_t)2;
255 }
256 /* If the requested audio frequency is not the default, compute the prescaler */
257 else
258 {
259 /* Check the frame length (For the Prescaler computing) */
260 if (I2S_InitStruct->DataFormat == I2S_DATA_FMT_16BITS)
261 {
262 /* Packet length is 16 bits */
263 packetlength = 1;
264 }
265 else
266 {
267 /* Packet length is 32 bits */
268 packetlength = 2;
269 }
270
271 /* Get the I2S clock source mask depending on the peripheral number */
272 if (((uint32_t)SPIx) == SPI2_BASE)
273 {
274 /* The mask is relative to I2S2 */
275 tmp = I2S2_CLKSRC;
276 }
277 else
278 {
279 /* The mask is relative to I2S3 */
280 tmp = I2S3_CLKSRC;
281 }
282
283 /* I2S Clock source is System clock: Get System Clock frequency */
284 RCC_GetClocksFreqValue(&RCC_Clocks);
285
286 /* Get the source clock value: based on System Clock value */
287 sourceclock = RCC_Clocks.SysclkFreq;
288
289 /* Compute the Real divider depending on the MCLK output state with a floating point */
290 if (I2S_InitStruct->MCLKEnable == I2S_MCLK_ENABLE)
291 {
292 /* MCLK output is enabled */
293 tmp = (uint16_t)(((((sourceclock / 256) * 10) / I2S_InitStruct->AudioFrequency)) + 5);
294 }
295 else
296 {
297 /* MCLK output is disabled */
298 tmp = (uint16_t)(((((sourceclock / (32 * packetlength)) * 10) / I2S_InitStruct->AudioFrequency)) + 5);
299 }
300
301 /* Remove the floating point */
302 tmp = tmp / 10;
303
304 /* Check the parity of the divider */
305 i2sodd = (uint16_t)(tmp & (uint16_t)0x0001);
306
307 /* Compute the i2sdiv prescaler */
308 i2sdiv = (uint16_t)((tmp - i2sodd) / 2);
309
310 /* Get the Mask for the Odd bit (SPI_I2SPREDIV[8]) register */
311 i2sodd = (uint16_t)(i2sodd << 8);
312 }
313
314 /* Test if the divider is 1 or 0 or greater than 0xFF */
315 if ((i2sdiv < 2) || (i2sdiv > 0xFF))
316 {
317 /* Set the default values */
318 i2sdiv = 2;
319 i2sodd = 0;
320 }
321
322 /* Write to SPIx I2SPREDIV register the computed value */
323 SPIx->I2SPREDIV = (uint16_t)(i2sdiv | (uint16_t)(i2sodd | (uint16_t)I2S_InitStruct->MCLKEnable));
324
325 /* Configure the I2S with the SPI_InitStruct values */
326 tmpregister |= (uint16_t)(
327 I2S_MODE_ENABLE
328 | (uint16_t)(I2S_InitStruct->I2sMode
329 | (uint16_t)(I2S_InitStruct->Standard
330 | (uint16_t)(I2S_InitStruct->DataFormat | (uint16_t)I2S_InitStruct->CLKPOL))));
331
332 /* Write to SPIx I2SCFG */
333 SPIx->I2SCFG = tmpregister;
334 }
335
336 /**
337 * @brief Fills each SPI_InitStruct member with its default value.
338 * @param SPI_InitStruct pointer to a SPI_InitType structure which will be initialized.
339 */
SPI_InitStruct(SPI_InitType * SPI_InitStruct)340 void SPI_InitStruct(SPI_InitType* SPI_InitStruct)
341 {
342 /*--------------- Reset SPI init structure parameters values -----------------*/
343 /* Initialize the DataDirection member */
344 SPI_InitStruct->DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
345 /* initialize the SpiMode member */
346 SPI_InitStruct->SpiMode = SPI_MODE_SLAVE;
347 /* initialize the DataLen member */
348 SPI_InitStruct->DataLen = SPI_DATA_SIZE_8BITS;
349 /* Initialize the CLKPOL member */
350 SPI_InitStruct->CLKPOL = SPI_CLKPOL_LOW;
351 /* Initialize the CLKPHA member */
352 SPI_InitStruct->CLKPHA = SPI_CLKPHA_FIRST_EDGE;
353 /* Initialize the NSS member */
354 SPI_InitStruct->NSS = SPI_NSS_HARD;
355 /* Initialize the BaudRatePres member */
356 SPI_InitStruct->BaudRatePres = SPI_BR_PRESCALER_2;
357 /* Initialize the FirstBit member */
358 SPI_InitStruct->FirstBit = SPI_FB_MSB;
359 /* Initialize the CRCPoly member */
360 SPI_InitStruct->CRCPoly = 7;
361 }
362
363 /**
364 * @brief Fills each I2S_InitStruct member with its default value.
365 * @param I2S_InitStruct pointer to a I2S_InitType structure which will be initialized.
366 */
I2S_InitStruct(I2S_InitType * I2S_InitStruct)367 void I2S_InitStruct(I2S_InitType* I2S_InitStruct)
368 {
369 /*--------------- Reset I2S init structure parameters values -----------------*/
370 /* Initialize the I2sMode member */
371 I2S_InitStruct->I2sMode = I2S_MODE_SlAVE_TX;
372
373 /* Initialize the Standard member */
374 I2S_InitStruct->Standard = I2S_STD_PHILLIPS;
375
376 /* Initialize the DataFormat member */
377 I2S_InitStruct->DataFormat = I2S_DATA_FMT_16BITS;
378
379 /* Initialize the MCLKEnable member */
380 I2S_InitStruct->MCLKEnable = I2S_MCLK_DISABLE;
381
382 /* Initialize the AudioFrequency member */
383 I2S_InitStruct->AudioFrequency = I2S_AUDIO_FREQ_DEFAULT;
384
385 /* Initialize the CLKPOL member */
386 I2S_InitStruct->CLKPOL = I2S_CLKPOL_LOW;
387 }
388
389 /**
390 * @brief Enables or disables the specified SPI peripheral.
391 * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral.
392 * @param Cmd new state of the SPIx peripheral.
393 * This parameter can be: ENABLE or DISABLE.
394 */
SPI_Enable(SPI_Module * SPIx,FunctionalState Cmd)395 void SPI_Enable(SPI_Module* SPIx, FunctionalState Cmd)
396 {
397 /* Check the parameters */
398 assert_param(IS_SPI_PERIPH(SPIx));
399 assert_param(IS_FUNCTIONAL_STATE(Cmd));
400 if (Cmd != DISABLE)
401 {
402 /* Enable the selected SPI peripheral */
403 SPIx->CTRL1 |= CTRL1_SPIEN_ENABLE;
404 }
405 else
406 {
407 /* Disable the selected SPI peripheral */
408 SPIx->CTRL1 &= CTRL1_SPIEN_DISABLE;
409 }
410 }
411
412 /**
413 * @brief Enables or disables the specified SPI peripheral (in I2S mode).
414 * @param SPIx where x can be 2 or 3 to select the SPI peripheral.
415 * @param Cmd new state of the SPIx peripheral.
416 * This parameter can be: ENABLE or DISABLE.
417 */
I2S_Enable(SPI_Module * SPIx,FunctionalState Cmd)418 void I2S_Enable(SPI_Module* SPIx, FunctionalState Cmd)
419 {
420 /* Check the parameters */
421 assert_param(IS_SPI_2OR3_PERIPH(SPIx));
422 assert_param(IS_FUNCTIONAL_STATE(Cmd));
423 if (Cmd != DISABLE)
424 {
425 /* Enable the selected SPI peripheral (in I2S mode) */
426 SPIx->I2SCFG |= I2SCFG_I2SEN_ENABLE;
427 }
428 else
429 {
430 /* Disable the selected SPI peripheral (in I2S mode) */
431 SPIx->I2SCFG &= I2SCFG_I2SEN_DISABLE;
432 }
433 }
434
435 /**
436 * @brief Enables or disables the specified SPI/I2S interrupts.
437 * @param SPIx where x can be
438 * - 1, 2 or 3 in SPI mode
439 * - 2 or 3 in I2S mode
440 * @param SPI_I2S_IT specifies the SPI/I2S interrupt source to be enabled or disabled.
441 * This parameter can be one of the following values:
442 * @arg SPI_I2S_INT_TE Tx buffer empty interrupt mask
443 * @arg SPI_I2S_INT_RNE Rx buffer not empty interrupt mask
444 * @arg SPI_I2S_INT_ERR Error interrupt mask
445 * @param Cmd new state of the specified SPI/I2S interrupt.
446 * This parameter can be: ENABLE or DISABLE.
447 */
SPI_I2S_EnableInt(SPI_Module * SPIx,uint8_t SPI_I2S_IT,FunctionalState Cmd)448 void SPI_I2S_EnableInt(SPI_Module* SPIx, uint8_t SPI_I2S_IT, FunctionalState Cmd)
449 {
450 uint16_t itpos = 0, itmask = 0;
451 /* Check the parameters */
452 assert_param(IS_SPI_PERIPH(SPIx));
453 assert_param(IS_FUNCTIONAL_STATE(Cmd));
454 assert_param(IS_SPI_I2S_CONFIG_INT(SPI_I2S_IT));
455
456 /* Get the SPI/I2S IT index */
457 itpos = SPI_I2S_IT >> 4;
458
459 /* Set the IT mask */
460 itmask = (uint16_t)1 << (uint16_t)itpos;
461
462 if (Cmd != DISABLE)
463 {
464 /* Enable the selected SPI/I2S interrupt */
465 SPIx->CTRL2 |= itmask;
466 }
467 else
468 {
469 /* Disable the selected SPI/I2S interrupt */
470 SPIx->CTRL2 &= (uint16_t)~itmask;
471 }
472 }
473
474 /**
475 * @brief Enables or disables the SPIx/I2Sx DMA interface.
476 * @param SPIx where x can be
477 * - 1, 2 or 3 in SPI mode
478 * - 2 or 3 in I2S mode
479 * @param SPI_I2S_DMAReq specifies the SPI/I2S DMA transfer request to be enabled or disabled.
480 * This parameter can be any combination of the following values:
481 * @arg SPI_I2S_DMA_TX Tx buffer DMA transfer request
482 * @arg SPI_I2S_DMA_RX Rx buffer DMA transfer request
483 * @param Cmd new state of the selected SPI/I2S DMA transfer request.
484 * This parameter can be: ENABLE or DISABLE.
485 */
SPI_I2S_EnableDma(SPI_Module * SPIx,uint16_t SPI_I2S_DMAReq,FunctionalState Cmd)486 void SPI_I2S_EnableDma(SPI_Module* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState Cmd)
487 {
488 /* Check the parameters */
489 assert_param(IS_SPI_PERIPH(SPIx));
490 assert_param(IS_FUNCTIONAL_STATE(Cmd));
491 assert_param(IS_SPI_I2S_DMA(SPI_I2S_DMAReq));
492 if (Cmd != DISABLE)
493 {
494 /* Enable the selected SPI/I2S DMA requests */
495 SPIx->CTRL2 |= SPI_I2S_DMAReq;
496 }
497 else
498 {
499 /* Disable the selected SPI/I2S DMA requests */
500 SPIx->CTRL2 &= (uint16_t)~SPI_I2S_DMAReq;
501 }
502 }
503
504 /**
505 * @brief Transmits a Data through the SPIx/I2Sx peripheral.
506 * @param SPIx where x can be
507 * - 1, 2 or 3 in SPI mode
508 * - 2 or 3 in I2S mode
509 * @param Data Data to be transmitted.
510 */
SPI_I2S_TransmitData(SPI_Module * SPIx,uint16_t Data)511 void SPI_I2S_TransmitData(SPI_Module* SPIx, uint16_t Data)
512 {
513 /* Check the parameters */
514 assert_param(IS_SPI_PERIPH(SPIx));
515
516 /* Write in the DAT register the data to be sent */
517 SPIx->DAT = Data;
518 }
519
520 /**
521 * @brief Returns the most recent received data by the SPIx/I2Sx peripheral.
522 * @param SPIx where x can be
523 * - 1, 2 or 3 in SPI mode
524 * - 2 or 3 in I2S mode
525 * @return The value of the received data.
526 */
SPI_I2S_ReceiveData(SPI_Module * SPIx)527 uint16_t SPI_I2S_ReceiveData(SPI_Module* SPIx)
528 {
529 /* Check the parameters */
530 assert_param(IS_SPI_PERIPH(SPIx));
531
532 /* Return the data in the DAT register */
533 return SPIx->DAT;
534 }
535
536 /**
537 * @brief Configures internally by software the NSS pin for the selected SPI.
538 * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral.
539 * @param SPI_NSSInternalSoft specifies the SPI NSS internal state.
540 * This parameter can be one of the following values:
541 * @arg SPI_NSS_HIGH Set NSS pin internally
542 * @arg SPI_NSS_LOW Reset NSS pin internally
543 */
SPI_SetNssLevel(SPI_Module * SPIx,uint16_t SPI_NSSInternalSoft)544 void SPI_SetNssLevel(SPI_Module* SPIx, uint16_t SPI_NSSInternalSoft)
545 {
546 /* Check the parameters */
547 assert_param(IS_SPI_PERIPH(SPIx));
548 assert_param(IS_SPI_NSS_LEVEL(SPI_NSSInternalSoft));
549 if (SPI_NSSInternalSoft != SPI_NSS_LOW)
550 {
551 /* Set NSS pin internally by software */
552 SPIx->CTRL1 |= SPI_NSS_HIGH;
553 }
554 else
555 {
556 /* Reset NSS pin internally by software */
557 SPIx->CTRL1 &= SPI_NSS_LOW;
558 }
559 }
560
561 /**
562 * @brief Enables or disables the SS output for the selected SPI.
563 * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral.
564 * @param Cmd new state of the SPIx SS output.
565 * This parameter can be: ENABLE or DISABLE.
566 */
SPI_SSOutputEnable(SPI_Module * SPIx,FunctionalState Cmd)567 void SPI_SSOutputEnable(SPI_Module* SPIx, FunctionalState Cmd)
568 {
569 /* Check the parameters */
570 assert_param(IS_SPI_PERIPH(SPIx));
571 assert_param(IS_FUNCTIONAL_STATE(Cmd));
572 if (Cmd != DISABLE)
573 {
574 /* Enable the selected SPI SS output */
575 SPIx->CTRL2 |= CTRL2_SSOEN_ENABLE;
576 }
577 else
578 {
579 /* Disable the selected SPI SS output */
580 SPIx->CTRL2 &= CTRL2_SSOEN_DISABLE;
581 }
582 }
583
584 /**
585 * @brief Configures the data size for the selected SPI.
586 * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral.
587 * @param DataLen specifies the SPI data size.
588 * This parameter can be one of the following values:
589 * @arg SPI_DATA_SIZE_16BITS Set data frame format to 16bit
590 * @arg SPI_DATA_SIZE_8BITS Set data frame format to 8bit
591 */
SPI_ConfigDataLen(SPI_Module * SPIx,uint16_t DataLen)592 void SPI_ConfigDataLen(SPI_Module* SPIx, uint16_t DataLen)
593 {
594 /* Check the parameters */
595 assert_param(IS_SPI_PERIPH(SPIx));
596 assert_param(IS_SPI_DATASIZE(DataLen));
597 /* Clear DFF bit */
598 SPIx->CTRL1 &= (uint16_t)~SPI_DATA_SIZE_16BITS;
599 /* Set new DFF bit value */
600 SPIx->CTRL1 |= DataLen;
601 }
602
603 /**
604 * @brief Transmit the SPIx CRC value.
605 * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral.
606 */
SPI_TransmitCrcNext(SPI_Module * SPIx)607 void SPI_TransmitCrcNext(SPI_Module* SPIx)
608 {
609 /* Check the parameters */
610 assert_param(IS_SPI_PERIPH(SPIx));
611
612 /* Enable the selected SPI CRC transmission */
613 SPIx->CTRL1 |= CTRL1_CRCNEXT_ENABLE;
614 }
615
616 /**
617 * @brief Enables or disables the CRC value calculation of the transferred bytes.
618 * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral.
619 * @param Cmd new state of the SPIx CRC value calculation.
620 * This parameter can be: ENABLE or DISABLE.
621 */
SPI_EnableCalculateCrc(SPI_Module * SPIx,FunctionalState Cmd)622 void SPI_EnableCalculateCrc(SPI_Module* SPIx, FunctionalState Cmd)
623 {
624 /* Check the parameters */
625 assert_param(IS_SPI_PERIPH(SPIx));
626 assert_param(IS_FUNCTIONAL_STATE(Cmd));
627 if (Cmd != DISABLE)
628 {
629 /* Enable the selected SPI CRC calculation */
630 SPIx->CTRL1 |= CTRL1_CRCEN_ENABLE;
631 }
632 else
633 {
634 /* Disable the selected SPI CRC calculation */
635 SPIx->CTRL1 &= CTRL1_CRCEN_DISABLE;
636 }
637 }
638
639 /**
640 * @brief Returns the transmit or the receive CRC register value for the specified SPI.
641 * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral.
642 * @param SPI_CRC specifies the CRC register to be read.
643 * This parameter can be one of the following values:
644 * @arg SPI_CRC_TX Selects Tx CRC register
645 * @arg SPI_CRC_RX Selects Rx CRC register
646 * @return The selected CRC register value..
647 */
SPI_GetCRCDat(SPI_Module * SPIx,uint8_t SPI_CRC)648 uint16_t SPI_GetCRCDat(SPI_Module* SPIx, uint8_t SPI_CRC)
649 {
650 uint16_t crcreg = 0;
651 /* Check the parameters */
652 assert_param(IS_SPI_PERIPH(SPIx));
653 assert_param(IS_SPI_CRC(SPI_CRC));
654 if (SPI_CRC != SPI_CRC_RX)
655 {
656 /* Get the Tx CRC register */
657 crcreg = SPIx->CRCTDAT;
658 }
659 else
660 {
661 /* Get the Rx CRC register */
662 crcreg = SPIx->CRCRDAT;
663 }
664 /* Return the selected CRC register */
665 return crcreg;
666 }
667
668 /**
669 * @brief Returns the CRC Polynomial register value for the specified SPI.
670 * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral.
671 * @return The CRC Polynomial register value.
672 */
SPI_GetCRCPoly(SPI_Module * SPIx)673 uint16_t SPI_GetCRCPoly(SPI_Module* SPIx)
674 {
675 /* Check the parameters */
676 assert_param(IS_SPI_PERIPH(SPIx));
677
678 /* Return the CRC polynomial register */
679 return SPIx->CRCPOLY;
680 }
681
682 /**
683 * @brief Selects the data transfer direction in bi-directional mode for the specified SPI.
684 * @param SPIx where x can be 1, 2 or 3 to select the SPI peripheral.
685 * @param DataDirection specifies the data transfer direction in bi-directional mode.
686 * This parameter can be one of the following values:
687 * @arg SPI_BIDIRECTION_TX Selects Tx transmission direction
688 * @arg SPI_BIDIRECTION_RX Selects Rx receive direction
689 */
SPI_ConfigBidirectionalMode(SPI_Module * SPIx,uint16_t DataDirection)690 void SPI_ConfigBidirectionalMode(SPI_Module* SPIx, uint16_t DataDirection)
691 {
692 /* Check the parameters */
693 assert_param(IS_SPI_PERIPH(SPIx));
694 assert_param(IS_SPI_BIDIRECTION(DataDirection));
695 if (DataDirection == SPI_BIDIRECTION_TX)
696 {
697 /* Set the Tx only mode */
698 SPIx->CTRL1 |= SPI_BIDIRECTION_TX;
699 }
700 else
701 {
702 /* Set the Rx only mode */
703 SPIx->CTRL1 &= SPI_BIDIRECTION_RX;
704 }
705 }
706
707 /**
708 * @brief Checks whether the specified SPI/I2S flag is set or not.
709 * @param SPIx where x can be
710 * - 1, 2 or 3 in SPI mode
711 * - 2 or 3 in I2S mode
712 * @param SPI_I2S_FLAG specifies the SPI/I2S flag to check.
713 * This parameter can be one of the following values:
714 * @arg SPI_I2S_TE_FLAG Transmit buffer empty flag.
715 * @arg SPI_I2S_RNE_FLAG Receive buffer not empty flag.
716 * @arg SPI_I2S_BUSY_FLAG Busy flag.
717 * @arg SPI_I2S_OVER_FLAG Overrun flag.
718 * @arg SPI_MODERR_FLAG Mode Fault flag.
719 * @arg SPI_CRCERR_FLAG CRC Error flag.
720 * @arg I2S_UNDER_FLAG Underrun Error flag.
721 * @arg I2S_CHSIDE_FLAG Channel Side flag.
722 * @return The new state of SPI_I2S_FLAG (SET or RESET).
723 */
SPI_I2S_GetStatus(SPI_Module * SPIx,uint16_t SPI_I2S_FLAG)724 FlagStatus SPI_I2S_GetStatus(SPI_Module* SPIx, uint16_t SPI_I2S_FLAG)
725 {
726 FlagStatus bitstatus = RESET;
727 /* Check the parameters */
728 assert_param(IS_SPI_PERIPH(SPIx));
729 assert_param(IS_SPI_I2S_GET_FLAG(SPI_I2S_FLAG));
730 /* Check the status of the specified SPI/I2S flag */
731 if ((SPIx->STS & SPI_I2S_FLAG) != (uint16_t)RESET)
732 {
733 /* SPI_I2S_FLAG is set */
734 bitstatus = SET;
735 }
736 else
737 {
738 /* SPI_I2S_FLAG is reset */
739 bitstatus = RESET;
740 }
741 /* Return the SPI_I2S_FLAG status */
742 return bitstatus;
743 }
744
745 /**
746 * @brief Clears the SPIx CRC Error (CRCERR) flag.
747 * @param SPIx where x can be
748 * - 1, 2 or 3 in SPI mode
749 * @param SPI_I2S_FLAG specifies the SPI flag to clear.
750 * This function clears only CRCERR flag.
751 * @note
752 * - OVR (OverRun error) flag is cleared by software sequence: a read
753 * operation to SPI_DAT register (SPI_I2S_ReceiveData()) followed by a read
754 * operation to SPI_STS register (SPI_I2S_GetStatus()).
755 * - UDR (UnderRun error) flag is cleared by a read operation to
756 * SPI_STS register (SPI_I2S_GetStatus()).
757 * - MODF (Mode Fault) flag is cleared by software sequence: a read/write
758 * operation to SPI_STS register (SPI_I2S_GetStatus()) followed by a
759 * write operation to SPI_CTRL1 register (SPI_Enable() to enable the SPI).
760 */
SPI_I2S_ClrCRCErrFlag(SPI_Module * SPIx,uint16_t SPI_I2S_FLAG)761 void SPI_I2S_ClrCRCErrFlag(SPI_Module* SPIx, uint16_t SPI_I2S_FLAG)
762 {
763 /* Check the parameters */
764 assert_param(IS_SPI_PERIPH(SPIx));
765 assert_param(IS_SPI_I2S_CLR_FLAG(SPI_I2S_FLAG));
766
767 /* Clear the selected SPI CRC Error (CRCERR) flag */
768 SPIx->STS = (uint16_t)~SPI_I2S_FLAG;
769 }
770
771 /**
772 * @brief Checks whether the specified SPI/I2S interrupt has occurred or not.
773 * @param SPIx where x can be
774 * - 1, 2 or 3 in SPI mode
775 * - 2 or 3 in I2S mode
776 * @param SPI_I2S_IT specifies the SPI/I2S interrupt source to check.
777 * This parameter can be one of the following values:
778 * @arg SPI_I2S_INT_TE Transmit buffer empty interrupt.
779 * @arg SPI_I2S_INT_RNE Receive buffer not empty interrupt.
780 * @arg SPI_I2S_INT_OVER Overrun interrupt.
781 * @arg SPI_INT_MODERR Mode Fault interrupt.
782 * @arg SPI_INT_CRCERR CRC Error interrupt.
783 * @arg I2S_INT_UNDER Underrun Error interrupt.
784 * @return The new state of SPI_I2S_IT (SET or RESET).
785 */
SPI_I2S_GetIntStatus(SPI_Module * SPIx,uint8_t SPI_I2S_IT)786 INTStatus SPI_I2S_GetIntStatus(SPI_Module* SPIx, uint8_t SPI_I2S_IT)
787 {
788 INTStatus bitstatus = RESET;
789 uint16_t itpos = 0, itmask = 0, enablestatus = 0;
790
791 /* Check the parameters */
792 assert_param(IS_SPI_PERIPH(SPIx));
793 assert_param(IS_SPI_I2S_GET_INT(SPI_I2S_IT));
794
795 /* Get the SPI/I2S IT index */
796 itpos = 0x01 << (SPI_I2S_IT & 0x0F);
797
798 /* Get the SPI/I2S IT mask */
799 itmask = SPI_I2S_IT >> 4;
800
801 /* Set the IT mask */
802 itmask = 0x01 << itmask;
803
804 /* Get the SPI_I2S_IT enable bit status */
805 enablestatus = (SPIx->CTRL2 & itmask);
806
807 /* Check the status of the specified SPI/I2S interrupt */
808 if (((SPIx->STS & itpos) != (uint16_t)RESET) && enablestatus)
809 {
810 /* SPI_I2S_IT is set */
811 bitstatus = SET;
812 }
813 else
814 {
815 /* SPI_I2S_IT is reset */
816 bitstatus = RESET;
817 }
818 /* Return the SPI_I2S_IT status */
819 return bitstatus;
820 }
821
822 /**
823 * @brief Clears the SPIx CRC Error (CRCERR) interrupt pending bit.
824 * @param SPIx where x can be
825 * - 1, 2 or 3 in SPI mode
826 * @param SPI_I2S_IT specifies the SPI interrupt pending bit to clear.
827 * This function clears only CRCERR interrupt pending bit.
828 * @note
829 * - OVR (OverRun Error) interrupt pending bit is cleared by software
830 * sequence: a read operation to SPI_DAT register (SPI_I2S_ReceiveData())
831 * followed by a read operation to SPI_STS register (SPI_I2S_GetIntStatus()).
832 * - UDR (UnderRun Error) interrupt pending bit is cleared by a read
833 * operation to SPI_STS register (SPI_I2S_GetIntStatus()).
834 * - MODF (Mode Fault) interrupt pending bit is cleared by software sequence:
835 * a read/write operation to SPI_STS register (SPI_I2S_GetIntStatus())
836 * followed by a write operation to SPI_CTRL1 register (SPI_Enable() to enable
837 * the SPI).
838 */
SPI_I2S_ClrITPendingBit(SPI_Module * SPIx,uint8_t SPI_I2S_IT)839 void SPI_I2S_ClrITPendingBit(SPI_Module* SPIx, uint8_t SPI_I2S_IT)
840 {
841 uint16_t itpos = 0;
842 /* Check the parameters */
843 assert_param(IS_SPI_PERIPH(SPIx));
844 assert_param(IS_SPI_I2S_CLR_INT(SPI_I2S_IT));
845
846 /* Get the SPI IT index */
847 itpos = 0x01 << (SPI_I2S_IT & 0x0F);
848
849 /* Clear the selected SPI CRC Error (CRCERR) interrupt pending bit */
850 SPIx->STS = (uint16_t)~itpos;
851 }
852 /**
853 * @}
854 */
855
856 /**
857 * @}
858 */
859
860 /**
861 * @}
862 */
863