M4521_BSP V3.02.000
The Board Support Package for M4521
spi.c
Go to the documentation of this file.
1/**************************************************************************/
12#include "M4521.h"
45uint32_t SPI_Open(SPI_T *spi,
46 uint32_t u32MasterSlave,
47 uint32_t u32SPIMode,
48 uint32_t u32DataWidth,
49 uint32_t u32BusClock)
50{
51 uint32_t u32ClkSrc = 0, u32Div, u32HCLKFreq;
52
53 if(spi == SPI1)
54 /* Disable I2S mode */
55 spi->I2SCTL &= ~SPI_I2SCTL_I2SEN_Msk;
56
57 if(u32DataWidth == 32)
58 u32DataWidth = 0;
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. */
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 CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI0SEL_Msk)) | CLK_CLKSEL2_SPI0SEL_PCLK0;
76 else
77 CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI1SEL_Msk)) | CLK_CLKSEL2_SPI1SEL_PCLK1;
78 }
79
80 /* Check clock source of SPI */
81 if(spi == SPI0)
82 {
84 u32ClkSrc = __HXT; /* Clock source is HXT */
86 u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
88 {
89 /* Clock source is PCLK0 */
91 u32ClkSrc = (u32HCLKFreq / 2);
92 else
93 u32ClkSrc = u32HCLKFreq;
94 }
95 else
96 u32ClkSrc = __HIRC; /* Clock source is HIRC */
97 }
98 else
99 {
101 u32ClkSrc = __HXT; /* Clock source is HXT */
103 u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
105 {
106 /* Clock source is PCLK1 */
108 u32ClkSrc = (u32HCLKFreq / 2);
109 else
110 u32ClkSrc = u32HCLKFreq;
111 }
112 else
113 u32ClkSrc = __HIRC; /* Clock source is HIRC */
114 }
115
116 if(u32BusClock >= u32HCLKFreq)
117 {
118 /* Set DIVIDER = 0 */
119 spi->CLKDIV = 0;
120 /* Return master peripheral clock rate */
121 return u32ClkSrc;
122 }
123 else if(u32BusClock >= u32ClkSrc)
124 {
125 /* Set DIVIDER = 0 */
126 spi->CLKDIV = 0;
127 /* Return master peripheral clock rate */
128 return u32ClkSrc;
129 }
130 else if(u32BusClock == 0)
131 {
132 /* Set DIVIDER to the maximum value 0xFF. f_spi = f_spi_clk_src / (DIVIDER + 1) */
134 /* Return master peripheral clock rate */
135 return (u32ClkSrc / (0xFF + 1));
136 }
137 else
138 {
139 u32Div = (((u32ClkSrc * 10) / u32BusClock + 5) / 10) - 1; /* Round to the nearest integer */
140 if(u32Div > 0xFF)
141 {
142 u32Div = 0xFF;
144 /* Return master peripheral clock rate */
145 return (u32ClkSrc / (0xFF + 1));
146 }
147 else
148 {
149 spi->CLKDIV = (spi->CLKDIV & (~SPI_CLKDIV_DIVIDER_Msk)) | (u32Div << SPI_CLKDIV_DIVIDER_Pos);
150 /* Return master peripheral clock rate */
151 return (u32ClkSrc / (u32Div + 1));
152 }
153 }
154 }
155 else /* For slave mode, force the SPI peripheral clock rate to equal APB clock rate. */
156 {
157 /* Default setting: slave selection signal is low level active. */
159
160 /* Default setting: MSB first, disable unit transfer interrupt, SP_CYCLE = 0. */
161 spi->CTL = u32MasterSlave | (u32DataWidth << SPI_CTL_DWIDTH_Pos) | (u32SPIMode) | SPI_CTL_SPIEN_Msk;
162
163 /* Set DIVIDER = 0 */
164 spi->CLKDIV = 0;
165
166 /* Select PCLK as the clock source of SPI */
167 if(spi == SPI0)
168 {
169 CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI0SEL_Msk)) | CLK_CLKSEL2_SPI0SEL_PCLK0;
170 /* Return slave peripheral clock rate */
172 return (u32HCLKFreq / 2);
173 else
174 return u32HCLKFreq;
175 }
176 else
177 {
178 CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI1SEL_Msk)) | CLK_CLKSEL2_SPI1SEL_PCLK1;
179 /* Return slave peripheral clock rate */
181 return (u32HCLKFreq / 2);
182 else
183 return u32HCLKFreq;
184 }
185 }
186}
187
194void SPI_Close(SPI_T *spi)
195{
196 if(spi == SPI0)
197 {
198 /* Reset SPI */
199 SYS->IPRST1 |= SYS_IPRST1_SPI0RST_Msk;
200 SYS->IPRST1 &= ~SYS_IPRST1_SPI0RST_Msk;
201 }
202 else
203 {
204 /* Reset SPI */
205 SYS->IPRST1 |= SYS_IPRST1_SPI1RST_Msk;
206 SYS->IPRST1 &= ~SYS_IPRST1_SPI1RST_Msk;
207 }
208}
209
217{
219}
220
229{
231}
232
240{
242}
243
253void SPI_EnableAutoSS(SPI_T *spi, uint32_t u32SSPinMask, uint32_t u32ActiveLevel)
254{
255 spi->SSCTL = (spi->SSCTL & (~(SPI_SSCTL_AUTOSS_Msk | SPI_SSCTL_SSACTPOL_Msk | SPI_SSCTL_SS_Msk))) | (u32SSPinMask | u32ActiveLevel | SPI_SSCTL_AUTOSS_Msk);
256}
257
270uint32_t SPI_SetBusClock(SPI_T *spi, uint32_t u32BusClock)
271{
272 uint32_t u32ClkSrc, u32HCLKFreq;
273 uint32_t u32Div;
274
275 /* Get system clock frequency */
276 u32HCLKFreq = CLK_GetHCLKFreq();
277
278 if(u32BusClock >= u32HCLKFreq)
279 {
280 /* Select PCLK as the clock source of SPI */
281 if(spi == SPI0)
282 CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI0SEL_Msk)) | CLK_CLKSEL2_SPI0SEL_PCLK0;
283 else
284 CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI1SEL_Msk)) | CLK_CLKSEL2_SPI1SEL_PCLK1;
285 }
286
287 /* Check clock source of SPI */
288 if(spi == SPI0)
289 {
291 u32ClkSrc = __HXT; /* Clock source is HXT */
293 u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
295 {
296 /* Clock source is PCLK0 */
298 u32ClkSrc = (u32HCLKFreq / 2);
299 else
300 u32ClkSrc = u32HCLKFreq;
301 }
302 else
303 u32ClkSrc = __HIRC; /* Clock source is HIRC */
304 }
305 else
306 {
308 u32ClkSrc = __HXT; /* Clock source is HXT */
310 u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
312 {
313 /* Clock source is PCLK1 */
315 u32ClkSrc = (u32HCLKFreq / 2);
316 else
317 u32ClkSrc = u32HCLKFreq;
318 }
319 else
320 u32ClkSrc = __HIRC; /* Clock source is HIRC */
321 }
322
323 if(u32BusClock >= u32HCLKFreq)
324 {
325 /* Set DIVIDER = 0 */
326 spi->CLKDIV = 0;
327 /* Return master peripheral clock rate */
328 return u32ClkSrc;
329 }
330 else if(u32BusClock >= u32ClkSrc)
331 {
332 /* Set DIVIDER = 0 */
333 spi->CLKDIV = 0;
334 /* Return master peripheral clock rate */
335 return u32ClkSrc;
336 }
337 else if(u32BusClock == 0)
338 {
339 /* Set DIVIDER to the maximum value 0xFF. f_spi = f_spi_clk_src / (DIVIDER + 1) */
341 /* Return master peripheral clock rate */
342 return (u32ClkSrc / (0xFF + 1));
343 }
344 else
345 {
346 u32Div = (((u32ClkSrc * 10) / u32BusClock + 5) / 10) - 1; /* Round to the nearest integer */
347 if(u32Div > 0xFF)
348 {
349 u32Div = 0xFF;
351 /* Return master peripheral clock rate */
352 return (u32ClkSrc / (0xFF + 1));
353 }
354 else
355 {
356 spi->CLKDIV = (spi->CLKDIV & (~SPI_CLKDIV_DIVIDER_Msk)) | (u32Div << SPI_CLKDIV_DIVIDER_Pos);
357 /* Return master peripheral clock rate */
358 return (u32ClkSrc / (u32Div + 1));
359 }
360 }
361}
362
371void SPI_SetFIFO(SPI_T *spi, uint32_t u32TxThreshold, uint32_t u32RxThreshold)
372{
374 (u32TxThreshold << SPI_FIFOCTL_TXTH_Pos) |
375 (u32RxThreshold << SPI_FIFOCTL_RXTH_Pos));
376}
377
384uint32_t SPI_GetBusClock(SPI_T *spi)
385{
386 uint32_t u32Div;
387 uint32_t u32ClkSrc, u32HCLKFreq;
388
389 /* Get DIVIDER setting */
391
392 /* Get system clock frequency */
393 u32HCLKFreq = CLK_GetHCLKFreq();
394
395 /* Check clock source of SPI */
396 if(spi == SPI0)
397 {
399 u32ClkSrc = __HXT; /* Clock source is HXT */
401 u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
403 {
404 /* Clock source is PCLK0 */
406 u32ClkSrc = (u32HCLKFreq / 2);
407 else
408 u32ClkSrc = u32HCLKFreq;
409 }
410 else
411 u32ClkSrc = __HIRC; /* Clock source is HIRC */
412 }
413 else
414 {
416 u32ClkSrc = __HXT; /* Clock source is HXT */
418 u32ClkSrc = CLK_GetPLLClockFreq(); /* Clock source is PLL */
420 {
421 /* Clock source is PCLK1 */
423 u32ClkSrc = (u32HCLKFreq / 2);
424 else
425 u32ClkSrc = u32HCLKFreq;
426 }
427 else
428 u32ClkSrc = __HIRC; /* Clock source is HIRC */
429 }
430
431 /* Return SPI bus clock rate */
432 return (u32ClkSrc / (u32Div + 1));
433}
434
456void SPI_EnableInt(SPI_T *spi, uint32_t u32Mask)
457{
458 /* Enable unit transfer interrupt flag */
459 if((u32Mask & SPI_UNIT_INT_MASK) == SPI_UNIT_INT_MASK)
460 spi->CTL |= SPI_CTL_UNITIEN_Msk;
461
462 /* Enable slave selection signal active interrupt flag */
463 if((u32Mask & SPI_SSACT_INT_MASK) == SPI_SSACT_INT_MASK)
465
466 /* Enable slave selection signal inactive interrupt flag */
469
470 /* Enable slave TX under run interrupt flag */
471 if((u32Mask & SPI_SLVUR_INT_MASK) == SPI_SLVUR_INT_MASK)
473
474 /* Enable slave bit count error interrupt flag */
475 if((u32Mask & SPI_SLVBE_INT_MASK) == SPI_SLVBE_INT_MASK)
477
478 /* Enable slave time-out interrupt flag */
479 if((u32Mask & SPI_SLVTO_INT_MASK) == SPI_SLVTO_INT_MASK)
481
482 /* Enable slave TX underflow interrupt flag */
483 if((u32Mask & SPI_TXUF_INT_MASK) == SPI_TXUF_INT_MASK)
485
486 /* Enable TX threshold interrupt flag */
489
490 /* Enable RX threshold interrupt flag */
493
494 /* Enable RX overrun interrupt flag */
497
498 /* Enable RX time-out interrupt flag */
501}
502
524void SPI_DisableInt(SPI_T *spi, uint32_t u32Mask)
525{
526 /* Disable unit transfer interrupt flag */
527 if((u32Mask & SPI_UNIT_INT_MASK) == SPI_UNIT_INT_MASK)
528 spi->CTL &= ~SPI_CTL_UNITIEN_Msk;
529
530 /* Disable slave selection signal active interrupt flag */
531 if((u32Mask & SPI_SSACT_INT_MASK) == SPI_SSACT_INT_MASK)
532 spi->SSCTL &= ~SPI_SSCTL_SSACTIEN_Msk;
533
534 /* Disable slave selection signal inactive interrupt flag */
536 spi->SSCTL &= ~SPI_SSCTL_SSINAIEN_Msk;
537
538 /* Disable slave TX under run interrupt flag */
539 if((u32Mask & SPI_SLVUR_INT_MASK) == SPI_SLVUR_INT_MASK)
540 spi->SSCTL &= ~SPI_SSCTL_SLVURIEN_Msk;
541
542 /* Disable slave bit count error interrupt flag */
543 if((u32Mask & SPI_SLVBE_INT_MASK) == SPI_SLVBE_INT_MASK)
544 spi->SSCTL &= ~SPI_SSCTL_SLVBEIEN_Msk;
545
546 /* Disable slave time-out interrupt flag */
547 if((u32Mask & SPI_SLVTO_INT_MASK) == SPI_SLVTO_INT_MASK)
548 spi->SSCTL &= ~SPI_SSCTL_SLVTOIEN_Msk;
549
550 /* Disable slave TX underflow interrupt flag */
551 if((u32Mask & SPI_TXUF_INT_MASK) == SPI_TXUF_INT_MASK)
552 spi->FIFOCTL &= ~SPI_FIFOCTL_TXUFIEN_Msk;
553
554 /* Disable TX threshold interrupt flag */
556 spi->FIFOCTL &= ~SPI_FIFOCTL_TXTHIEN_Msk;
557
558 /* Disable RX threshold interrupt flag */
560 spi->FIFOCTL &= ~SPI_FIFOCTL_RXTHIEN_Msk;
561
562 /* Disable RX overrun interrupt flag */
564 spi->FIFOCTL &= ~SPI_FIFOCTL_RXOVIEN_Msk;
565
566 /* Disable RX time-out interrupt flag */
568 spi->FIFOCTL &= ~SPI_FIFOCTL_RXTOIEN_Msk;
569}
570
592uint32_t SPI_GetIntFlag(SPI_T *spi, uint32_t u32Mask)
593{
594 uint32_t u32IntFlag = 0;
595
596 /* Check unit transfer interrupt flag */
597 if((u32Mask & SPI_UNIT_INT_MASK) && (spi->STATUS & SPI_STATUS_UNITIF_Msk))
598 u32IntFlag |= SPI_UNIT_INT_MASK;
599
600 /* Check slave selection signal active interrupt flag */
601 if((u32Mask & SPI_SSACT_INT_MASK) && (spi->STATUS & SPI_STATUS_SSACTIF_Msk))
602 u32IntFlag |= SPI_SSACT_INT_MASK;
603
604 /* Check slave selection signal inactive interrupt flag */
605 if((u32Mask & SPI_SSINACT_INT_MASK) && (spi->STATUS & SPI_STATUS_SSINAIF_Msk))
606 u32IntFlag |= SPI_SSINACT_INT_MASK;
607
608 /* Check slave TX under run interrupt flag */
609 if((u32Mask & SPI_SLVUR_INT_MASK) && (spi->STATUS & SPI_STATUS_SLVURIF_Msk))
610 u32IntFlag |= SPI_SLVUR_INT_MASK;
611
612 /* Check slave bit count error interrupt flag */
613 if((u32Mask & SPI_SLVBE_INT_MASK) && (spi->STATUS & SPI_STATUS_SLVBEIF_Msk))
614 u32IntFlag |= SPI_SLVBE_INT_MASK;
615
616 /* Check slave time-out interrupt flag */
617 if((u32Mask & SPI_SLVTO_INT_MASK) && (spi->STATUS & SPI_STATUS_SLVTOIF_Msk))
618 u32IntFlag |= SPI_SLVTO_INT_MASK;
619
620 /* Check slave TX underflow interrupt flag */
621 if((u32Mask & SPI_TXUF_INT_MASK) && (spi->STATUS & SPI_STATUS_TXUFIF_Msk))
622 u32IntFlag |= SPI_TXUF_INT_MASK;
623
624 /* Check TX threshold interrupt flag */
625 if((u32Mask & SPI_FIFO_TXTH_INT_MASK) && (spi->STATUS & SPI_STATUS_TXTHIF_Msk))
626 u32IntFlag |= SPI_FIFO_TXTH_INT_MASK;
627
628 /* Check RX threshold interrupt flag */
629 if((u32Mask & SPI_FIFO_RXTH_INT_MASK) && (spi->STATUS & SPI_STATUS_RXTHIF_Msk))
630 u32IntFlag |= SPI_FIFO_RXTH_INT_MASK;
631
632 /* Check RX overrun interrupt flag */
633 if((u32Mask & SPI_FIFO_RXOV_INT_MASK) && (spi->STATUS & SPI_STATUS_RXOVIF_Msk))
634 u32IntFlag |= SPI_FIFO_RXOV_INT_MASK;
635
636 /* Check RX time-out interrupt flag */
637 if((u32Mask & SPI_FIFO_RXTO_INT_MASK) && (spi->STATUS & SPI_STATUS_RXTOIF_Msk))
638 u32IntFlag |= SPI_FIFO_RXTO_INT_MASK;
639
640 return u32IntFlag;
641}
642
662void SPI_ClearIntFlag(SPI_T *spi, uint32_t u32Mask)
663{
664 if(u32Mask & SPI_UNIT_INT_MASK)
665 spi->STATUS = SPI_STATUS_UNITIF_Msk; /* Clear unit transfer interrupt flag */
666
667 if(u32Mask & SPI_SSACT_INT_MASK)
668 spi->STATUS = SPI_STATUS_SSACTIF_Msk; /* Clear slave selection signal active interrupt flag */
669
670 if(u32Mask & SPI_SSINACT_INT_MASK)
671 spi->STATUS = SPI_STATUS_SSINAIF_Msk; /* Clear slave selection signal inactive interrupt flag */
672
673 if(u32Mask & SPI_SLVUR_INT_MASK)
674 spi->STATUS = SPI_STATUS_SLVURIF_Msk; /* Clear slave TX under run interrupt flag */
675
676 if(u32Mask & SPI_SLVBE_INT_MASK)
677 spi->STATUS = SPI_STATUS_SLVBEIF_Msk; /* Clear slave bit count error interrupt flag */
678
679 if(u32Mask & SPI_SLVTO_INT_MASK)
680 spi->STATUS = SPI_STATUS_SLVTOIF_Msk; /* Clear slave time-out interrupt flag */
681
682 if(u32Mask & SPI_TXUF_INT_MASK)
683 spi->STATUS = SPI_STATUS_TXUFIF_Msk; /* Clear slave TX underflow interrupt flag */
684
685 if(u32Mask & SPI_FIFO_RXOV_INT_MASK)
686 spi->STATUS = SPI_STATUS_RXOVIF_Msk; /* Clear RX overrun interrupt flag */
687
688 if(u32Mask & SPI_FIFO_RXTO_INT_MASK)
689 spi->STATUS = SPI_STATUS_RXTOIF_Msk; /* Clear RX time-out interrupt flag */
690}
691
710uint32_t SPI_GetStatus(SPI_T *spi, uint32_t u32Mask)
711{
712 uint32_t u32Flag = 0;
713
714 /* Check busy status */
715 if((u32Mask & SPI_BUSY_MASK) && (spi->STATUS & SPI_STATUS_BUSY_Msk))
716 u32Flag |= SPI_BUSY_MASK;
717
718 /* Check RX empty flag */
719 if((u32Mask & SPI_RX_EMPTY_MASK) && (spi->STATUS & SPI_STATUS_RXEMPTY_Msk))
720 u32Flag |= SPI_RX_EMPTY_MASK;
721
722 /* Check RX full flag */
723 if((u32Mask & SPI_RX_FULL_MASK) && (spi->STATUS & SPI_STATUS_RXFULL_Msk))
724 u32Flag |= SPI_RX_FULL_MASK;
725
726 /* Check TX empty flag */
727 if((u32Mask & SPI_TX_EMPTY_MASK) && (spi->STATUS & SPI_STATUS_TXEMPTY_Msk))
728 u32Flag |= SPI_TX_EMPTY_MASK;
729
730 /* Check TX full flag */
731 if((u32Mask & SPI_TX_FULL_MASK) && (spi->STATUS & SPI_STATUS_TXFULL_Msk))
732 u32Flag |= SPI_TX_FULL_MASK;
733
734 /* Check TX/RX reset flag */
735 if((u32Mask & SPI_TXRX_RESET_MASK) && (spi->STATUS & SPI_STATUS_TXRXRST_Msk))
736 u32Flag |= SPI_TXRX_RESET_MASK;
737
738 /* Check SPIEN flag */
739 if((u32Mask & SPI_SPIEN_STS_MASK) && (spi->STATUS & SPI_STATUS_SPIENSTS_Msk))
740 u32Flag |= SPI_SPIEN_STS_MASK;
741
742 /* Check SPIn_SS line status */
743 if((u32Mask & SPI_SSLINE_STS_MASK) && (spi->STATUS & SPI_STATUS_SSLINE_Msk))
744 u32Flag |= SPI_SSLINE_STS_MASK;
745
746 return u32Flag;
747}
748
749
757static uint32_t I2S_GetSourceClockFreq(SPI_T *i2s)
758{
759 uint32_t u32Freq, u32HCLKFreq;
760
762 u32Freq = __HXT; /* Clock source is HXT */
764 u32Freq = CLK_GetPLLClockFreq(); /* Clock source is PLL */
766 {
767 /* Get system clock frequency */
768 u32HCLKFreq = CLK_GetHCLKFreq();
769 /* Clock source is PCLK1 */
771 u32Freq = (u32HCLKFreq / 2);
772 else
773 u32Freq = u32HCLKFreq;
774 }
775 else
776 u32Freq = __HIRC; /* Clock source is HIRC */
777
778 return u32Freq;
779}
780
808uint32_t I2S_Open(SPI_T *i2s, uint32_t u32MasterSlave, uint32_t u32SampleRate, uint32_t u32WordWidth, uint32_t u32Channels, uint32_t u32DataFormat)
809{
810 uint32_t u32Divider;
811 uint32_t u32BitRate, u32SrcClk;
812 uint32_t u32HCLKFreq;
813
814 /* Reset SPI/I2S */
815 SYS->IPRST1 |= SYS_IPRST1_SPI1RST_Msk;
816 SYS->IPRST1 &= ~SYS_IPRST1_SPI1RST_Msk;
817
818 /* Configure I2S controller */
819 i2s->I2SCTL = u32MasterSlave | u32WordWidth | u32Channels | u32DataFormat;
820 /* Set TX and RX FIFO threshold to middle value */
822
823 if(u32MasterSlave == SPI_MASTER)
824 {
825 /* Get the source clock rate */
826 u32SrcClk = I2S_GetSourceClockFreq(i2s);
827
828 /* Calculate the bit clock rate */
829 u32BitRate = u32SampleRate * ((u32WordWidth >> SPI_I2SCTL_WDWIDTH_Pos) + 1) * 16;
830 u32Divider = ((u32SrcClk / u32BitRate) >> 1) - 1;
831 /* Set BCLKDIV setting */
832 i2s->I2SCLK = (i2s->I2SCLK & ~SPI_I2SCLK_BCLKDIV_Msk) | (u32Divider << SPI_I2SCLK_BCLKDIV_Pos);
833
834 /* Calculate bit clock rate */
835 u32BitRate = u32SrcClk / ((u32Divider + 1) * 2);
836 /* Calculate real sample rate */
837 u32SampleRate = u32BitRate / (((u32WordWidth >> SPI_I2SCTL_WDWIDTH_Pos) + 1) * 16);
838
839 /* Enable TX function, RX function and I2S mode. */
841
842 /* Return the real sample rate */
843 return u32SampleRate;
844 }
845 else
846 {
847 /* Set BCLKDIV = 0 */
848 i2s->I2SCLK &= ~SPI_I2SCLK_BCLKDIV_Msk;
849 /* Get system clock frequency */
850 u32HCLKFreq = CLK_GetHCLKFreq();
851
852 /* Set the peripheral clock rate to equal APB clock rate */
853 CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_SPI1SEL_Msk)) | CLK_CLKSEL2_SPI1SEL_PCLK1;
854 /* Enable TX function, RX function and I2S mode. */
856 /* Return slave peripheral clock rate */
858 return (u32HCLKFreq / 2);
859 else
860 return u32HCLKFreq;
861 }
862}
863
871void I2S_Close(SPI_T *i2s)
872{
873 i2s->I2SCTL &= ~SPI_I2SCTL_I2SEN_Msk;
874}
875
892void I2S_EnableInt(SPI_T *i2s, uint32_t u32Mask)
893{
894 /* Enable TX threshold interrupt flag */
897
898 /* Enable RX threshold interrupt flag */
901
902 /* Enable RX overrun interrupt flag */
905
906 /* Enable RX time-out interrupt flag */
909
910 /* Enable TX underflow interrupt flag */
911 if((u32Mask & I2S_TXUF_INT_MASK) == I2S_TXUF_INT_MASK)
913
914 /* Enable right channel zero cross interrupt flag */
917
918 /* Enable left channel zero cross interrupt flag */
921}
922
939void I2S_DisableInt(SPI_T *i2s, uint32_t u32Mask)
940{
941 /* Disable TX threshold interrupt flag */
943 i2s->FIFOCTL &= ~SPI_FIFOCTL_TXTHIEN_Msk;
944
945 /* Disable RX threshold interrupt flag */
947 i2s->FIFOCTL &= ~SPI_FIFOCTL_RXTHIEN_Msk;
948
949 /* Disable RX overrun interrupt flag */
951 i2s->FIFOCTL &= ~SPI_FIFOCTL_RXOVIEN_Msk;
952
953 /* Disable RX time-out interrupt flag */
955 i2s->FIFOCTL &= ~SPI_FIFOCTL_RXTOIEN_Msk;
956
957 /* Disable TX underflow interrupt flag */
958 if((u32Mask & I2S_TXUF_INT_MASK) == I2S_TXUF_INT_MASK)
959 i2s->FIFOCTL &= ~SPI_FIFOCTL_TXUFIEN_Msk;
960
961 /* Disable right channel zero cross interrupt flag */
963 i2s->I2SCTL &= ~SPI_I2SCTL_RZCIEN_Msk;
964
965 /* Disable left channel zero cross interrupt flag */
967 i2s->I2SCTL &= ~SPI_I2SCTL_LZCIEN_Msk;
968}
969
979uint32_t I2S_EnableMCLK(SPI_T *i2s, uint32_t u32BusClock)
980{
981 uint32_t u32Divider;
982 uint32_t u32SrcClk;
983
984 u32SrcClk = I2S_GetSourceClockFreq(i2s);
985 if(u32BusClock == u32SrcClk)
986 u32Divider = 0;
987 else
988 {
989// u32Divider = (u32SrcClk / u32BusClock) >> 1;
990 u32Divider = (((u32SrcClk * 10UL / u32BusClock) >> 1) + 5UL) / 10UL;
991 /* MCLKDIV is a 6-bit width configuration. The maximum value is 0x3F. */
992 if(u32Divider > 0x3F)
993 u32Divider = 0x3F;
994 }
995
996 /* Write u32Divider to MCLKDIV (SPI_I2SCLK[5:0]) */
997 i2s->I2SCLK = (i2s->I2SCLK & ~SPI_I2SCLK_MCLKDIV_Msk) | (u32Divider << SPI_I2SCLK_MCLKDIV_Pos);
998
999 /* Enable MCLK output */
1001
1002 if(u32Divider == 0)
1003 return u32SrcClk; /* If MCLKDIV=0, master clock rate is equal to the source clock rate. */
1004 else
1005 return ((u32SrcClk >> 1) / u32Divider); /* If MCLKDIV>0, master clock rate = source clock rate / (MCLKDIV * 2) */
1006}
1007
1016{
1017 i2s->I2SCTL &= ~SPI_I2SCTL_MCLKEN_Msk;
1018}
1019
1028void I2S_SetFIFO(SPI_T *i2s, uint32_t u32TxThreshold, uint32_t u32RxThreshold)
1029{
1031 (u32TxThreshold << SPI_FIFOCTL_TXTH_Pos) |
1032 (u32RxThreshold << SPI_FIFOCTL_RXTH_Pos));
1033}
1034 /* end of group SPI_EXPORTED_FUNCTIONS */
1036 /* end of group SPI_Driver */
1038 /* end of group Standard_Driver */
1040
1041/*** (C) COPYRIGHT 2022 Nuvoton Technology Corp. ***/
#define SPI_STATUS_TXFULL_Msk
Definition: M4521.h:9502
#define SPI_SSCTL_SSACTPOL_Msk
Definition: M4521.h:9382
#define SPI_FIFOCTL_RXOVIEN_Msk
Definition: M4521.h:9436
#define SPI_STATUS_SSACTIF_Msk
Definition: M4521.h:9463
#define SPI_SSCTL_SS_Msk
Definition: M4521.h:9379
#define SPI_CTL_UNITIEN_Msk
Definition: M4521.h:9358
#define SPI_FIFOCTL_RXTH_Pos
Definition: M4521.h:9450
#define SPI_FIFOCTL_TXTH_Msk
Definition: M4521.h:9454
#define SPI_CTL_DWIDTH_Pos
Definition: M4521.h:9348
#define SPI_I2SCTL_TXEN_Msk
Definition: M4521.h:9529
#define SPI_STATUS_TXRXRST_Msk
Definition: M4521.h:9511
#define SPI_STATUS_TXTHIF_Msk
Definition: M4521.h:9505
#define SPI_I2SCTL_LZCIEN_Msk
Definition: M4521.h:9565
#define SPI_STATUS_RXTHIF_Msk
Definition: M4521.h:9487
#define SPI_SSCTL_SLVTOIEN_Msk
Definition: M4521.h:9391
#define SPI_I2SCTL_RZCIEN_Msk
Definition: M4521.h:9562
#define SPI_STATUS_UNITIF_Msk
Definition: M4521.h:9460
#define SPI_SSCTL_SSACTIEN_Msk
Definition: M4521.h:9403
#define SPI_CLKDIV_DIVIDER_Pos
Definition: M4521.h:9375
#define SYS_IPRST1_SPI1RST_Msk
Definition: M4521.h:10427
#define SPI_STATUS_SSINAIF_Msk
Definition: M4521.h:9466
#define SYS_IPRST1_SPI0RST_Msk
Definition: M4521.h:10424
#define SPI_FIFOCTL_TXUFIEN_Msk
Definition: M4521.h:9442
#define SPI_STATUS_SLVTOIF_Msk
Definition: M4521.h:9472
#define SPI_CLKDIV_DIVIDER_Msk
Definition: M4521.h:9376
#define SPI_FIFOCTL_TXTH_Pos
Definition: M4521.h:9453
#define SPI_CTL_SPIEN_Msk
Definition: M4521.h:9334
#define SPI_SSCTL_SLVBEIEN_Msk
Definition: M4521.h:9397
#define SPI_STATUS_TXEMPTY_Msk
Definition: M4521.h:9499
#define SPI_SSCTL_SSINAIEN_Msk
Definition: M4521.h:9406
#define SPI_STATUS_RXOVIF_Msk
Definition: M4521.h:9490
#define SPI_I2SCTL_WDWIDTH_Pos
Definition: M4521.h:9537
#define SPI_I2SCTL_RXEN_Msk
Definition: M4521.h:9532
#define SPI_FIFOCTL_RXTOIEN_Msk
Definition: M4521.h:9433
#define SPI_FIFOCTL_RXTHIEN_Msk
Definition: M4521.h:9427
#define SPI_STATUS_RXFULL_Msk
Definition: M4521.h:9484
#define SPI_FIFOCTL_RXTH_Msk
Definition: M4521.h:9451
#define SPI_I2SCTL_I2SEN_Msk
Definition: M4521.h:9526
#define SPI_STATUS_SLVBEIF_Msk
Definition: M4521.h:9475
#define SPI_STATUS_RXTOIF_Msk
Definition: M4521.h:9493
#define SPI_STATUS_RXEMPTY_Msk
Definition: M4521.h:9481
#define SPI_STATUS_SSLINE_Msk
Definition: M4521.h:9469
#define SPI_SSCTL_SLVURIEN_Msk
Definition: M4521.h:9400
#define SPI_STATUS_TXUFIF_Msk
Definition: M4521.h:9508
#define SPI_STATUS_SLVURIF_Msk
Definition: M4521.h:9478
#define SPI_FIFOCTL_TXFBCLR_Msk
Definition: M4521.h:9448
#define SPI_FIFOCTL_TXTHIEN_Msk
Definition: M4521.h:9430
#define SPI_STATUS_SPIENSTS_Msk
Definition: M4521.h:9496
#define SPI_FIFOCTL_RXFBCLR_Msk
Definition: M4521.h:9445
#define SPI_SSCTL_AUTOSS_Msk
Definition: M4521.h:9385
#define SPI_I2SCTL_MCLKEN_Msk
Definition: M4521.h:9550
#define SPI_STATUS_BUSY_Msk
Definition: M4521.h:9457
#define SPI_I2SCLK_MCLKDIV_Pos
Definition: M4521.h:9570
#define SPI_I2SCLK_BCLKDIV_Pos
Definition: M4521.h:9573
#define CLK_CLKSEL0_PCLK0SEL_HCLK_DIV2
Definition: clk.h:59
#define CLK_CLKSEL0_PCLK1SEL_HCLK_DIV2
Definition: clk.h:62
#define CLK_CLKSEL2_SPI0SEL_HXT
Definition: clk.h:123
#define CLK_CLKSEL2_SPI0SEL_PLL
Definition: clk.h:124
#define CLK_CLKSEL2_SPI1SEL_PCLK1
Definition: clk.h:130
#define CLK_CLKSEL2_SPI1SEL_PLL
Definition: clk.h:129
#define CLK_CLKSEL2_SPI0SEL_PCLK0
Definition: clk.h:125
#define CLK_CLKSEL2_SPI1SEL_HXT
Definition: clk.h:128
uint32_t CLK_GetHCLKFreq(void)
Get HCLK frequency.
Definition: clk.c:175
__STATIC_INLINE uint32_t CLK_GetPLLClockFreq(void)
Get PLL clock frequency.
Definition: clk.h:332
#define CLK_CLKSEL2_SPI1SEL_Msk
Definition: M4521.h:1614
#define CLK_CLKSEL0_PCLK1SEL_Msk
Definition: M4521.h:1575
#define CLK_CLKSEL2_SPI0SEL_Msk
Definition: M4521.h:1611
#define CLK_CLKSEL0_PCLK0SEL_Msk
Definition: M4521.h:1572
__IO uint32_t I2SCLK
Definition: M4521.h:9321
__IO uint32_t I2SCTL
Definition: M4521.h:9320
__IO uint32_t FIFOCTL
Definition: M4521.h:9313
__IO uint32_t STATUS
Definition: M4521.h:9314
__IO uint32_t CTL
Definition: M4521.h:9309
#define CLK
Definition: M4521.h:13822
__IO uint32_t SSCTL
Definition: M4521.h:9311
__IO uint32_t CLKDIV
Definition: M4521.h:9310
#define SPI1
Definition: M4521.h:13849
#define SYS
Definition: M4521.h:13820
#define SPI0
Definition: M4521.h:13848
#define SPI_FIFO_RXTO_INT_MASK
Definition: spi.h:61
#define I2S_FIFO_RXTO_INT_MASK
Definition: spi.h:117
#define SPI_RX_EMPTY_MASK
Definition: spi.h:65
#define SPI_FIFO_RXTH_INT_MASK
Definition: spi.h:59
#define SPI_SLVBE_INT_MASK
Definition: spi.h:55
#define SPI_SSACT_INT_MASK
Definition: spi.h:52
#define SPI_SSLINE_STS_MASK
Definition: spi.h:71
#define SPI_SSINACT_INT_MASK
Definition: spi.h:53
#define I2S_FIFO_TX_LEVEL_WORD_2
Definition: spi.h:97
#define I2S_FIFO_RX_LEVEL_WORD_2
Definition: spi.h:101
#define SPI_SS_ACTIVE_LOW
Definition: spi.h:48
#define SPI_UNIT_INT_MASK
Definition: spi.h:51
#define SPI_FIFO_TXTH_INT_MASK
Definition: spi.h:58
#define SPI_SLVTO_INT_MASK
Definition: spi.h:56
#define SPI_TX_EMPTY_MASK
Definition: spi.h:67
#define SPI_TXRX_RESET_MASK
Definition: spi.h:69
#define SPI_TXUF_INT_MASK
Definition: spi.h:57
#define SPI_FIFO_RXOV_INT_MASK
Definition: spi.h:60
#define SPI_SLVUR_INT_MASK
Definition: spi.h:54
#define SPI_SPIEN_STS_MASK
Definition: spi.h:70
#define I2S_LEFT_ZC_INT_MASK
Definition: spi.h:120
#define SPI_BUSY_MASK
Definition: spi.h:64
#define I2S_TXUF_INT_MASK
Definition: spi.h:118
#define I2S_FIFO_RXTH_INT_MASK
Definition: spi.h:115
#define I2S_RIGHT_ZC_INT_MASK
Definition: spi.h:119
#define I2S_FIFO_TXTH_INT_MASK
Definition: spi.h:114
#define SPI_MASTER
Definition: spi.h:44
#define SPI_TX_FULL_MASK
Definition: spi.h:68
#define SPI_RX_FULL_MASK
Definition: spi.h:66
#define I2S_FIFO_RXOV_INT_MASK
Definition: spi.h:116
static uint32_t I2S_GetSourceClockFreq(SPI_T *i2s)
This function is used to get I2S source clock frequency.
Definition: spi.c:757
void SPI_DisableInt(SPI_T *spi, uint32_t u32Mask)
Disable interrupt function.
Definition: spi.c:524
uint32_t SPI_GetIntFlag(SPI_T *spi, uint32_t u32Mask)
Get interrupt flag.
Definition: spi.c:592
void I2S_SetFIFO(SPI_T *i2s, uint32_t u32TxThreshold, uint32_t u32RxThreshold)
Configure FIFO threshold setting.
Definition: spi.c:1028
void I2S_EnableInt(SPI_T *i2s, uint32_t u32Mask)
Enable interrupt function.
Definition: spi.c:892
void SPI_EnableInt(SPI_T *spi, uint32_t u32Mask)
Enable interrupt function.
Definition: spi.c:456
void SPI_EnableAutoSS(SPI_T *spi, uint32_t u32SSPinMask, uint32_t u32ActiveLevel)
Enable the automatic slave selection function.
Definition: spi.c:253
void SPI_DisableAutoSS(SPI_T *spi)
Disable the automatic slave selection function.
Definition: spi.c:239
void SPI_ClearIntFlag(SPI_T *spi, uint32_t u32Mask)
Clear interrupt flag.
Definition: spi.c:662
uint32_t I2S_EnableMCLK(SPI_T *i2s, uint32_t u32BusClock)
Enable master clock (MCLK).
Definition: spi.c:979
void I2S_Close(SPI_T *i2s)
Disable I2S function.
Definition: spi.c:871
uint32_t SPI_SetBusClock(SPI_T *spi, uint32_t u32BusClock)
Set the SPI bus clock.
Definition: spi.c:270
void SPI_Close(SPI_T *spi)
Disable SPI controller.
Definition: spi.c:194
uint32_t I2S_Open(SPI_T *i2s, uint32_t u32MasterSlave, uint32_t u32SampleRate, uint32_t u32WordWidth, uint32_t u32Channels, uint32_t u32DataFormat)
This function configures some parameters of I2S interface for general purpose use.
Definition: spi.c:808
void SPI_SetFIFO(SPI_T *spi, uint32_t u32TxThreshold, uint32_t u32RxThreshold)
Configure FIFO threshold setting.
Definition: spi.c:371
void I2S_DisableMCLK(SPI_T *i2s)
Disable master clock (MCLK).
Definition: spi.c:1015
uint32_t SPI_GetStatus(SPI_T *spi, uint32_t u32Mask)
Get SPI status.
Definition: spi.c:710
void I2S_DisableInt(SPI_T *i2s, uint32_t u32Mask)
Disable interrupt function.
Definition: spi.c:939
void SPI_ClearTxFIFO(SPI_T *spi)
Clear TX FIFO buffer.
Definition: spi.c:228
uint32_t SPI_Open(SPI_T *spi, uint32_t u32MasterSlave, uint32_t u32SPIMode, uint32_t u32DataWidth, uint32_t u32BusClock)
This function make SPI module be ready to transfer.
Definition: spi.c:45
uint32_t SPI_GetBusClock(SPI_T *spi)
Get the actual frequency of SPI bus clock. Only available in Master mode.
Definition: spi.c:384
void SPI_ClearRxFIFO(SPI_T *spi)
Clear RX FIFO buffer.
Definition: spi.c:216
Definition: M4521.h:8846
#define __HIRC
Definition: system_M4521.h:37
#define __HXT
Definition: system_M4521.h:35