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