1 /*****************************************************************************
2  * Copyright (c) 2022, 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 n32g43x_spi.c
30  * @author Nations
31  * @version v1.2.0
32  *
33  * @copyright Copyright (c) 2022, Nations Technologies Inc. All rights reserved.
34  */
35 #include "n32g43x_spi.h"
36 #include "n32g43x_rcc.h"
37 
38 /** @addtogroup N32G43x_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 SPIEN mask */
60 #define CTRL1_SPIEN_ENABLE  ((uint16_t)0x0040)
61 #define CTRL1_SPIEN_DISABLE ((uint16_t)0xFFBF)
62 
63 /* I2S I2SEN 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 I2S1_CLKSRC  ((uint32_t)(0x00020000))
88 #define I2S2_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 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_EnableAPB2PeriphReset(RCC_APB2_PERIPH_SPI2, ENABLE);
145         /* Release SPI2 from reset state */
146         RCC_EnableAPB2PeriphReset(RCC_APB2_PERIPH_SPI2, DISABLE);
147     }
148 
149 }
150 
151 /**
152  * @brief  Initializes the SPIx peripheral according to the specified
153  *         parameters in the SPI_InitStruct.
154  * @param SPIx where x can be 1 or 2 to select the SPI peripheral.
155  * @param SPI_InitStruct pointer to a SPI_InitType structure that
156  *         contains the configuration information for the specified SPI peripheral.
157  */
SPI_Init(SPI_Module * SPIx,SPI_InitType * SPI_InitStruct)158 void SPI_Init(SPI_Module* SPIx, SPI_InitType* SPI_InitStruct)
159 {
160     uint16_t tmpregister = 0;
161 
162     /* check the parameters */
163     assert_param(IS_SPI_PERIPH(SPIx));
164 
165     /* Check the SPI parameters */
166     assert_param(IS_SPI_DIR_MODE(SPI_InitStruct->DataDirection));
167     assert_param(IS_SPI_MODE(SPI_InitStruct->SpiMode));
168     assert_param(IS_SPI_DATASIZE(SPI_InitStruct->DataLen));
169     assert_param(IS_SPI_CLKPOL(SPI_InitStruct->CLKPOL));
170     assert_param(IS_SPI_CLKPHA(SPI_InitStruct->CLKPHA));
171     assert_param(IS_SPI_NSS(SPI_InitStruct->NSS));
172     assert_param(IS_SPI_BR_PRESCALER(SPI_InitStruct->BaudRatePres));
173     assert_param(IS_SPI_FIRST_BIT(SPI_InitStruct->FirstBit));
174     assert_param(IS_SPI_CRC_POLYNOMIAL(SPI_InitStruct->CRCPoly));
175 
176     /*---------------------------- SPIx CTRL1 Configuration ------------------------*/
177     /* Get the SPIx CTRL1 value */
178     tmpregister = SPIx->CTRL1;
179     /* Clear BIDIMode, BIDIOE, RxONLY, SSM, SSI, LSBFirst, BR, MSTR, CPOL and CPHA bits */
180     tmpregister &= CTRL1_CLR_MASK;
181     /* Configure SPIx: direction, NSS management, first transmitted bit, BaudRate prescaler
182        master/salve mode, CPOL and CPHA */
183     /* Set BIDImode, BIDIOE and RxONLY bits according to DataDirection value */
184     /* Set SSM, SSI and MSTR bits according to SpiMode and NSS values */
185     /* Set LSBFirst bit according to FirstBit value */
186     /* Set BR bits according to BaudRatePres value */
187     /* Set CPOL bit according to CLKPOL value */
188     /* Set CPHA bit according to CLKPHA value */
189     tmpregister |= (uint16_t)((uint32_t)SPI_InitStruct->DataDirection | SPI_InitStruct->SpiMode
190                               | SPI_InitStruct->DataLen | SPI_InitStruct->CLKPOL | SPI_InitStruct->CLKPHA
191                               | SPI_InitStruct->NSS | SPI_InitStruct->BaudRatePres | SPI_InitStruct->FirstBit);
192     /* Write to SPIx CTRL1 */
193     SPIx->CTRL1 = tmpregister;
194 
195     /* Activate the SPI mode (Reset I2SMOD bit in I2SCFG register) */
196     SPIx->I2SCFG &= SPI_MODE_ENABLE;
197 
198     /*---------------------------- SPIx CRCPOLY Configuration --------------------*/
199     /* Write to SPIx CRCPOLY */
200     SPIx->CRCPOLY = SPI_InitStruct->CRCPoly;
201 }
202 
203 /**
204  * @brief  Initializes the SPIx peripheral according to the specified
205  *         parameters in the I2S_InitStruct.
206  * @param SPIx where x can be  1 or 2 to select the SPI peripheral
207  *         (configured in I2S mode).
208  * @param I2S_InitStruct pointer to an I2S_InitType structure that
209  *         contains the configuration information for the specified SPI peripheral
210  *         configured in I2S mode.
211  * @note
212  *  The function calculates the optimal prescaler needed to obtain the most
213  *  accurate audio frequency (depending on the I2S clock source, the PLL values
214  *  and the product configuration). But in case the prescaler value is greater
215  *  than 511, the default value (0x02) will be configured instead.  *
216  */
I2S_Init(SPI_Module * SPIx,I2S_InitType * I2S_InitStruct)217 void I2S_Init(SPI_Module* SPIx, I2S_InitType* I2S_InitStruct)
218 {
219     uint16_t tmpregister = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1;
220     uint32_t tmp = 0;
221     RCC_ClocksType RCC_Clocks;
222     uint32_t sourceclock = 0;
223 
224     /* Check the I2S parameters */
225     assert_param(IS_SPI_PERIPH(SPIx));
226     assert_param(IS_I2S_MODE(I2S_InitStruct->I2sMode));
227     assert_param(IS_I2S_STANDARD(I2S_InitStruct->Standard));
228     assert_param(IS_I2S_DATA_FMT(I2S_InitStruct->DataFormat));
229     assert_param(IS_I2S_MCLK_ENABLE(I2S_InitStruct->MCLKEnable));
230     assert_param(IS_I2S_AUDIO_FREQ(I2S_InitStruct->AudioFrequency));
231     assert_param(IS_I2S_CLKPOL(I2S_InitStruct->CLKPOL));
232 
233     /*----------------------- SPIx I2SCFG & I2SPREDIV Configuration -----------------*/
234     /* Clear I2SMOD, I2SE, MODCFG, PCMSYNC, STDSEL, CKPOL, TDATLEN and CHLEN bits */
235     SPIx->I2SCFG &= I2SCFG_CLR_MASK;
236     SPIx->I2SPREDIV = 0x0002;
237 
238     /* Get the I2SCFG register value */
239     tmpregister = SPIx->I2SCFG;
240 
241     /* If the default value has to be written, reinitialize i2sdiv and i2sodd*/
242     if (I2S_InitStruct->AudioFrequency == I2S_AUDIO_FREQ_DEFAULT)
243     {
244         i2sodd = (uint16_t)0;
245         i2sdiv = (uint16_t)2;
246     }
247     /* If the requested audio frequency is not the default, compute the prescaler */
248     else
249     {
250         /* Check the frame length (For the Prescaler computing) */
251         if (I2S_InitStruct->DataFormat == I2S_DATA_FMT_16BITS)
252         {
253             /* Packet length is 16 bits */
254             packetlength = 1;
255         }
256         else
257         {
258             /* Packet length is 32 bits */
259             packetlength = 2;
260         }
261 
262         /* Get the I2S clock source mask depending on the peripheral number */
263         if (((uint32_t)SPIx) == SPI2_BASE)
264         {
265             /* The mask is relative to I2S1 */
266             tmp = I2S1_CLKSRC;
267         }
268         else
269         {
270             /* The mask is relative to I2S2 */
271             tmp = I2S2_CLKSRC;
272         }
273 
274         /* I2S Clock source is System clock: Get System Clock frequency */
275         RCC_GetClocksFreqValue(&RCC_Clocks);
276 
277         /* Get the source clock value: based on System Clock value */
278         sourceclock = RCC_Clocks.SysclkFreq;
279 
280         /* Compute the Real divider depending on the MCLK output state with a floating point */
281         if (I2S_InitStruct->MCLKEnable == I2S_MCLK_ENABLE)
282         {
283             /* MCLK output is enabled */
284             tmp = (uint16_t)(((((sourceclock / 256) * 10) / I2S_InitStruct->AudioFrequency)) + 5);
285         }
286         else
287         {
288             /* MCLK output is disabled */
289             tmp = (uint16_t)(((((sourceclock / (32 * packetlength)) * 10) / I2S_InitStruct->AudioFrequency)) + 5);
290         }
291 
292         /* Remove the floating point */
293         tmp = tmp / 10;
294 
295         /* Check the parity of the divider */
296         i2sodd = (uint16_t)(tmp & (uint16_t)0x0001);
297 
298         /* Compute the i2sdiv prescaler */
299         i2sdiv = (uint16_t)((tmp - i2sodd) / 2);
300 
301         /* Get the Mask for the Odd bit (SPI_I2SPREDIV[8]) register */
302         i2sodd = (uint16_t)(i2sodd << 8);
303     }
304 
305     /* Test if the divider is 1 or 0 or greater than 0xFF */
306     if ((i2sdiv < 2) || (i2sdiv > 0xFF))
307     {
308         /* Set the default values */
309         i2sdiv = 2;
310         i2sodd = 0;
311     }
312 
313     /* Write to SPIx I2SPREDIV register the computed value */
314     SPIx->I2SPREDIV = (uint16_t)(i2sdiv | (uint16_t)(i2sodd | (uint16_t)I2S_InitStruct->MCLKEnable));
315 
316     /* Configure the I2S with the SPI_InitStruct values */
317     tmpregister |= (uint16_t)(
318         I2S_MODE_ENABLE
319         | (uint16_t)(I2S_InitStruct->I2sMode
320                      | (uint16_t)(I2S_InitStruct->Standard
321                                   | (uint16_t)(I2S_InitStruct->DataFormat | (uint16_t)I2S_InitStruct->CLKPOL))));
322 
323     /* Write to SPIx I2SCFG */
324     SPIx->I2SCFG = tmpregister;
325 }
326 
327 /**
328  * @brief  Fills each SPI_InitStruct member with its default value.
329  * @param SPI_InitStruct pointer to a SPI_InitType structure which will be initialized.
330  */
SPI_InitStruct(SPI_InitType * SPI_InitStruct)331 void SPI_InitStruct(SPI_InitType* SPI_InitStruct)
332 {
333     /*--------------- Reset SPI init structure parameters values -----------------*/
334     /* Initialize the DataDirection member */
335     SPI_InitStruct->DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX;
336     /* initialize the SpiMode member */
337     SPI_InitStruct->SpiMode = SPI_MODE_SLAVE;
338     /* initialize the DataLen member */
339     SPI_InitStruct->DataLen = SPI_DATA_SIZE_8BITS;
340     /* Initialize the CLKPOL member */
341     SPI_InitStruct->CLKPOL = SPI_CLKPOL_LOW;
342     /* Initialize the CLKPHA member */
343     SPI_InitStruct->CLKPHA = SPI_CLKPHA_FIRST_EDGE;
344     /* Initialize the NSS member */
345     SPI_InitStruct->NSS = SPI_NSS_HARD;
346     /* Initialize the BaudRatePres member */
347     SPI_InitStruct->BaudRatePres = SPI_BR_PRESCALER_2;
348     /* Initialize the FirstBit member */
349     SPI_InitStruct->FirstBit = SPI_FB_MSB;
350     /* Initialize the CRCPoly member */
351     SPI_InitStruct->CRCPoly = 7;
352 }
353 
354 /**
355  * @brief  Fills each I2S_InitStruct member with its default value.
356  * @param I2S_InitStruct pointer to a I2S_InitType structure which will be initialized.
357  */
I2S_InitStruct(I2S_InitType * I2S_InitStruct)358 void I2S_InitStruct(I2S_InitType* I2S_InitStruct)
359 {
360     /*--------------- Reset I2S init structure parameters values -----------------*/
361     /* Initialize the I2sMode member */
362     I2S_InitStruct->I2sMode = I2S_MODE_SlAVE_TX;
363 
364     /* Initialize the Standard member */
365     I2S_InitStruct->Standard = I2S_STD_PHILLIPS;
366 
367     /* Initialize the DataFormat member */
368     I2S_InitStruct->DataFormat = I2S_DATA_FMT_16BITS;
369 
370     /* Initialize the MCLKEnable member */
371     I2S_InitStruct->MCLKEnable = I2S_MCLK_DISABLE;
372 
373     /* Initialize the AudioFrequency member */
374     I2S_InitStruct->AudioFrequency = I2S_AUDIO_FREQ_DEFAULT;
375 
376     /* Initialize the CLKPOL member */
377     I2S_InitStruct->CLKPOL = I2S_CLKPOL_LOW;
378 }
379 
380 /**
381  * @brief  Enables or disables the specified SPI peripheral.
382  * @param SPIx where x can be 1 or 2 to select the SPI peripheral.
383  * @param Cmd new state of the SPIx peripheral.
384  *   This parameter can be: ENABLE or DISABLE.
385  */
SPI_Enable(SPI_Module * SPIx,FunctionalState Cmd)386 void SPI_Enable(SPI_Module* SPIx, FunctionalState Cmd)
387 {
388     /* Check the parameters */
389     assert_param(IS_SPI_PERIPH(SPIx));
390     assert_param(IS_FUNCTIONAL_STATE(Cmd));
391     if (Cmd != DISABLE)
392     {
393         /* Enable the selected SPI peripheral */
394         SPIx->CTRL1 |= CTRL1_SPIEN_ENABLE;
395     }
396     else
397     {
398         /* Disable the selected SPI peripheral */
399         SPIx->CTRL1 &= CTRL1_SPIEN_DISABLE;
400     }
401 }
402 
403 /**
404  * @brief  Enables or disables the specified SPI peripheral (in I2S mode).
405  * @param SPIx where x can be 1 or 2 to select the SPI peripheral.
406  * @param Cmd new state of the SPIx peripheral.
407  *   This parameter can be: ENABLE or DISABLE.
408  */
I2S_Enable(SPI_Module * SPIx,FunctionalState Cmd)409 void I2S_Enable(SPI_Module* SPIx, FunctionalState Cmd)
410 {
411     /* Check the parameters */
412     assert_param(IS_SPI_PERIPH(SPIx));
413     assert_param(IS_FUNCTIONAL_STATE(Cmd));
414     if (Cmd != DISABLE)
415     {
416         /* Enable the selected SPI peripheral (in I2S mode) */
417         SPIx->I2SCFG |= I2SCFG_I2SEN_ENABLE;
418     }
419     else
420     {
421         /* Disable the selected SPI peripheral (in I2S mode) */
422         SPIx->I2SCFG &= I2SCFG_I2SEN_DISABLE;
423     }
424 }
425 
426 /**
427  * @brief  Enables or disables the specified SPI/I2S interrupts.
428  * @param SPIx where x can be
429  *   - 1 or 2 in SPI mode
430  *   - 1 or 2 in I2S mode
431  * @param SPI_I2S_IT specifies the SPI/I2S interrupt source to be enabled or disabled.
432  *   This parameter can be one of the following values:
433  *     @arg SPI_I2S_INT_TE Tx buffer empty interrupt mask
434  *     @arg SPI_I2S_INT_RNE Rx buffer not empty interrupt mask
435  *     @arg SPI_I2S_INT_ERR Error interrupt mask
436  * @param Cmd new state of the specified SPI/I2S interrupt.
437  *   This parameter can be: ENABLE or DISABLE.
438  */
SPI_I2S_EnableInt(SPI_Module * SPIx,uint8_t SPI_I2S_IT,FunctionalState Cmd)439 void SPI_I2S_EnableInt(SPI_Module* SPIx, uint8_t SPI_I2S_IT, FunctionalState Cmd)
440 {
441     uint16_t itpos = 0, itmask = 0;
442     /* Check the parameters */
443     assert_param(IS_SPI_PERIPH(SPIx));
444     assert_param(IS_FUNCTIONAL_STATE(Cmd));
445     assert_param(IS_SPI_I2S_CONFIG_INT(SPI_I2S_IT));
446 
447     /* Get the SPI/I2S IT index */
448     itpos = SPI_I2S_IT >> 4;
449 
450     /* Set the IT mask */
451     itmask = (uint16_t)1 << (uint16_t)itpos;
452 
453     if (Cmd != DISABLE)
454     {
455         /* Enable the selected SPI/I2S interrupt */
456         SPIx->CTRL2 |= itmask;
457     }
458     else
459     {
460         /* Disable the selected SPI/I2S interrupt */
461         SPIx->CTRL2 &= (uint16_t)~itmask;
462     }
463 }
464 
465 /**
466  * @brief  Enables or disables the SPIx/I2Sx DMA interface.
467  * @param SPIx where x can be
468  *   - 1 or 2 in SPI mode
469  *   - 1 or 2 in I2S mode
470  * @param SPI_I2S_DMAReq specifies the SPI/I2S DMA transfer request to be enabled or disabled.
471  *   This parameter can be any combination of the following values:
472  *     @arg SPI_I2S_DMA_TX Tx buffer DMA transfer request
473  *     @arg SPI_I2S_DMA_RX Rx buffer DMA transfer request
474  * @param Cmd new state of the selected SPI/I2S DMA transfer request.
475  *   This parameter can be: ENABLE or DISABLE.
476  */
SPI_I2S_EnableDma(SPI_Module * SPIx,uint16_t SPI_I2S_DMAReq,FunctionalState Cmd)477 void SPI_I2S_EnableDma(SPI_Module* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState Cmd)
478 {
479     /* Check the parameters */
480     assert_param(IS_SPI_PERIPH(SPIx));
481     assert_param(IS_FUNCTIONAL_STATE(Cmd));
482     assert_param(IS_SPI_I2S_DMA(SPI_I2S_DMAReq));
483     if (Cmd != DISABLE)
484     {
485         /* Enable the selected SPI/I2S DMA requests */
486         SPIx->CTRL2 |= SPI_I2S_DMAReq;
487     }
488     else
489     {
490         /* Disable the selected SPI/I2S DMA requests */
491         SPIx->CTRL2 &= (uint16_t)~SPI_I2S_DMAReq;
492     }
493 }
494 
495 /**
496  * @brief  Transmits a Data through the SPIx/I2Sx peripheral.
497  * @param SPIx where x can be
498  *   - 1 or 2 in SPI mode
499  *   - 1 or 2 in I2S mode
500  * @param Data Data to be transmitted.
501  */
SPI_I2S_TransmitData(SPI_Module * SPIx,uint16_t Data)502 void SPI_I2S_TransmitData(SPI_Module* SPIx, uint16_t Data)
503 {
504     /* Check the parameters */
505     assert_param(IS_SPI_PERIPH(SPIx));
506 
507     /* Write in the DAT register the data to be sent */
508     SPIx->DAT = Data;
509 }
510 
511 /**
512  * @brief  Returns the most recent received data by the SPIx/I2Sx peripheral.
513  * @param SPIx where x can be
514  *   - 1 or 2 in SPI mode
515  *   - 1 or 2 in I2S mode
516  * @return The value of the received data.
517  */
SPI_I2S_ReceiveData(SPI_Module * SPIx)518 uint16_t SPI_I2S_ReceiveData(SPI_Module* SPIx)
519 {
520     /* Check the parameters */
521     assert_param(IS_SPI_PERIPH(SPIx));
522 
523     /* Return the data in the DAT register */
524     return SPIx->DAT;
525 }
526 
527 /**
528  * @brief  Configures internally by software the NSS pin for the selected SPI.
529  * @param SPIx where x can be 1 or 2 to select the SPI peripheral.
530  * @param SPI_NSSInternalSoft specifies the SPI NSS internal state.
531  *   This parameter can be one of the following values:
532  *     @arg SPI_NSS_HIGH Set NSS pin internally
533  *     @arg SPI_NSS_LOW Reset NSS pin internally
534  */
SPI_SetNssLevel(SPI_Module * SPIx,uint16_t SPI_NSSInternalSoft)535 void SPI_SetNssLevel(SPI_Module* SPIx, uint16_t SPI_NSSInternalSoft)
536 {
537     /* Check the parameters */
538     assert_param(IS_SPI_PERIPH(SPIx));
539     assert_param(IS_SPI_NSS_LEVEL(SPI_NSSInternalSoft));
540     if (SPI_NSSInternalSoft != SPI_NSS_LOW)
541     {
542         /* Set NSS pin internally by software */
543         SPIx->CTRL1 |= SPI_NSS_HIGH;
544     }
545     else
546     {
547         /* Reset NSS pin internally by software */
548         SPIx->CTRL1 &= SPI_NSS_LOW;
549     }
550 }
551 
552 /**
553  * @brief  Enables or disables the SS output for the selected SPI.
554  * @param SPIx where x can be 1 or 2 to select the SPI peripheral.
555  * @param Cmd new state of the SPIx SS output.
556  *   This parameter can be: ENABLE or DISABLE.
557  */
SPI_SSOutputEnable(SPI_Module * SPIx,FunctionalState Cmd)558 void SPI_SSOutputEnable(SPI_Module* SPIx, FunctionalState Cmd)
559 {
560     /* Check the parameters */
561     assert_param(IS_SPI_PERIPH(SPIx));
562     assert_param(IS_FUNCTIONAL_STATE(Cmd));
563     if (Cmd != DISABLE)
564     {
565         /* Enable the selected SPI SS output */
566         SPIx->CTRL2 |= CTRL2_SSOEN_ENABLE;
567     }
568     else
569     {
570         /* Disable the selected SPI SS output */
571         SPIx->CTRL2 &= CTRL2_SSOEN_DISABLE;
572     }
573 }
574 
575 /**
576  * @brief  Configures the data size for the selected SPI.
577  * @param SPIx where x can be 1 or 2 to select the SPI peripheral.
578  * @param DataLen specifies the SPI data size.
579  *   This parameter can be one of the following values:
580  *     @arg SPI_DATA_SIZE_16BITS Set data frame format to 16bit
581  *     @arg SPI_DATA_SIZE_8BITS Set data frame format to 8bit
582  */
SPI_ConfigDataLen(SPI_Module * SPIx,uint16_t DataLen)583 void SPI_ConfigDataLen(SPI_Module* SPIx, uint16_t DataLen)
584 {
585     /* Check the parameters */
586     assert_param(IS_SPI_PERIPH(SPIx));
587     assert_param(IS_SPI_DATASIZE(DataLen));
588     /* Clear DFF bit */
589     SPIx->CTRL1 &= (uint16_t)~SPI_DATA_SIZE_16BITS;
590     /* Set new DFF bit value */
591     SPIx->CTRL1 |= DataLen;
592 }
593 
594 /**
595  * @brief  Transmit the SPIx CRC value.
596  * @param SPIx where x can be 1 or 2 to select the SPI peripheral.
597  */
SPI_TransmitCrcNext(SPI_Module * SPIx)598 void SPI_TransmitCrcNext(SPI_Module* SPIx)
599 {
600     /* Check the parameters */
601     assert_param(IS_SPI_PERIPH(SPIx));
602 
603     /* Enable the selected SPI CRC transmission */
604     SPIx->CTRL1 |= CTRL1_CRCNEXT_ENABLE;
605 }
606 
607 /**
608  * @brief  Enables or disables the CRC value calculation of the transferred bytes.
609  * @param SPIx where x can be 1 or 2 to select the SPI peripheral.
610  * @param Cmd new state of the SPIx CRC value calculation.
611  *   This parameter can be: ENABLE or DISABLE.
612  */
SPI_EnableCalculateCrc(SPI_Module * SPIx,FunctionalState Cmd)613 void SPI_EnableCalculateCrc(SPI_Module* SPIx, FunctionalState Cmd)
614 {
615     /* Check the parameters */
616     assert_param(IS_SPI_PERIPH(SPIx));
617     assert_param(IS_FUNCTIONAL_STATE(Cmd));
618     if (Cmd != DISABLE)
619     {
620         /* Enable the selected SPI CRC calculation */
621         SPIx->CTRL1 |= CTRL1_CRCEN_ENABLE;
622     }
623     else
624     {
625         /* Disable the selected SPI CRC calculation */
626         SPIx->CTRL1 &= CTRL1_CRCEN_DISABLE;
627     }
628 }
629 
630 /**
631  * @brief  Returns the transmit or the receive CRC register value for the specified SPI.
632  * @param SPIx where x can be 1 or 2 to select the SPI peripheral.
633  * @param SPI_CRC specifies the CRC register to be read.
634  *   This parameter can be one of the following values:
635  *     @arg SPI_CRC_TX Selects Tx CRC register
636  *     @arg SPI_CRC_RX Selects Rx CRC register
637  * @return The selected CRC register value..
638  */
SPI_GetCRCDat(SPI_Module * SPIx,uint8_t SPI_CRC)639 uint16_t SPI_GetCRCDat(SPI_Module* SPIx, uint8_t SPI_CRC)
640 {
641     uint16_t crcreg = 0;
642     /* Check the parameters */
643     assert_param(IS_SPI_PERIPH(SPIx));
644     assert_param(IS_SPI_CRC(SPI_CRC));
645     if (SPI_CRC != SPI_CRC_RX)
646     {
647         /* Get the Tx CRC register */
648         crcreg = SPIx->CRCTDAT;
649     }
650     else
651     {
652         /* Get the Rx CRC register */
653         crcreg = SPIx->CRCRDAT;
654     }
655     /* Return the selected CRC register */
656     return crcreg;
657 }
658 
659 /**
660  * @brief  Returns the CRC Polynomial register value for the specified SPI.
661  * @param SPIx where x can be 1 or 2 to select the SPI peripheral.
662  * @return The CRC Polynomial register value.
663  */
SPI_GetCRCPoly(SPI_Module * SPIx)664 uint16_t SPI_GetCRCPoly(SPI_Module* SPIx)
665 {
666     /* Check the parameters */
667     assert_param(IS_SPI_PERIPH(SPIx));
668 
669     /* Return the CRC polynomial register */
670     return SPIx->CRCPOLY;
671 }
672 
673 /**
674  * @brief  Selects the data transfer direction in bi-directional mode for the specified SPI.
675  * @param SPIx where x can be 1 or 2 to select the SPI peripheral.
676  * @param DataDirection specifies the data transfer direction in bi-directional mode.
677  *   This parameter can be one of the following values:
678  *     @arg SPI_BIDIRECTION_TX Selects Tx transmission direction
679  *     @arg SPI_BIDIRECTION_RX Selects Rx receive direction
680  */
SPI_ConfigBidirectionalMode(SPI_Module * SPIx,uint16_t DataDirection)681 void SPI_ConfigBidirectionalMode(SPI_Module* SPIx, uint16_t DataDirection)
682 {
683     /* Check the parameters */
684     assert_param(IS_SPI_PERIPH(SPIx));
685     assert_param(IS_SPI_BIDIRECTION(DataDirection));
686     if (DataDirection == SPI_BIDIRECTION_TX)
687     {
688         /* Set the Tx only mode */
689         SPIx->CTRL1 |= SPI_BIDIRECTION_TX;
690     }
691     else
692     {
693         /* Set the Rx only mode */
694         SPIx->CTRL1 &= SPI_BIDIRECTION_RX;
695     }
696 }
697 
698 /**
699  * @brief  Checks whether the specified SPI/I2S flag is set or not.
700  * @param SPIx where x can be
701  *   - 1 or 2 in SPI mode
702  *   - 1 or 2 in I2S mode
703  * @param SPI_I2S_FLAG specifies the SPI/I2S flag to check.
704  *   This parameter can be one of the following values:
705  *     @arg SPI_I2S_TE_FLAG Transmit buffer empty flag.
706  *     @arg SPI_I2S_RNE_FLAG Receive buffer not empty flag.
707  *     @arg SPI_I2S_BUSY_FLAG Busy flag.
708  *     @arg SPI_I2S_OVER_FLAG Overrun flag.
709  *     @arg SPI_MODERR_FLAG Mode Fault flag.
710  *     @arg SPI_CRCERR_FLAG CRC Error flag.
711  *     @arg I2S_UNDER_FLAG Underrun Error flag.
712  *     @arg I2S_CHSIDE_FLAG Channel Side flag.
713  * @return The new state of SPI_I2S_FLAG (SET or RESET).
714  */
SPI_I2S_GetStatus(SPI_Module * SPIx,uint16_t SPI_I2S_FLAG)715 FlagStatus SPI_I2S_GetStatus(SPI_Module* SPIx, uint16_t SPI_I2S_FLAG)
716 {
717     FlagStatus bitstatus = RESET;
718     /* Check the parameters */
719     assert_param(IS_SPI_PERIPH(SPIx));
720     assert_param(IS_SPI_I2S_GET_FLAG(SPI_I2S_FLAG));
721     /* Check the status of the specified SPI/I2S flag */
722     if ((SPIx->STS & SPI_I2S_FLAG) != (uint16_t)RESET)
723     {
724         /* SPI_I2S_FLAG is set */
725         bitstatus = SET;
726     }
727     else
728     {
729         /* SPI_I2S_FLAG is reset */
730         bitstatus = RESET;
731     }
732     /* Return the SPI_I2S_FLAG status */
733     return bitstatus;
734 }
735 
736 /**
737  * @brief  Clears the SPIx CRC Error (CRCERR) flag.
738  * @param SPIx where x can be
739  *   - 1 or 2 in SPI mode
740  * @param SPI_I2S_FLAG specifies the SPI flag to clear.
741  *   This function clears only CRCERR flag.
742  * @note
743  *   - OVR (OverRun error) flag is cleared by software sequence: a read
744  *     operation to SPI_DAT register (SPI_I2S_ReceiveData()) followed by a read
745  *     operation to SPI_STS register (SPI_I2S_GetStatus()).
746  *   - UDR (UnderRun error) flag is cleared by a read operation to
747  *     SPI_STS register (SPI_I2S_GetStatus()).
748  *   - MODF (Mode Fault) flag is cleared by software sequence: a read/write
749  *     operation to SPI_STS register (SPI_I2S_GetStatus()) followed by a
750  *     write operation to SPI_CTRL1 register (SPI_Enable() to enable the SPI).
751  */
SPI_I2S_ClrCRCErrFlag(SPI_Module * SPIx,uint16_t SPI_I2S_FLAG)752 void SPI_I2S_ClrCRCErrFlag(SPI_Module* SPIx, uint16_t SPI_I2S_FLAG)
753 {
754     /* Check the parameters */
755     assert_param(IS_SPI_PERIPH(SPIx));
756     assert_param(IS_SPI_I2S_CLR_FLAG(SPI_I2S_FLAG));
757 
758     /* Clear the selected SPI CRC Error (CRCERR) flag */
759     SPIx->STS = (uint16_t)~SPI_I2S_FLAG;
760 }
761 
762 /**
763  * @brief  Checks whether the specified SPI/I2S interrupt has occurred or not.
764  * @param SPIx where x can be
765  *   - 1 or 2 in SPI mode
766  *   - 1 or 2 in I2S mode
767  * @param SPI_I2S_IT specifies the SPI/I2S interrupt source to check.
768  *   This parameter can be one of the following values:
769  *     @arg SPI_I2S_INT_TE Transmit buffer empty interrupt.
770  *     @arg SPI_I2S_INT_RNE Receive buffer not empty interrupt.
771  *     @arg SPI_I2S_INT_OVER Overrun interrupt.
772  *     @arg SPI_INT_MODERR Mode Fault interrupt.
773  *     @arg SPI_INT_CRCERR CRC Error interrupt.
774  *     @arg I2S_INT_UNDER Underrun Error interrupt.
775  * @return The new state of SPI_I2S_IT (SET or RESET).
776  */
SPI_I2S_GetIntStatus(SPI_Module * SPIx,uint8_t SPI_I2S_IT)777 INTStatus SPI_I2S_GetIntStatus(SPI_Module* SPIx, uint8_t SPI_I2S_IT)
778 {
779     INTStatus bitstatus = RESET;
780     uint16_t itpos = 0, itmask = 0, enablestatus = 0;
781 
782     /* Check the parameters */
783     assert_param(IS_SPI_PERIPH(SPIx));
784     assert_param(IS_SPI_I2S_GET_INT(SPI_I2S_IT));
785 
786     /* Get the SPI/I2S IT index */
787     itpos = 0x01 << (SPI_I2S_IT & 0x0F);
788 
789     /* Get the SPI/I2S IT mask */
790     itmask = SPI_I2S_IT >> 4;
791 
792     /* Set the IT mask */
793     itmask = 0x01 << itmask;
794 
795     /* Get the SPI_I2S_IT enable bit status */
796     enablestatus = (SPIx->CTRL2 & itmask);
797 
798     /* Check the status of the specified SPI/I2S interrupt */
799     if (((SPIx->STS & itpos) != (uint16_t)RESET) && enablestatus)
800     {
801         /* SPI_I2S_IT is set */
802         bitstatus = SET;
803     }
804     else
805     {
806         /* SPI_I2S_IT is reset */
807         bitstatus = RESET;
808     }
809     /* Return the SPI_I2S_IT status */
810     return bitstatus;
811 }
812 
813 /**
814  * @brief  Clears the SPIx CRC Error (CRCERR) interrupt pending bit.
815  * @param SPIx where x can be
816  *   - 1 or 2 in SPI mode
817  * @param SPI_I2S_IT specifies the SPI interrupt pending bit to clear.
818  *   This function clears only CRCERR interrupt pending bit.
819  * @note
820  *   - OVR (OverRun Error) interrupt pending bit is cleared by software
821  *     sequence: a read operation to SPI_DAT register (SPI_I2S_ReceiveData())
822  *     followed by a read operation to SPI_STS register (SPI_I2S_GetIntStatus()).
823  *   - UDR (UnderRun Error) interrupt pending bit is cleared by a read
824  *     operation to SPI_STS register (SPI_I2S_GetIntStatus()).
825  *   - MODF (Mode Fault) interrupt pending bit is cleared by software sequence:
826  *     a read/write operation to SPI_STS register (SPI_I2S_GetIntStatus())
827  *     followed by a write operation to SPI_CTRL1 register (SPI_Enable() to enable
828  *     the SPI).
829  */
SPI_I2S_ClrITPendingBit(SPI_Module * SPIx,uint8_t SPI_I2S_IT)830 void SPI_I2S_ClrITPendingBit(SPI_Module* SPIx, uint8_t SPI_I2S_IT)
831 {
832     uint16_t itpos = 0;
833     /* Check the parameters */
834     assert_param(IS_SPI_PERIPH(SPIx));
835     assert_param(IS_SPI_I2S_CLR_INT(SPI_I2S_IT));
836 
837     /* Get the SPI IT index */
838     itpos = 0x01 << (SPI_I2S_IT & 0x0F);
839 
840     /* Clear the selected SPI CRC Error (CRCERR) interrupt pending bit */
841     SPIx->STS = (uint16_t)~itpos;
842 }
843 /**
844  * @}
845  */
846 
847 /**
848  * @}
849  */
850 
851 /**
852  * @}
853  */
854