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