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