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