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