1 /**************************************************************************//**
2  * @file     spi.c
3  * @version  V3.00
4  * @brief    M2L31 series SPI driver source file
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  * @copyright (C) 2016-2020 Nuvoton Technology Corp. All rights reserved.
8 *****************************************************************************/
9 #include "NuMicro.h"
10 
11 /** @addtogroup Standard_Driver Standard Driver
12   @{
13 */
14 
15 /** @addtogroup SPI_Driver SPI Driver
16   @{
17 */
18 
19 /** @addtogroup SPI_EXPORTED_FUNCTIONS SPI Exported Functions
20   @{
21 */
22 static uint32_t SPII2S_GetSourceClockFreq(SPI_T *i2s);
23 
24 /**
25   * @brief  This function make SPI module be ready to transfer.
26   * @param[in]  spi The pointer of the specified SPI module.
27   * @param[in]  u32MasterSlave Decides the SPI module is operating in master mode or in slave mode. (SPI_SLAVE, SPI_MASTER)
28   * @param[in]  u32SPIMode Decides the transfer timing. (SPI_MODE_0, SPI_MODE_1, SPI_MODE_2, SPI_MODE_3)
29   * @param[in]  u32DataWidth Decides the data width of a SPI transaction.
30   * @param[in]  u32BusClock The expected frequency of SPI bus clock in Hz.
31   * @return Actual frequency of SPI peripheral clock.
32   * @details By default, the SPI transfer sequence is MSB first, the slave selection signal is active low and the automatic
33   *          slave selection function is disabled.
34   *          In Slave mode, the u32BusClock shall be NULL and the SPI clock divider setting will be 0.
35   *          The actual clock rate may be different from the target SPI clock rate.
36   *          For example, if the SPI source clock rate is 12 MHz and the target SPI bus clock rate is 7 MHz, the
37   *          actual SPI clock rate will be 6MHz.
38   * @note   If u32BusClock = 0, DIVIDER setting will be set to the maximum value.
39   * @note   If u32BusClock >= system clock frequency, SPI peripheral clock source will be set to APB clock and DIVIDER will be set to 0.
40   * @note   If u32BusClock >= SPI peripheral clock source, DIVIDER will be set to 0.
41   * @note   In slave mode, the SPI peripheral clock rate will be equal to APB clock rate.
42   */
SPI_Open(SPI_T * spi,uint32_t u32MasterSlave,uint32_t u32SPIMode,uint32_t u32DataWidth,uint32_t u32BusClock)43 uint32_t SPI_Open(SPI_T *spi,
44                   uint32_t u32MasterSlave,
45                   uint32_t u32SPIMode,
46                   uint32_t u32DataWidth,
47                   uint32_t u32BusClock)
48 {
49     uint32_t u32ClkSrc = 0U, u32Div, u32HCLKFreq, u32RetValue=0U;
50 
51     /* Disable I2S mode */
52     spi->I2SCTL &= ~SPI_I2SCTL_I2SEN_Msk;
53 
54     if(u32DataWidth == 32U)
55     {
56         u32DataWidth = 0U;
57     }
58 
59     /* Get system clock frequency */
60     u32HCLKFreq = CLK_GetHCLKFreq();
61 
62     if(u32MasterSlave == SPI_MASTER)
63     {
64         /* Default setting: slave selection signal is active low; disable automatic slave selection function. */
65         spi->SSCTL = SPI_SS_ACTIVE_LOW;
66 
67         /* Default setting: MSB first, disable unit transfer interrupt, SP_CYCLE = 0. */
68         spi->CTL = u32MasterSlave | (u32DataWidth << SPI_CTL_DWIDTH_Pos) | (u32SPIMode) | SPI_CTL_SPIEN_Msk;
69 
70         if(u32BusClock >= u32HCLKFreq)
71         {
72             /* Select PCLK as the clock source of SPI */
73             if(spi == SPI0)
74             {
75                 CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI0SEL_Msk)) | CLK_CLKSEL2_SPI0SEL_PCLK1;
76             }
77             else if(spi == SPI1)
78             {
79                 CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI1SEL_Msk)) | CLK_CLKSEL2_SPI1SEL_PCLK0;
80             }
81             else if(spi == SPI2)
82             {
83                 CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL3_SPI2SEL_Msk)) | CLK_CLKSEL3_SPI2SEL_PCLK1;
84             }
85             else
86             {
87                 CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL3_SPI3SEL_Msk)) | CLK_CLKSEL3_SPI3SEL_PCLK0;
88             }
89         }
90 
91         /* Check clock source of SPI */
92         if(spi == SPI0)
93         {
94             if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_HXT)
95             {
96                 u32ClkSrc = __HXT; /* Clock source is HXT */
97             }
98             else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PLL)
99             {
100                 u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
101             }
102             else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PCLK1)
103             {
104                 /* Clock source is PCLK1 */
105                 u32ClkSrc = CLK_GetPCLK1Freq();
106             }
107             else
108             {
109                 u32ClkSrc = __HIRC; /* Clock source is HIRC */
110             }
111         }
112         else if(spi == SPI1)
113         {
114             if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI1SEL_Msk) == CLK_CLKSEL2_SPI1SEL_HXT)
115             {
116                 u32ClkSrc = __HXT; /* Clock source is HXT */
117             }
118             else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI1SEL_Msk) == CLK_CLKSEL2_SPI1SEL_PLL)
119             {
120                 u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
121             }
122             else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI1SEL_Msk) == CLK_CLKSEL2_SPI1SEL_PCLK0)
123             {
124                 /* Clock source is PCLK0 */
125                 u32ClkSrc = CLK_GetPCLK0Freq();
126             }
127             else
128             {
129                 u32ClkSrc = __HIRC; /* Clock source is HIRC */
130             }
131         }
132         else if(spi == SPI2)
133         {
134             if((CLK->CLKSEL2 & CLK_CLKSEL3_SPI2SEL_Msk) == CLK_CLKSEL3_SPI2SEL_HXT)
135             {
136                 u32ClkSrc = __HXT; /* Clock source is HXT */
137             }
138             else if((CLK->CLKSEL2 & CLK_CLKSEL3_SPI2SEL_Msk) == CLK_CLKSEL3_SPI2SEL_PLL)
139             {
140                 u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
141             }
142             else if((CLK->CLKSEL2 & CLK_CLKSEL3_SPI2SEL_Msk) == CLK_CLKSEL3_SPI2SEL_PCLK1)
143             {
144                 u32ClkSrc = CLK_GetPCLK1Freq();
145             }
146             else
147             {
148                 u32ClkSrc = __HIRC; /* Clock source is HIRC */
149             }
150         }
151         else
152         {
153             if((CLK->CLKSEL2 & CLK_CLKSEL3_SPI3SEL_Msk) == CLK_CLKSEL3_SPI3SEL_HXT)
154             {
155                 u32ClkSrc = __HXT; /* Clock source is HXT */
156             }
157             else if((CLK->CLKSEL2 & CLK_CLKSEL3_SPI3SEL_Msk) == CLK_CLKSEL3_SPI3SEL_PLL)
158             {
159                 u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
160             }
161             else if((CLK->CLKSEL2 & CLK_CLKSEL3_SPI3SEL_Msk) == CLK_CLKSEL3_SPI3SEL_PCLK0)
162             {
163                 /* Clock source is PCLK0 */
164                 u32ClkSrc = CLK_GetPCLK0Freq();
165             }
166             else
167             {
168                 u32ClkSrc = __HIRC; /* Clock source is HIRC */
169             }
170         }
171 
172         if(u32BusClock >= u32HCLKFreq)
173         {
174             /* Set DIVIDER = 0 */
175             spi->CLKDIV = 0U;
176             /* Return master peripheral clock rate */
177             u32RetValue = u32ClkSrc;
178         }
179         else if(u32BusClock >= u32ClkSrc)
180         {
181             /* Set DIVIDER = 0 */
182             spi->CLKDIV = 0U;
183             /* Return master peripheral clock rate */
184             u32RetValue = u32ClkSrc;
185         }
186         else if(u32BusClock == 0U)
187         {
188             /* Set DIVIDER to the maximum value 0xFF. f_spi = f_spi_clk_src / (DIVIDER + 1) */
189             spi->CLKDIV |= SPI_CLKDIV_DIVIDER_Msk;
190             /* Return master peripheral clock rate */
191             u32RetValue = (u32ClkSrc / (0xFFU + 1U));
192         }
193         else
194         {
195             u32Div = (((u32ClkSrc * 10U) / u32BusClock + 5U) / 10U) - 1U; /* Round to the nearest integer */
196             if(u32Div > 0xFFU)
197             {
198                 u32Div = 0xFFU;
199                 spi->CLKDIV |= SPI_CLKDIV_DIVIDER_Msk;
200                 /* Return master peripheral clock rate */
201                 u32RetValue = (u32ClkSrc / (0xFFU + 1U));
202             }
203             else
204             {
205                 spi->CLKDIV = (spi->CLKDIV & (~SPI_CLKDIV_DIVIDER_Msk)) | (u32Div << SPI_CLKDIV_DIVIDER_Pos);
206                 /* Return master peripheral clock rate */
207                 u32RetValue = (u32ClkSrc / (u32Div + 1U));
208             }
209         }
210     }
211     else     /* For slave mode, force the SPI peripheral clock rate to equal APB clock rate. */
212     {
213         /* Default setting: slave selection signal is low level active. */
214         spi->SSCTL = SPI_SS_ACTIVE_LOW;
215 
216         /* Default setting: MSB first, disable unit transfer interrupt, SP_CYCLE = 0. */
217         spi->CTL = u32MasterSlave | (u32DataWidth << SPI_CTL_DWIDTH_Pos) | (u32SPIMode) | SPI_CTL_SPIEN_Msk;
218 
219         /* Set DIVIDER = 0 */
220         spi->CLKDIV = 0U;
221 
222         /* Select PCLK as the clock source of SPI */
223         if(spi == SPI0)
224         {
225             CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI0SEL_Msk)) | CLK_CLKSEL2_SPI0SEL_PCLK1;
226             /* Return slave peripheral clock rate */
227             u32RetValue = CLK_GetPCLK1Freq();
228         }
229         else if(spi == SPI1)
230         {
231             CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI1SEL_Msk)) | CLK_CLKSEL2_SPI1SEL_PCLK0;
232             /* Return slave peripheral clock rate */
233             u32RetValue = CLK_GetPCLK0Freq();
234         }
235         else if(spi == SPI2)
236         {
237             CLK->CLKSEL3 = (CLK->CLKSEL3 & (~CLK_CLKSEL3_SPI2SEL_Msk)) | CLK_CLKSEL3_SPI2SEL_PCLK1;
238             /* Return slave peripheral clock rate */
239             u32RetValue = CLK_GetPCLK1Freq();
240         }
241         else
242         {
243             CLK->CLKSEL3 = (CLK->CLKSEL3 & (~CLK_CLKSEL3_SPI3SEL_Msk)) | CLK_CLKSEL3_SPI3SEL_PCLK0;
244             /* Return slave peripheral clock rate */
245             u32RetValue = CLK_GetPCLK0Freq();
246         }
247     }
248 
249     return u32RetValue;
250 }
251 
252 /**
253   * @brief  Disable SPI controller.
254   * @param[in]  spi The pointer of the specified SPI module.
255   * @return None
256   * @details This function will reset SPI controller.
257   */
SPI_Close(SPI_T * spi)258 void SPI_Close(SPI_T *spi)
259 {
260     if(spi == SPI0)
261     {
262         /* Reset SPI */
263         SYS->IPRST1 |= SYS_IPRST1_SPI0RST_Msk;
264         SYS->IPRST1 &= ~SYS_IPRST1_SPI0RST_Msk;
265     }
266     else if(spi == SPI1)
267     {
268         /* Reset SPI */
269         SYS->IPRST1 |= SYS_IPRST1_SPI1RST_Msk;
270         SYS->IPRST1 &= ~SYS_IPRST1_SPI1RST_Msk;
271     }
272     else if(spi == SPI2)
273     {
274         /* Reset SPI */
275         SYS->IPRST1 |= SYS_IPRST1_SPI2RST_Msk;
276         SYS->IPRST1 &= ~SYS_IPRST1_SPI2RST_Msk;
277     }
278     else
279     {
280         /* Reset SPI */
281         SYS->IPRST2 |= SYS_IPRST2_SPI3RST_Msk;
282         SYS->IPRST2 &= ~SYS_IPRST2_SPI3RST_Msk;
283     }
284 }
285 
286 /**
287   * @brief  Clear RX FIFO buffer.
288   * @param[in]  spi The pointer of the specified SPI module.
289   * @return None
290   * @details This function will clear SPI RX FIFO buffer. The RXEMPTY (SPI_STATUS[8]) will be set to 1.
291   */
SPI_ClearRxFIFO(SPI_T * spi)292 void SPI_ClearRxFIFO(SPI_T *spi)
293 {
294     spi->FIFOCTL |= SPI_FIFOCTL_RXFBCLR_Msk;
295 }
296 
297 /**
298   * @brief  Clear TX FIFO buffer.
299   * @param[in]  spi The pointer of the specified SPI module.
300   * @return None
301   * @details This function will clear SPI TX FIFO buffer. The TXEMPTY (SPI_STATUS[16]) will be set to 1.
302   * @note The TX shift register will not be cleared.
303   */
SPI_ClearTxFIFO(SPI_T * spi)304 void SPI_ClearTxFIFO(SPI_T *spi)
305 {
306     spi->FIFOCTL |= SPI_FIFOCTL_TXFBCLR_Msk;
307 }
308 
309 /**
310   * @brief  Disable the automatic slave selection function.
311   * @param[in]  spi The pointer of the specified SPI module.
312   * @return None
313   * @details This function will disable the automatic slave selection function and set slave selection signal to inactive state.
314   */
SPI_DisableAutoSS(SPI_T * spi)315 void SPI_DisableAutoSS(SPI_T *spi)
316 {
317     spi->SSCTL &= ~(SPI_SSCTL_AUTOSS_Msk | SPI_SSCTL_SS_Msk);
318 }
319 
320 /**
321   * @brief  Enable the automatic slave selection function.
322   * @param[in]  spi The pointer of the specified SPI module.
323   * @param[in]  u32SSPinMask Specifies slave selection pins. (SPI_SS)
324   * @param[in]  u32ActiveLevel Specifies the active level of slave selection signal. (SPI_SS_ACTIVE_HIGH, SPI_SS_ACTIVE_LOW)
325   * @return None
326   * @details This function will enable the automatic slave selection function. Only available in Master mode.
327   *          The slave selection pin and the active level will be set in this function.
328   */
SPI_EnableAutoSS(SPI_T * spi,uint32_t u32SSPinMask,uint32_t u32ActiveLevel)329 void SPI_EnableAutoSS(SPI_T *spi, uint32_t u32SSPinMask, uint32_t u32ActiveLevel)
330 {
331     spi->SSCTL = (spi->SSCTL & (~(SPI_SSCTL_AUTOSS_Msk | SPI_SSCTL_SSACTPOL_Msk | SPI_SSCTL_SS_Msk))) | (u32SSPinMask | u32ActiveLevel | SPI_SSCTL_AUTOSS_Msk);
332 }
333 
334 /**
335   * @brief  Set the SPI bus clock.
336   * @param[in]  spi The pointer of the specified SPI module.
337   * @param[in]  u32BusClock The expected frequency of SPI bus clock in Hz.
338   * @return Actual frequency of SPI bus clock.
339   * @details This function is only available in Master mode. The actual clock rate may be different from the target SPI bus clock rate.
340   *          For example, if the SPI source clock rate is 12 MHz and the target SPI bus clock rate is 7 MHz, the actual SPI bus clock
341   *          rate will be 6 MHz.
342   * @note   If u32BusClock = 0, DIVIDER setting will be set to the maximum value.
343   * @note   If u32BusClock >= system clock frequency, SPI peripheral clock source will be set to APB clock and DIVIDER will be set to 0.
344   * @note   If u32BusClock >= SPI peripheral clock source, DIVIDER will be set to 0.
345   */
SPI_SetBusClock(SPI_T * spi,uint32_t u32BusClock)346 uint32_t SPI_SetBusClock(SPI_T *spi, uint32_t u32BusClock)
347 {
348     uint32_t u32ClkSrc, u32HCLKFreq;
349     uint32_t u32Div, u32RetValue;
350 
351     /* Get system clock frequency */
352     u32HCLKFreq = CLK_GetHCLKFreq();
353 
354     if(u32BusClock >= u32HCLKFreq)
355     {
356         /* Select PCLK as the clock source of SPI */
357         if(spi == SPI0)
358             CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI0SEL_Msk)) | CLK_CLKSEL2_SPI0SEL_PCLK1;
359         else if(spi == SPI1)
360             CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI1SEL_Msk)) | CLK_CLKSEL2_SPI1SEL_PCLK0;
361         else if(spi == SPI2)
362             CLK->CLKSEL3 = (CLK->CLKSEL3 & (~CLK_CLKSEL3_SPI2SEL_Msk)) | CLK_CLKSEL3_SPI2SEL_PCLK1;
363         else
364             CLK->CLKSEL3 = (CLK->CLKSEL3 & (~CLK_CLKSEL3_SPI3SEL_Msk)) | CLK_CLKSEL3_SPI3SEL_PCLK0;
365     }
366 
367     /* Check clock source of SPI */
368     if(spi == SPI0)
369     {
370         if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_HXT)
371         {
372             u32ClkSrc = __HXT; /* Clock source is HXT */
373         }
374         else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PLL)
375         {
376             u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
377         }
378         else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PCLK1)
379         {
380             /* Clock source is PCLK1 */
381             u32ClkSrc = CLK_GetPCLK1Freq();
382         }
383         else
384         {
385             u32ClkSrc = __HIRC; /* Clock source is HIRC */
386         }
387     }
388     else if(spi == SPI1)
389     {
390         if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI1SEL_Msk) == CLK_CLKSEL2_SPI1SEL_HXT)
391         {
392             u32ClkSrc = __HXT; /* Clock source is HXT */
393         }
394         else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI1SEL_Msk) == CLK_CLKSEL2_SPI1SEL_PLL)
395         {
396             u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
397         }
398         else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI1SEL_Msk) == CLK_CLKSEL2_SPI1SEL_PCLK0)
399         {
400             /* Clock source is PCLK0 */
401             u32ClkSrc = CLK_GetPCLK0Freq();
402         }
403         else
404         {
405             u32ClkSrc = __HIRC; /* Clock source is HIRC */
406         }
407     }
408     else if(spi == SPI2)
409     {
410         if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI2SEL_Msk) == CLK_CLKSEL3_SPI2SEL_HXT)
411         {
412             u32ClkSrc = __HXT; /* Clock source is HXT */
413         }
414         else if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI2SEL_Msk) == CLK_CLKSEL3_SPI2SEL_PLL)
415         {
416             u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
417         }
418         else if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI2SEL_Msk) == CLK_CLKSEL3_SPI2SEL_PCLK1)
419         {
420             /* Clock source is PCLK1 */
421             u32ClkSrc = CLK_GetPCLK1Freq();
422         }
423         else
424         {
425             u32ClkSrc = __HIRC; /* Clock source is HIRC */
426         }
427     }
428     else
429     {
430         if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI3SEL_Msk) == CLK_CLKSEL3_SPI3SEL_HXT)
431         {
432             u32ClkSrc = __HXT; /* Clock source is HXT */
433         }
434         else if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI3SEL_Msk) == CLK_CLKSEL3_SPI3SEL_PLL)
435         {
436             u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
437         }
438         else if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI3SEL_Msk) == CLK_CLKSEL3_SPI3SEL_PCLK0)
439         {
440             /* Clock source is PCLK0 */
441             u32ClkSrc = CLK_GetPCLK0Freq();
442         }
443         else
444         {
445             u32ClkSrc = __HIRC; /* Clock source is HIRC */
446         }
447     }
448 
449     if(u32BusClock >= u32HCLKFreq)
450     {
451         /* Set DIVIDER = 0 */
452         spi->CLKDIV = 0U;
453         /* Return master peripheral clock rate */
454         u32RetValue = u32ClkSrc;
455     }
456     else if(u32BusClock >= u32ClkSrc)
457     {
458         /* Set DIVIDER = 0 */
459         spi->CLKDIV = 0U;
460         /* Return master peripheral clock rate */
461         u32RetValue = u32ClkSrc;
462     }
463     else if(u32BusClock == 0U)
464     {
465         /* Set DIVIDER to the maximum value 0xFF. f_spi = f_spi_clk_src / (DIVIDER + 1) */
466         spi->CLKDIV |= SPI_CLKDIV_DIVIDER_Msk;
467         /* Return master peripheral clock rate */
468         u32RetValue = (u32ClkSrc / (0xFFU + 1U));
469     }
470     else
471     {
472         u32Div = (((u32ClkSrc * 10U) / u32BusClock + 5U) / 10U) - 1U; /* Round to the nearest integer */
473         if(u32Div > 0x1FFU)
474         {
475             u32Div = 0x1FFU;
476             spi->CLKDIV |= SPI_CLKDIV_DIVIDER_Msk;
477             /* Return master peripheral clock rate */
478             u32RetValue = (u32ClkSrc / (0xFFU + 1U));
479         }
480         else
481         {
482             spi->CLKDIV = (spi->CLKDIV & (~SPI_CLKDIV_DIVIDER_Msk)) | (u32Div << SPI_CLKDIV_DIVIDER_Pos);
483             /* Return master peripheral clock rate */
484             u32RetValue = (u32ClkSrc / (u32Div + 1U));
485         }
486     }
487 
488     return u32RetValue;
489 }
490 
491 /**
492   * @brief  Configure FIFO threshold setting.
493   * @param[in]  spi The pointer of the specified SPI module.
494   * @param[in]  u32TxThreshold Decides the TX FIFO threshold. It could be 0 ~ 3. If data width is 8~16 bits, it could be 0 ~ 7.
495   * @param[in]  u32RxThreshold Decides the RX FIFO threshold. It could be 0 ~ 3. If data width is 8~16 bits, it could be 0 ~ 7.
496   * @return None
497   * @details Set TX FIFO threshold and RX FIFO threshold configurations.
498   */
SPI_SetFIFO(SPI_T * spi,uint32_t u32TxThreshold,uint32_t u32RxThreshold)499 void SPI_SetFIFO(SPI_T *spi, uint32_t u32TxThreshold, uint32_t u32RxThreshold)
500 {
501     spi->FIFOCTL = (spi->FIFOCTL & ~(SPI_FIFOCTL_TXTH_Msk | SPI_FIFOCTL_RXTH_Msk)) |
502                    (u32TxThreshold << SPI_FIFOCTL_TXTH_Pos) |
503                    (u32RxThreshold << SPI_FIFOCTL_RXTH_Pos);
504 }
505 
506 /**
507   * @brief  Get the actual frequency of SPI bus clock. Only available in Master mode.
508   * @param[in]  spi The pointer of the specified SPI module.
509   * @return Actual SPI bus clock frequency in Hz.
510   * @details This function will calculate the actual SPI bus clock rate according to the SPInSEL and DIVIDER settings. Only available in Master mode.
511   */
SPI_GetBusClock(SPI_T * spi)512 uint32_t SPI_GetBusClock(SPI_T *spi)
513 {
514     uint32_t u32Div;
515     uint32_t u32ClkSrc;
516 
517     /* Get DIVIDER setting */
518     u32Div = (spi->CLKDIV & SPI_CLKDIV_DIVIDER_Msk) >> SPI_CLKDIV_DIVIDER_Pos;
519 
520     /* Check clock source of SPI */
521     if(spi == SPI0)
522     {
523         if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_HXT)
524         {
525             u32ClkSrc = __HXT; /* Clock source is HXT */
526         }
527         else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PLL)
528         {
529             u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
530         }
531         else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PCLK1)
532         {
533             /* Clock source is PCLK1 */
534             u32ClkSrc = CLK_GetPCLK1Freq();
535         }
536         else
537         {
538             u32ClkSrc = __HIRC; /* Clock source is HIRC */
539         }
540     }
541     else if(spi == SPI1)
542     {
543         if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI1SEL_Msk) == CLK_CLKSEL2_SPI1SEL_HXT)
544         {
545             u32ClkSrc = __HXT; /* Clock source is HXT */
546         }
547         else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI1SEL_Msk) == CLK_CLKSEL2_SPI1SEL_PLL)
548         {
549             u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
550         }
551         else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI1SEL_Msk) == CLK_CLKSEL2_SPI1SEL_PCLK0)
552         {
553             /* Clock source is PCLK0 */
554             u32ClkSrc = CLK_GetPCLK0Freq();
555         }
556         else
557         {
558             u32ClkSrc = __HIRC; /* Clock source is HIRC */
559         }
560     }
561     else if(spi == SPI2)
562     {
563         if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI2SEL_Msk) == CLK_CLKSEL3_SPI2SEL_HXT)
564         {
565             u32ClkSrc = __HXT; /* Clock source is HXT */
566         }
567         else if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI2SEL_Msk) == CLK_CLKSEL3_SPI2SEL_PLL)
568         {
569             u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
570         }
571         else if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI2SEL_Msk) == CLK_CLKSEL3_SPI2SEL_PCLK1)
572         {
573             /* Clock source is PCLK1 */
574             u32ClkSrc = CLK_GetPCLK1Freq();
575         }
576         else
577         {
578             u32ClkSrc = __HIRC; /* Clock source is HIRC */
579         }
580     }
581     else
582     {
583         if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI3SEL_Msk) == CLK_CLKSEL3_SPI3SEL_HXT)
584         {
585             u32ClkSrc = __HXT; /* Clock source is HXT */
586         }
587         else if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI3SEL_Msk) == CLK_CLKSEL3_SPI3SEL_PLL)
588         {
589             u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
590         }
591         else if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI3SEL_Msk) == CLK_CLKSEL3_SPI3SEL_PCLK0)
592         {
593             /* Clock source is PCLK0 */
594             u32ClkSrc = CLK_GetPCLK0Freq();
595         }
596         else
597         {
598             u32ClkSrc = __HIRC; /* Clock source is HIRC */
599         }
600     }
601 
602     /* Return SPI bus clock rate */
603     return (u32ClkSrc / (u32Div + 1U));
604 }
605 
606 /**
607   * @brief  Enable interrupt function.
608   * @param[in]  spi The pointer of the specified SPI module.
609   * @param[in]  u32Mask The combination of all related interrupt enable bits.
610   *                     Each bit corresponds to a interrupt enable bit.
611   *                     This parameter decides which interrupts will be enabled. It is combination of:
612   *                       - \ref SPI_UNIT_INT_MASK
613   *                       - \ref SPI_SSACT_INT_MASK
614   *                       - \ref SPI_SSINACT_INT_MASK
615   *                       - \ref SPI_SLVUR_INT_MASK
616   *                       - \ref SPI_SLVBE_INT_MASK
617   *                       - \ref SPI_TXUF_INT_MASK
618   *                       - \ref SPI_FIFO_TXTH_INT_MASK
619   *                       - \ref SPI_FIFO_RXTH_INT_MASK
620   *                       - \ref SPI_FIFO_RXOV_INT_MASK
621   *                       - \ref SPI_FIFO_RXTO_INT_MASK
622   *
623   * @return None
624   * @details Enable SPI related interrupts specified by u32Mask parameter.
625   */
SPI_EnableInt(SPI_T * spi,uint32_t u32Mask)626 void SPI_EnableInt(SPI_T *spi, uint32_t u32Mask)
627 {
628     /* Enable unit transfer interrupt flag */
629     if((u32Mask & SPI_UNIT_INT_MASK) == SPI_UNIT_INT_MASK)
630     {
631         spi->CTL |= SPI_CTL_UNITIEN_Msk;
632     }
633 
634     /* Enable slave selection signal active interrupt flag */
635     if((u32Mask & SPI_SSACT_INT_MASK) == SPI_SSACT_INT_MASK)
636     {
637         spi->SSCTL |= SPI_SSCTL_SSACTIEN_Msk;
638     }
639 
640     /* Enable slave selection signal inactive interrupt flag */
641     if((u32Mask & SPI_SSINACT_INT_MASK) == SPI_SSINACT_INT_MASK)
642     {
643         spi->SSCTL |= SPI_SSCTL_SSINAIEN_Msk;
644     }
645 
646     /* Enable slave TX under run interrupt flag */
647     if((u32Mask & SPI_SLVUR_INT_MASK) == SPI_SLVUR_INT_MASK)
648     {
649         spi->SSCTL |= SPI_SSCTL_SLVURIEN_Msk;
650     }
651 
652     /* Enable slave bit count error interrupt flag */
653     if((u32Mask & SPI_SLVBE_INT_MASK) == SPI_SLVBE_INT_MASK)
654     {
655         spi->SSCTL |= SPI_SSCTL_SLVBEIEN_Msk;
656     }
657 
658     /* Enable slave TX underflow interrupt flag */
659     if((u32Mask & SPI_TXUF_INT_MASK) == SPI_TXUF_INT_MASK)
660     {
661         spi->FIFOCTL |= SPI_FIFOCTL_TXUFIEN_Msk;
662     }
663 
664     /* Enable TX threshold interrupt flag */
665     if((u32Mask & SPI_FIFO_TXTH_INT_MASK) == SPI_FIFO_TXTH_INT_MASK)
666     {
667         spi->FIFOCTL |= SPI_FIFOCTL_TXTHIEN_Msk;
668     }
669 
670     /* Enable RX threshold interrupt flag */
671     if((u32Mask & SPI_FIFO_RXTH_INT_MASK) == SPI_FIFO_RXTH_INT_MASK)
672     {
673         spi->FIFOCTL |= SPI_FIFOCTL_RXTHIEN_Msk;
674     }
675 
676     /* Enable RX overrun interrupt flag */
677     if((u32Mask & SPI_FIFO_RXOV_INT_MASK) == SPI_FIFO_RXOV_INT_MASK)
678     {
679         spi->FIFOCTL |= SPI_FIFOCTL_RXOVIEN_Msk;
680     }
681 
682     /* Enable RX time-out interrupt flag */
683     if((u32Mask & SPI_FIFO_RXTO_INT_MASK) == SPI_FIFO_RXTO_INT_MASK)
684     {
685         spi->FIFOCTL |= SPI_FIFOCTL_RXTOIEN_Msk;
686     }
687 }
688 
689 /**
690   * @brief  Disable interrupt function.
691   * @param[in]  spi The pointer of the specified SPI module.
692   * @param[in]  u32Mask The combination of all related interrupt enable bits.
693   *                     Each bit corresponds to a interrupt bit.
694   *                     This parameter decides which interrupts will be disabled. It is combination of:
695   *                       - \ref SPI_UNIT_INT_MASK
696   *                       - \ref SPI_SSACT_INT_MASK
697   *                       - \ref SPI_SSINACT_INT_MASK
698   *                       - \ref SPI_SLVUR_INT_MASK
699   *                       - \ref SPI_SLVBE_INT_MASK
700   *                       - \ref SPI_TXUF_INT_MASK
701   *                       - \ref SPI_FIFO_TXTH_INT_MASK
702   *                       - \ref SPI_FIFO_RXTH_INT_MASK
703   *                       - \ref SPI_FIFO_RXOV_INT_MASK
704   *                       - \ref SPI_FIFO_RXTO_INT_MASK
705   *
706   * @return None
707   * @details Disable SPI related interrupts specified by u32Mask parameter.
708   */
SPI_DisableInt(SPI_T * spi,uint32_t u32Mask)709 void SPI_DisableInt(SPI_T *spi, uint32_t u32Mask)
710 {
711     /* Disable unit transfer interrupt flag */
712     if((u32Mask & SPI_UNIT_INT_MASK) == SPI_UNIT_INT_MASK)
713     {
714         spi->CTL &= ~SPI_CTL_UNITIEN_Msk;
715     }
716 
717     /* Disable slave selection signal active interrupt flag */
718     if((u32Mask & SPI_SSACT_INT_MASK) == SPI_SSACT_INT_MASK)
719     {
720         spi->SSCTL &= ~SPI_SSCTL_SSACTIEN_Msk;
721     }
722 
723     /* Disable slave selection signal inactive interrupt flag */
724     if((u32Mask & SPI_SSINACT_INT_MASK) == SPI_SSINACT_INT_MASK)
725     {
726         spi->SSCTL &= ~SPI_SSCTL_SSINAIEN_Msk;
727     }
728 
729     /* Disable slave TX under run interrupt flag */
730     if((u32Mask & SPI_SLVUR_INT_MASK) == SPI_SLVUR_INT_MASK)
731     {
732         spi->SSCTL &= ~SPI_SSCTL_SLVURIEN_Msk;
733     }
734 
735     /* Disable slave bit count error interrupt flag */
736     if((u32Mask & SPI_SLVBE_INT_MASK) == SPI_SLVBE_INT_MASK)
737     {
738         spi->SSCTL &= ~SPI_SSCTL_SLVBEIEN_Msk;
739     }
740 
741     /* Disable slave TX underflow interrupt flag */
742     if((u32Mask & SPI_TXUF_INT_MASK) == SPI_TXUF_INT_MASK)
743     {
744         spi->FIFOCTL &= ~SPI_FIFOCTL_TXUFIEN_Msk;
745     }
746 
747     /* Disable TX threshold interrupt flag */
748     if((u32Mask & SPI_FIFO_TXTH_INT_MASK) == SPI_FIFO_TXTH_INT_MASK)
749     {
750         spi->FIFOCTL &= ~SPI_FIFOCTL_TXTHIEN_Msk;
751     }
752 
753     /* Disable RX threshold interrupt flag */
754     if((u32Mask & SPI_FIFO_RXTH_INT_MASK) == SPI_FIFO_RXTH_INT_MASK)
755     {
756         spi->FIFOCTL &= ~SPI_FIFOCTL_RXTHIEN_Msk;
757     }
758 
759     /* Disable RX overrun interrupt flag */
760     if((u32Mask & SPI_FIFO_RXOV_INT_MASK) == SPI_FIFO_RXOV_INT_MASK)
761     {
762         spi->FIFOCTL &= ~SPI_FIFOCTL_RXOVIEN_Msk;
763     }
764 
765     /* Disable RX time-out interrupt flag */
766     if((u32Mask & SPI_FIFO_RXTO_INT_MASK) == SPI_FIFO_RXTO_INT_MASK)
767     {
768         spi->FIFOCTL &= ~SPI_FIFOCTL_RXTOIEN_Msk;
769     }
770 }
771 
772 /**
773   * @brief  Get interrupt flag.
774   * @param[in]  spi The pointer of the specified SPI module.
775   * @param[in]  u32Mask The combination of all related interrupt sources.
776   *                     Each bit corresponds to a interrupt source.
777   *                     This parameter decides which interrupt flags will be read. It is combination of:
778   *                       - \ref SPI_UNIT_INT_MASK
779   *                       - \ref SPI_SSACT_INT_MASK
780   *                       - \ref SPI_SSINACT_INT_MASK
781   *                       - \ref SPI_SLVUR_INT_MASK
782   *                       - \ref SPI_SLVBE_INT_MASK
783   *                       - \ref SPI_TXUF_INT_MASK
784   *                       - \ref SPI_FIFO_TXTH_INT_MASK
785   *                       - \ref SPI_FIFO_RXTH_INT_MASK
786   *                       - \ref SPI_FIFO_RXOV_INT_MASK
787   *                       - \ref SPI_FIFO_RXTO_INT_MASK
788   *
789   * @return Interrupt flags of selected sources.
790   * @details Get SPI related interrupt flags specified by u32Mask parameter.
791   */
SPI_GetIntFlag(SPI_T * spi,uint32_t u32Mask)792 uint32_t SPI_GetIntFlag(SPI_T *spi, uint32_t u32Mask)
793 {
794     uint32_t u32IntFlag = 0U, u32TmpVal;
795 
796     u32TmpVal = spi->STATUS & SPI_STATUS_UNITIF_Msk;
797     /* Check unit transfer interrupt flag */
798     if((u32Mask & SPI_UNIT_INT_MASK) && (u32TmpVal))
799     {
800         u32IntFlag |= SPI_UNIT_INT_MASK;
801     }
802 
803     u32TmpVal = spi->STATUS & SPI_STATUS_SSACTIF_Msk;
804     /* Check slave selection signal active interrupt flag */
805     if((u32Mask & SPI_SSACT_INT_MASK) && (u32TmpVal))
806     {
807         u32IntFlag |= SPI_SSACT_INT_MASK;
808     }
809 
810     u32TmpVal = spi->STATUS & SPI_STATUS_SSINAIF_Msk;
811     /* Check slave selection signal inactive interrupt flag */
812     if((u32Mask & SPI_SSINACT_INT_MASK) && (u32TmpVal))
813     {
814         u32IntFlag |= SPI_SSINACT_INT_MASK;
815     }
816 
817     u32TmpVal = spi->STATUS & SPI_STATUS_SLVURIF_Msk;
818     /* Check slave TX under run interrupt flag */
819     if((u32Mask & SPI_SLVUR_INT_MASK) && (u32TmpVal))
820     {
821         u32IntFlag |= SPI_SLVUR_INT_MASK;
822     }
823 
824     u32TmpVal = spi->STATUS & SPI_STATUS_SLVBEIF_Msk;
825     /* Check slave bit count error interrupt flag */
826     if((u32Mask & SPI_SLVBE_INT_MASK) && (u32TmpVal))
827     {
828         u32IntFlag |= SPI_SLVBE_INT_MASK;
829     }
830 
831     u32TmpVal = spi->STATUS & SPI_STATUS_TXUFIF_Msk;
832     /* Check slave TX underflow interrupt flag */
833     if((u32Mask & SPI_TXUF_INT_MASK) && (u32TmpVal))
834     {
835         u32IntFlag |= SPI_TXUF_INT_MASK;
836     }
837 
838     u32TmpVal = spi->STATUS & SPI_STATUS_TXTHIF_Msk;
839     /* Check TX threshold interrupt flag */
840     if((u32Mask & SPI_FIFO_TXTH_INT_MASK) && (u32TmpVal))
841     {
842         u32IntFlag |= SPI_FIFO_TXTH_INT_MASK;
843     }
844 
845     u32TmpVal = spi->STATUS & SPI_STATUS_RXTHIF_Msk;
846     /* Check RX threshold interrupt flag */
847     if((u32Mask & SPI_FIFO_RXTH_INT_MASK) && (u32TmpVal))
848     {
849         u32IntFlag |= SPI_FIFO_RXTH_INT_MASK;
850     }
851 
852     u32TmpVal = spi->STATUS & SPI_STATUS_RXOVIF_Msk;
853     /* Check RX overrun interrupt flag */
854     if((u32Mask & SPI_FIFO_RXOV_INT_MASK) && (u32TmpVal))
855     {
856         u32IntFlag |= SPI_FIFO_RXOV_INT_MASK;
857     }
858 
859     u32TmpVal = spi->STATUS & SPI_STATUS_RXTOIF_Msk;
860     /* Check RX time-out interrupt flag */
861     if((u32Mask & SPI_FIFO_RXTO_INT_MASK) && (u32TmpVal))
862     {
863         u32IntFlag |= SPI_FIFO_RXTO_INT_MASK;
864     }
865 
866     return u32IntFlag;
867 }
868 
869 /**
870   * @brief  Clear interrupt flag.
871   * @param[in]  spi The pointer of the specified SPI module.
872   * @param[in]  u32Mask The combination of all related interrupt sources.
873   *                     Each bit corresponds to a interrupt source.
874   *                     This parameter decides which interrupt flags will be cleared. It could be the combination of:
875   *                       - \ref SPI_UNIT_INT_MASK
876   *                       - \ref SPI_SSACT_INT_MASK
877   *                       - \ref SPI_SSINACT_INT_MASK
878   *                       - \ref SPI_SLVUR_INT_MASK
879   *                       - \ref SPI_SLVBE_INT_MASK
880   *                       - \ref SPI_TXUF_INT_MASK
881   *                       - \ref SPI_FIFO_RXOV_INT_MASK
882   *                       - \ref SPI_FIFO_RXTO_INT_MASK
883   *
884   * @return None
885   * @details Clear SPI related interrupt flags specified by u32Mask parameter.
886   */
SPI_ClearIntFlag(SPI_T * spi,uint32_t u32Mask)887 void SPI_ClearIntFlag(SPI_T *spi, uint32_t u32Mask)
888 {
889     if(u32Mask & SPI_UNIT_INT_MASK)
890     {
891         spi->STATUS = SPI_STATUS_UNITIF_Msk; /* Clear unit transfer interrupt flag */
892     }
893 
894     if(u32Mask & SPI_SSACT_INT_MASK)
895     {
896         spi->STATUS = SPI_STATUS_SSACTIF_Msk; /* Clear slave selection signal active interrupt flag */
897     }
898 
899     if(u32Mask & SPI_SSINACT_INT_MASK)
900     {
901         spi->STATUS = SPI_STATUS_SSINAIF_Msk; /* Clear slave selection signal inactive interrupt flag */
902     }
903 
904     if(u32Mask & SPI_SLVUR_INT_MASK)
905     {
906         spi->STATUS = SPI_STATUS_SLVURIF_Msk; /* Clear slave TX under run interrupt flag */
907     }
908 
909     if(u32Mask & SPI_SLVBE_INT_MASK)
910     {
911         spi->STATUS = SPI_STATUS_SLVBEIF_Msk; /* Clear slave bit count error interrupt flag */
912     }
913 
914     if(u32Mask & SPI_TXUF_INT_MASK)
915     {
916         spi->STATUS = SPI_STATUS_TXUFIF_Msk; /* Clear slave TX underflow interrupt flag */
917     }
918 
919     if(u32Mask & SPI_FIFO_RXOV_INT_MASK)
920     {
921         spi->STATUS = SPI_STATUS_RXOVIF_Msk; /* Clear RX overrun interrupt flag */
922     }
923 
924     if(u32Mask & SPI_FIFO_RXTO_INT_MASK)
925     {
926         spi->STATUS = SPI_STATUS_RXTOIF_Msk; /* Clear RX time-out interrupt flag */
927     }
928 }
929 
930 /**
931   * @brief  Get SPI status.
932   * @param[in]  spi The pointer of the specified SPI module.
933   * @param[in]  u32Mask The combination of all related sources.
934   *                     Each bit corresponds to a source.
935   *                     This parameter decides which flags will be read. It is combination of:
936   *                       - \ref SPI_BUSY_MASK
937   *                       - \ref SPI_RX_EMPTY_MASK
938   *                       - \ref SPI_RX_FULL_MASK
939   *                       - \ref SPI_TX_EMPTY_MASK
940   *                       - \ref SPI_TX_FULL_MASK
941   *                       - \ref SPI_TXRX_RESET_MASK
942   *                       - \ref SPI_SPIEN_STS_MASK
943   *                       - \ref SPI_SSLINE_STS_MASK
944   *
945   * @return Flags of selected sources.
946   * @details Get SPI related status specified by u32Mask parameter.
947   */
SPI_GetStatus(SPI_T * spi,uint32_t u32Mask)948 uint32_t SPI_GetStatus(SPI_T *spi, uint32_t u32Mask)
949 {
950     uint32_t u32Flag = 0U, u32TmpValue;
951 
952     u32TmpValue = spi->STATUS & SPI_STATUS_BUSY_Msk;
953     /* Check busy status */
954     if((u32Mask & SPI_BUSY_MASK) && (u32TmpValue))
955     {
956         u32Flag |= SPI_BUSY_MASK;
957     }
958 
959     u32TmpValue = spi->STATUS & SPI_STATUS_RXEMPTY_Msk;
960     /* Check RX empty flag */
961     if((u32Mask & SPI_RX_EMPTY_MASK) && (u32TmpValue))
962     {
963         u32Flag |= SPI_RX_EMPTY_MASK;
964     }
965 
966     u32TmpValue = spi->STATUS & SPI_STATUS_RXFULL_Msk;
967     /* Check RX full flag */
968     if((u32Mask & SPI_RX_FULL_MASK) && (u32TmpValue))
969     {
970         u32Flag |= SPI_RX_FULL_MASK;
971     }
972 
973     u32TmpValue = spi->STATUS & SPI_STATUS_TXEMPTY_Msk;
974     /* Check TX empty flag */
975     if((u32Mask & SPI_TX_EMPTY_MASK) && (u32TmpValue))
976     {
977         u32Flag |= SPI_TX_EMPTY_MASK;
978     }
979 
980     u32TmpValue = spi->STATUS & SPI_STATUS_TXFULL_Msk;
981     /* Check TX full flag */
982     if((u32Mask & SPI_TX_FULL_MASK) && (u32TmpValue))
983     {
984         u32Flag |= SPI_TX_FULL_MASK;
985     }
986 
987     u32TmpValue = spi->STATUS & SPI_STATUS_TXRXRST_Msk;
988     /* Check TX/RX reset flag */
989     if((u32Mask & SPI_TXRX_RESET_MASK) && (u32TmpValue))
990     {
991         u32Flag |= SPI_TXRX_RESET_MASK;
992     }
993 
994     u32TmpValue = spi->STATUS & SPI_STATUS_SPIENSTS_Msk;
995     /* Check SPIEN flag */
996     if((u32Mask & SPI_SPIEN_STS_MASK) && (u32TmpValue))
997     {
998         u32Flag |= SPI_SPIEN_STS_MASK;
999     }
1000 
1001     u32TmpValue = spi->STATUS & SPI_STATUS_SSLINE_Msk;
1002     /* Check SPIx_SS line status */
1003     if((u32Mask & SPI_SSLINE_STS_MASK) && (u32TmpValue))
1004     {
1005         u32Flag |= SPI_SSLINE_STS_MASK;
1006     }
1007 
1008     return u32Flag;
1009 }
1010 
1011 
1012 /**
1013   * @brief  This function is used to get I2S source clock frequency.
1014   * @param[in]  i2s The pointer of the specified I2S module.
1015   * @return I2S source clock frequency (Hz).
1016   * @details Return the source clock frequency according to the setting of SPI0SEL (CLKSEL2[27:26]).
1017   */
SPII2S_GetSourceClockFreq(SPI_T * i2s)1018 static uint32_t SPII2S_GetSourceClockFreq(SPI_T *i2s)
1019 {
1020     uint32_t u32Freq;
1021 
1022     if(i2s == SPI0)
1023     {
1024         if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_HXT)
1025         {
1026             u32Freq = __HXT; /* Clock source is HXT */
1027         }
1028         else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PLL)
1029         {
1030             u32Freq = CLK_GetPLLClockFreq(); /* Clock source is PLL */
1031         }
1032         else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI0SEL_Msk) == CLK_CLKSEL2_SPI0SEL_PCLK1)
1033         {
1034             /* Clock source is PCLK1 */
1035             u32Freq = CLK_GetPCLK1Freq();
1036         }
1037         else
1038         {
1039             u32Freq = __HIRC; /* Clock source is HIRC */
1040         }
1041     }
1042     else if(i2s == SPI1)
1043     {
1044         if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI1SEL_Msk) == CLK_CLKSEL2_SPI1SEL_HXT)
1045         {
1046             u32Freq = __HXT; /* Clock source is HXT */
1047         }
1048         else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI1SEL_Msk) == CLK_CLKSEL2_SPI1SEL_PLL)
1049         {
1050             u32Freq = CLK_GetPLLClockFreq(); /* Clock source is PLL */
1051         }
1052         else if((CLK->CLKSEL2 & CLK_CLKSEL2_SPI1SEL_Msk) == CLK_CLKSEL2_SPI1SEL_PCLK0)
1053         {
1054             /* Clock source is PCLK0 */
1055             u32Freq = CLK_GetPCLK0Freq();
1056         }
1057         else
1058         {
1059             u32Freq = __HIRC; /* Clock source is HIRC */
1060         }
1061     }
1062     else if(i2s == SPI2)
1063     {
1064         if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI2SEL_Msk) == CLK_CLKSEL3_SPI2SEL_HXT)
1065         {
1066             u32Freq = __HXT; /* Clock source is HXT */
1067         }
1068         else if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI2SEL_Msk) == CLK_CLKSEL3_SPI2SEL_PLL)
1069         {
1070             u32Freq = CLK_GetPLLClockFreq(); /* Clock source is PLL */
1071         }
1072         else if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI2SEL_Msk) == CLK_CLKSEL3_SPI2SEL_PCLK1)
1073         {
1074             /* Clock source is PCLK1 */
1075             u32Freq = CLK_GetPCLK1Freq();
1076         }
1077         else
1078         {
1079             u32Freq = __HIRC; /* Clock source is HIRC */
1080         }
1081     }
1082     else
1083     {
1084         if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI3SEL_Msk) == CLK_CLKSEL3_SPI3SEL_HXT)
1085         {
1086             u32Freq = __HXT; /* Clock source is HXT */
1087         }
1088         else if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI3SEL_Msk) == CLK_CLKSEL3_SPI3SEL_PLL)
1089         {
1090             u32Freq = CLK_GetPLLClockFreq(); /* Clock source is PLL */
1091         }
1092         else if((CLK->CLKSEL3 & CLK_CLKSEL3_SPI3SEL_Msk) == CLK_CLKSEL3_SPI3SEL_PCLK0)
1093         {
1094             /* Clock source is PCLK0 */
1095             u32Freq = CLK_GetPCLK0Freq();
1096         }
1097         else
1098         {
1099             u32Freq = __HIRC; /* Clock source is HIRC */
1100         }
1101     }
1102 
1103     return u32Freq;
1104 }
1105 
1106 /**
1107   * @brief  This function configures some parameters of I2S interface for general purpose use.
1108   * @param[in] i2s The pointer of the specified I2S module.
1109   * @param[in] u32MasterSlave I2S operation mode. Valid values are listed below.
1110   *                                     - \ref SPII2S_MODE_MASTER
1111   *                                     - \ref SPII2S_MODE_SLAVE
1112   * @param[in] u32SampleRate Sample rate
1113   * @param[in] u32WordWidth Data length. Valid values are listed below.
1114   *                                     - \ref SPII2S_DATABIT_8
1115   *                                     - \ref SPII2S_DATABIT_16
1116   *                                     - \ref SPII2S_DATABIT_24
1117   *                                     - \ref SPII2S_DATABIT_32
1118   * @param[in] u32Channels Audio format. Valid values are listed below.
1119   *                                     - \ref SPII2S_MONO
1120   *                                     - \ref SPII2S_STEREO
1121   * @param[in] u32DataFormat Data format. Valid values are listed below.
1122   *                                     - \ref SPII2S_FORMAT_I2S
1123   *                                     - \ref SPII2S_FORMAT_MSB
1124   *                                     - \ref SPII2S_FORMAT_PCMA
1125   *                                     - \ref SPII2S_FORMAT_PCMB
1126   * @return Real sample rate of master mode or peripheral clock rate of slave mode.
1127   * @details This function will reset SPI/I2S controller and configure I2S controller according to the input parameters.
1128   *          Set TX FIFO threshold to 2 and RX FIFO threshold to 1. Both the TX and RX functions will be enabled.
1129   *          The actual sample rate may be different from the target sample rate. The real sample rate will be returned for reference.
1130   * @note   In slave mode, the SPI peripheral clock rate will be equal to APB clock rate.
1131   */
SPII2S_Open(SPI_T * i2s,uint32_t u32MasterSlave,uint32_t u32SampleRate,uint32_t u32WordWidth,uint32_t u32Channels,uint32_t u32DataFormat)1132 uint32_t SPII2S_Open(SPI_T *i2s, uint32_t u32MasterSlave, uint32_t u32SampleRate, uint32_t u32WordWidth, uint32_t u32Channels, uint32_t u32DataFormat)
1133 {
1134     uint32_t u32Divider;
1135     uint32_t u32BitRate, u32SrcClk, u32RetValue;
1136 
1137     /* Reset SPI/I2S */
1138     if(i2s == SPI0)
1139     {
1140         SYS->IPRST1 |= SYS_IPRST1_SPI0RST_Msk;
1141         SYS->IPRST1 &= ~SYS_IPRST1_SPI0RST_Msk;
1142     }
1143     else if(i2s == SPI1)
1144     {
1145         SYS->IPRST1 |= SYS_IPRST1_SPI1RST_Msk;
1146         SYS->IPRST1 &= ~SYS_IPRST1_SPI1RST_Msk;
1147     }
1148     else if(i2s == SPI2)
1149     {
1150         SYS->IPRST1 |= SYS_IPRST1_SPI2RST_Msk;
1151         SYS->IPRST1 &= ~SYS_IPRST1_SPI2RST_Msk;
1152     }
1153     else
1154     {
1155         SYS->IPRST2 |= SYS_IPRST2_SPI3RST_Msk;
1156         SYS->IPRST2 &= ~SYS_IPRST2_SPI3RST_Msk;
1157     }
1158 
1159     /* Configure I2S controller */
1160     i2s->I2SCTL = u32MasterSlave | u32WordWidth | u32Channels | u32DataFormat;
1161     /* Set TX FIFO threshold to 2 and RX FIFO threshold to 1 */
1162     SPI_SetFIFO(i2s, 2, 1);
1163 
1164     if(u32MasterSlave == SPI_MASTER)
1165     {
1166         /* Get the source clock rate */
1167         u32SrcClk = SPII2S_GetSourceClockFreq(i2s);
1168 
1169         /* Calculate the bit clock rate */
1170         u32BitRate = u32SampleRate * ((u32WordWidth >> SPI_I2SCTL_WDWIDTH_Pos) + 1U) * 16U;
1171         u32Divider = ((u32SrcClk / u32BitRate) >> 1U) - 1U;
1172         //u32Divider = ((((u32SrcClk * 10UL / u32BitRate) >> 1U) + 5UL) / 10UL) - 1U;
1173         /* Set BCLKDIV setting */
1174         i2s->I2SCLK = (i2s->I2SCLK & ~SPI_I2SCLK_BCLKDIV_Msk) | (u32Divider << SPI_I2SCLK_BCLKDIV_Pos);
1175 
1176         /* Calculate bit clock rate */
1177         u32BitRate = u32SrcClk / ((u32Divider + 1U) * 2U);
1178         /* Calculate real sample rate */
1179         u32SampleRate = u32BitRate / (((u32WordWidth >> SPI_I2SCTL_WDWIDTH_Pos) + 1U) * 16U);
1180 
1181         /* Enable TX function, RX function and I2S mode. */
1182         i2s->I2SCTL |= (SPI_I2SCTL_RXEN_Msk | SPI_I2SCTL_TXEN_Msk | SPI_I2SCTL_I2SEN_Msk);
1183 
1184         /* Return the real sample rate */
1185         u32RetValue = u32SampleRate;
1186     }
1187     else
1188     {
1189         /* Set BCLKDIV = 0 */
1190         i2s->I2SCLK &= ~SPI_I2SCLK_BCLKDIV_Msk;
1191 
1192         if(i2s == SPI0)
1193         {
1194             /* Set the peripheral clock rate to equal APB clock rate */
1195             CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI0SEL_Msk)) | CLK_CLKSEL2_SPI0SEL_PCLK1;
1196             /* Enable TX function, RX function and I2S mode. */
1197             i2s->I2SCTL |= (SPI_I2SCTL_RXEN_Msk | SPI_I2SCTL_TXEN_Msk | SPI_I2SCTL_I2SEN_Msk);
1198             /* Return slave peripheral clock rate */
1199             u32RetValue = CLK_GetPCLK1Freq();
1200         }
1201         else if(i2s == SPI1)
1202         {
1203             /* Set the peripheral clock rate to equal APB clock rate */
1204             CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI1SEL_Msk)) | CLK_CLKSEL2_SPI1SEL_PCLK0;
1205             /* Enable TX function, RX function and I2S mode. */
1206             i2s->I2SCTL |= (SPI_I2SCTL_RXEN_Msk | SPI_I2SCTL_TXEN_Msk | SPI_I2SCTL_I2SEN_Msk);
1207             /* Return slave peripheral clock rate */
1208             u32RetValue = CLK_GetPCLK0Freq();
1209         }
1210         else if(i2s == SPI2)
1211         {
1212             /* Set the peripheral clock rate to equal APB clock rate */
1213             CLK->CLKSEL3 = (CLK->CLKSEL3 & (~CLK_CLKSEL3_SPI2SEL_Msk)) | CLK_CLKSEL3_SPI2SEL_PCLK1;
1214             /* Enable TX function, RX function and I2S mode. */
1215             i2s->I2SCTL |= (SPI_I2SCTL_RXEN_Msk | SPI_I2SCTL_TXEN_Msk | SPI_I2SCTL_I2SEN_Msk);
1216             /* Return slave peripheral clock rate */
1217             u32RetValue = CLK_GetPCLK1Freq();
1218         }
1219         else
1220         {
1221             /* Set the peripheral clock rate to equal APB clock rate */
1222             CLK->CLKSEL3 = (CLK->CLKSEL3 & (~CLK_CLKSEL3_SPI3SEL_Msk)) | CLK_CLKSEL3_SPI3SEL_PCLK0;
1223             /* Enable TX function, RX function and I2S mode. */
1224             i2s->I2SCTL |= (SPI_I2SCTL_RXEN_Msk | SPI_I2SCTL_TXEN_Msk | SPI_I2SCTL_I2SEN_Msk);
1225             /* Return slave peripheral clock rate */
1226             u32RetValue = CLK_GetPCLK0Freq();
1227         }
1228     }
1229 
1230     return u32RetValue;
1231 }
1232 
1233 /**
1234   * @brief  Disable I2S function.
1235   * @param[in]  i2s The pointer of the specified I2S module.
1236   * @return None
1237   * @details Disable I2S function.
1238   */
SPII2S_Close(SPI_T * i2s)1239 void SPII2S_Close(SPI_T *i2s)
1240 {
1241     i2s->I2SCTL &= ~SPI_I2SCTL_I2SEN_Msk;
1242 }
1243 
1244 /**
1245   * @brief Enable interrupt function.
1246   * @param[in] i2s The pointer of the specified I2S module.
1247   * @param[in] u32Mask The combination of all related interrupt enable bits.
1248   *            Each bit corresponds to a interrupt source. Valid values are listed below.
1249   *            - \ref SPII2S_FIFO_TXTH_INT_MASK
1250   *            - \ref SPII2S_FIFO_RXTH_INT_MASK
1251   *            - \ref SPII2S_FIFO_RXOV_INT_MASK
1252   *            - \ref SPII2S_FIFO_RXTO_INT_MASK
1253   *            - \ref SPII2S_TXUF_INT_MASK
1254   *            - \ref SPII2S_RIGHT_ZC_INT_MASK
1255   *            - \ref SPII2S_LEFT_ZC_INT_MASK
1256   * @return None
1257   * @details This function enables the interrupt according to the u32Mask parameter.
1258   */
SPII2S_EnableInt(SPI_T * i2s,uint32_t u32Mask)1259 void SPII2S_EnableInt(SPI_T *i2s, uint32_t u32Mask)
1260 {
1261     /* Enable TX threshold interrupt flag */
1262     if((u32Mask & SPII2S_FIFO_TXTH_INT_MASK) == SPII2S_FIFO_TXTH_INT_MASK)
1263     {
1264         i2s->FIFOCTL |= SPI_FIFOCTL_TXTHIEN_Msk;
1265     }
1266 
1267     /* Enable RX threshold interrupt flag */
1268     if((u32Mask & SPII2S_FIFO_RXTH_INT_MASK) == SPII2S_FIFO_RXTH_INT_MASK)
1269     {
1270         i2s->FIFOCTL |= SPI_FIFOCTL_RXTHIEN_Msk;
1271     }
1272 
1273     /* Enable RX overrun interrupt flag */
1274     if((u32Mask & SPII2S_FIFO_RXOV_INT_MASK) == SPII2S_FIFO_RXOV_INT_MASK)
1275     {
1276         i2s->FIFOCTL |= SPI_FIFOCTL_RXOVIEN_Msk;
1277     }
1278 
1279     /* Enable RX time-out interrupt flag */
1280     if((u32Mask & SPII2S_FIFO_RXTO_INT_MASK) == SPII2S_FIFO_RXTO_INT_MASK)
1281     {
1282         i2s->FIFOCTL |= SPI_FIFOCTL_RXTOIEN_Msk;
1283     }
1284 
1285     /* Enable TX underflow interrupt flag */
1286     if((u32Mask & SPII2S_TXUF_INT_MASK) == SPII2S_TXUF_INT_MASK)
1287     {
1288         i2s->FIFOCTL |= SPI_FIFOCTL_TXUFIEN_Msk;
1289     }
1290 
1291     /* Enable right channel zero cross interrupt flag */
1292     if((u32Mask & SPII2S_RIGHT_ZC_INT_MASK) == SPII2S_RIGHT_ZC_INT_MASK)
1293     {
1294         i2s->I2SCTL |= SPI_I2SCTL_RZCIEN_Msk;
1295     }
1296 
1297     /* Enable left channel zero cross interrupt flag */
1298     if((u32Mask & SPII2S_LEFT_ZC_INT_MASK) == SPII2S_LEFT_ZC_INT_MASK)
1299     {
1300         i2s->I2SCTL |= SPI_I2SCTL_LZCIEN_Msk;
1301     }
1302 }
1303 
1304 /**
1305   * @brief Disable interrupt function.
1306   * @param[in] i2s The pointer of the specified I2S module.
1307   * @param[in] u32Mask The combination of all related interrupt enable bits.
1308   *            Each bit corresponds to a interrupt source. Valid values are listed below.
1309   *            - \ref SPII2S_FIFO_TXTH_INT_MASK
1310   *            - \ref SPII2S_FIFO_RXTH_INT_MASK
1311   *            - \ref SPII2S_FIFO_RXOV_INT_MASK
1312   *            - \ref SPII2S_FIFO_RXTO_INT_MASK
1313   *            - \ref SPII2S_TXUF_INT_MASK
1314   *            - \ref SPII2S_RIGHT_ZC_INT_MASK
1315   *            - \ref SPII2S_LEFT_ZC_INT_MASK
1316   * @return None
1317   * @details This function disables the interrupt according to the u32Mask parameter.
1318   */
SPII2S_DisableInt(SPI_T * i2s,uint32_t u32Mask)1319 void SPII2S_DisableInt(SPI_T *i2s, uint32_t u32Mask)
1320 {
1321     /* Disable TX threshold interrupt flag */
1322     if((u32Mask & SPII2S_FIFO_TXTH_INT_MASK) == SPII2S_FIFO_TXTH_INT_MASK)
1323     {
1324         i2s->FIFOCTL &= ~SPI_FIFOCTL_TXTHIEN_Msk;
1325     }
1326 
1327     /* Disable RX threshold interrupt flag */
1328     if((u32Mask & SPII2S_FIFO_RXTH_INT_MASK) == SPII2S_FIFO_RXTH_INT_MASK)
1329     {
1330         i2s->FIFOCTL &= ~SPI_FIFOCTL_RXTHIEN_Msk;
1331     }
1332 
1333     /* Disable RX overrun interrupt flag */
1334     if((u32Mask & SPII2S_FIFO_RXOV_INT_MASK) == SPII2S_FIFO_RXOV_INT_MASK)
1335     {
1336         i2s->FIFOCTL &= ~SPI_FIFOCTL_RXOVIEN_Msk;
1337     }
1338 
1339     /* Disable RX time-out interrupt flag */
1340     if((u32Mask & SPII2S_FIFO_RXTO_INT_MASK) == SPII2S_FIFO_RXTO_INT_MASK)
1341     {
1342         i2s->FIFOCTL &= ~SPI_FIFOCTL_RXTOIEN_Msk;
1343     }
1344 
1345     /* Disable TX underflow interrupt flag */
1346     if((u32Mask & SPII2S_TXUF_INT_MASK) == SPII2S_TXUF_INT_MASK)
1347     {
1348         i2s->FIFOCTL &= ~SPI_FIFOCTL_TXUFIEN_Msk;
1349     }
1350 
1351     /* Disable right channel zero cross interrupt flag */
1352     if((u32Mask & SPII2S_RIGHT_ZC_INT_MASK) == SPII2S_RIGHT_ZC_INT_MASK)
1353     {
1354         i2s->I2SCTL &= ~SPI_I2SCTL_RZCIEN_Msk;
1355     }
1356 
1357     /* Disable left channel zero cross interrupt flag */
1358     if((u32Mask & SPII2S_LEFT_ZC_INT_MASK) == SPII2S_LEFT_ZC_INT_MASK)
1359     {
1360         i2s->I2SCTL &= ~SPI_I2SCTL_LZCIEN_Msk;
1361     }
1362 }
1363 
1364 /**
1365   * @brief  Enable master clock (MCLK).
1366   * @param[in] i2s The pointer of the specified I2S module.
1367   * @param[in] u32BusClock The target MCLK clock rate.
1368   * @return Actual MCLK clock rate
1369   * @details Set the master clock rate according to u32BusClock parameter and enable master clock output.
1370   *          The actual master clock rate may be different from the target master clock rate. The real master clock rate will be returned for reference.
1371   */
SPII2S_EnableMCLK(SPI_T * i2s,uint32_t u32BusClock)1372 uint32_t SPII2S_EnableMCLK(SPI_T *i2s, uint32_t u32BusClock)
1373 {
1374     uint32_t u32Divider;
1375     uint32_t u32SrcClk, u32RetValue;
1376 
1377     u32SrcClk = SPII2S_GetSourceClockFreq(i2s);
1378     if(u32BusClock == u32SrcClk)
1379     {
1380         u32Divider = 0U;
1381     }
1382     else
1383     {
1384         u32Divider = (u32SrcClk / u32BusClock) >> 1U;
1385         /* MCLKDIV is a 6-bit width configuration. The maximum value is 0x3F. */
1386         if(u32Divider > 0x3FU)
1387         {
1388             u32Divider = 0x3FU;
1389         }
1390     }
1391 
1392     /* Write u32Divider to MCLKDIV (SPI_I2SCLK[5:0]) */
1393     i2s->I2SCLK = (i2s->I2SCLK & ~SPI_I2SCLK_MCLKDIV_Msk) | (u32Divider << SPI_I2SCLK_MCLKDIV_Pos);
1394 
1395     /* Enable MCLK output */
1396     i2s->I2SCTL |= SPI_I2SCTL_MCLKEN_Msk;
1397 
1398     if(u32Divider == 0U)
1399     {
1400         u32RetValue = u32SrcClk; /* If MCLKDIV=0, master clock rate is equal to the source clock rate. */
1401     }
1402     else
1403     {
1404         u32RetValue = ((u32SrcClk >> 1U) / u32Divider); /* If MCLKDIV>0, master clock rate = source clock rate / (MCLKDIV * 2) */
1405     }
1406 
1407     return u32RetValue;
1408 }
1409 
1410 /**
1411   * @brief  Disable master clock (MCLK).
1412   * @param[in] i2s The pointer of the specified I2S module.
1413   * @return None
1414   * @details Clear MCLKEN bit of SPI_I2SCTL register to disable master clock output.
1415   */
SPII2S_DisableMCLK(SPI_T * i2s)1416 void SPII2S_DisableMCLK(SPI_T *i2s)
1417 {
1418     i2s->I2SCTL &= ~SPI_I2SCTL_MCLKEN_Msk;
1419 }
1420 
1421 /**
1422   * @brief  Configure FIFO threshold setting.
1423   * @param[in]  i2s The pointer of the specified I2S module.
1424   * @param[in]  u32TxThreshold Decides the TX FIFO threshold. It could be 0 ~ 3.
1425   * @param[in]  u32RxThreshold Decides the RX FIFO threshold. It could be 0 ~ 3.
1426   * @return None
1427   * @details Set TX FIFO threshold and RX FIFO threshold configurations.
1428   */
SPII2S_SetFIFO(SPI_T * i2s,uint32_t u32TxThreshold,uint32_t u32RxThreshold)1429 void SPII2S_SetFIFO(SPI_T *i2s, uint32_t u32TxThreshold, uint32_t u32RxThreshold)
1430 {
1431     i2s->FIFOCTL = (i2s->FIFOCTL & ~(SPI_FIFOCTL_TXTH_Msk | SPI_FIFOCTL_RXTH_Msk)) |
1432                    (u32TxThreshold << SPI_FIFOCTL_TXTH_Pos) |
1433                    (u32RxThreshold << SPI_FIFOCTL_RXTH_Pos);
1434 }
1435 
1436 /*@}*/ /* end of group SPI_EXPORTED_FUNCTIONS */
1437 
1438 /*@}*/ /* end of group SPI_Driver */
1439 
1440 /*@}*/ /* end of group Standard_Driver */
1441 
1442 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/
1443