2 * -------------------------------------------
3 * CC3220 SDK - v0.10.00.00
4 * -------------------------------------------
6 * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the
20 * Neither the name of Texas Instruments Incorporated nor the names of
21 * its contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //*****************************************************************************
41 // Driver for the SPI.
43 //*****************************************************************************
45 //*****************************************************************************
47 //! \addtogroup SPI_Serial_Peripheral_Interface_api
50 //*****************************************************************************
53 #include "inc/hw_ints.h"
54 #include "inc/hw_types.h"
55 #include "inc/hw_memmap.h"
56 #include "inc/hw_mcspi.h"
57 #include "inc/hw_apps_config.h"
58 #include "interrupt.h"
62 //*****************************************************************************
64 // A mapping of SPI base address to interupt number.
66 //*****************************************************************************
67 static const unsigned long g_ppulSPIIntMap[][3] =
69 { SSPI_BASE, INT_SSPI }, // Shared SPI
70 { GSPI_BASE, INT_GSPI }, // Generic SPI
71 { LSPI_BASE, INT_LSPI }, // LINK SPI
74 //*****************************************************************************
76 // A mapping of SPI base address to DMA done interrupt mask bit(s).
78 //*****************************************************************************
79 static const unsigned long g_ulSPIDmaMaskMap[][2]=
81 {SSPI_BASE,APPS_CONFIG_DMA_DONE_INT_MASK_SHSPI_WR_DMA_DONE_INT_MASK},
82 {LSPI_BASE,APPS_CONFIG_DMA_DONE_INT_MASK_HOSTSPI_WR_DMA_DONE_INT_MASK},
83 {GSPI_BASE,APPS_CONFIG_DMA_DONE_INT_MASK_APPS_SPI_WR_DMA_DONE_INT_MASK},
86 //*****************************************************************************
89 //! Transfer bytes over SPI channel
91 //! \param ulBase is the base address of SPI module
92 //! \param ucDout is the pointer to Tx data buffer or 0.
93 //! \param ucDin is pointer to Rx data buffer or 0
94 //! \param ulCount is the size of data in bytes.
96 //! This function transfers \e ulCount bytes of data over SPI channel.
98 //! The function will not return until data has been transmitted
100 //! \return Returns 0 on success, -1 otherwise.
102 //*****************************************************************************
103 static long SPITransfer8(unsigned long ulBase, unsigned char *ucDout,
104 unsigned char *ucDin, unsigned long ulCount,
105 unsigned long ulFlags)
107 unsigned long ulReadReg;
108 unsigned long ulWriteReg;
109 unsigned long ulStatReg;
110 unsigned long ulOutIncr;
111 unsigned long ulInIncr;
112 unsigned long ulTxDummy;
113 unsigned long ulRxDummy;
116 // Initialize the variables
122 // Check if output buffer pointer is 0
127 ulTxDummy = 0xFFFFFFFF;
128 ucDout = (unsigned char *)&ulTxDummy;
132 // Check if input buffer pointer is 0
137 ucDin = (unsigned char *)&ulRxDummy;
141 // Load the register addresses.
143 ulReadReg = (ulBase + MCSPI_O_RX0);
144 ulWriteReg = (ulBase + MCSPI_O_TX0);
145 ulStatReg = (ulBase + MCSPI_O_CH0STAT);
148 // Enable CS based on Flag
150 if( ulFlags & SPI_CS_ENABLE)
152 HWREG( ulBase + MCSPI_O_CH0CONF) |= MCSPI_CH0CONF_FORCE;
158 // Wait for space in output register/FIFO.
160 while( !(HWREG(ulStatReg) & MCSPI_CH0STAT_TXS) )
167 HWREG(ulWriteReg) = *ucDout;
170 // Wait for data in input register/FIFO.
172 while( !( HWREG(ulStatReg) & MCSPI_CH0STAT_RXS) )
179 *ucDin = HWREG(ulReadReg);
182 // Increment pointers.
184 ucDout = ucDout + ulOutIncr;
185 ucDin = ucDin + ulInIncr;
188 // Decrement the count.
194 // Disable CS based on Flag
196 if( ulFlags & SPI_CS_DISABLE)
198 HWREG( ulBase + MCSPI_O_CH0CONF) &= ~MCSPI_CH0CONF_FORCE;
204 //*****************************************************************************
207 //! Transfer half-words over SPI channel
209 //! \param ulBase is the base address of SPI module
210 //! \param usDout is the pointer to Tx data buffer or 0.
211 //! \param usDin is pointer to Rx data buffer or 0
212 //! \param ulCount is the size of data in bytes.
214 //! This function transfers \e ulCount bytes of data over SPI channel. Since
215 //! the API sends a half-word at a time \e ulCount should be a multiple
218 //! The function will not return until data has been transmitted
220 //! \return Returns 0 on success, -1 otherwise.
222 //*****************************************************************************
223 static long SPITransfer16(unsigned long ulBase, unsigned short *usDout,
224 unsigned short *usDin, unsigned long ulCount,
225 unsigned long ulFlags)
227 unsigned long ulReadReg;
228 unsigned long ulWriteReg;
229 unsigned long ulStatReg;
230 unsigned long ulOutIncr;
231 unsigned long ulInIncr;
232 unsigned long ulTxDummy;
233 unsigned long ulRxDummy;
236 // Initialize the variables.
242 // Check if count is multiple of half-word
250 // Compute number of half words.
255 // Check if output buffer pointer is 0
260 ulTxDummy = 0xFFFFFFFF;
261 usDout = (unsigned short *)&ulTxDummy;
265 // Check if input buffer pointer is 0
270 usDin = (unsigned short *)&ulRxDummy;
274 // Load the register addresses.
276 ulReadReg = (ulBase + MCSPI_O_RX0);
277 ulWriteReg = (ulBase + MCSPI_O_TX0);
278 ulStatReg = (ulBase + MCSPI_O_CH0STAT);
281 // Enable CS based on Flag
283 if( ulFlags & SPI_CS_ENABLE)
285 HWREG( ulBase + MCSPI_O_CH0CONF) |= MCSPI_CH0CONF_FORCE;
291 // Wait for space in output register/FIFO.
293 while( !(HWREG(ulStatReg) & MCSPI_CH0STAT_TXS) )
300 HWREG(ulWriteReg) = *usDout;
303 // Wait for data in input register/FIFO.
305 while( !( HWREG(ulStatReg) & MCSPI_CH0STAT_RXS) )
312 *usDin = HWREG(ulReadReg);
315 // Increment pointers.
317 usDout = usDout + ulOutIncr;
318 usDin = usDin + ulInIncr;
321 // Decrement the count.
327 // Disable CS based on Flag
329 if( ulFlags & SPI_CS_DISABLE)
331 HWREG( ulBase + MCSPI_O_CH0CONF) &= ~MCSPI_CH0CONF_FORCE;
337 //*****************************************************************************
340 //! Transfer words over SPI channel
342 //! \param ulBase is the base address of SPI module
343 //! \param ulDout is the pointer to Tx data buffer or 0.
344 //! \param ulDin is pointer to Rx data buffer or 0
345 //! \param ulCount is the size of data in bytes.
347 //! This function transfers \e ulCount bytes of data over SPI channel. Since
348 //! the API sends a word at a time \e ulCount should be a multiple of four.
350 //! The function will not return until data has been transmitted
352 //! \return Returns 0 on success, -1 otherwise.
354 //*****************************************************************************
355 static long SPITransfer32(unsigned long ulBase, unsigned long *ulDout,
356 unsigned long *ulDin, unsigned long ulCount,
357 unsigned long ulFlags)
359 unsigned long ulReadReg;
360 unsigned long ulWriteReg;
361 unsigned long ulStatReg;
362 unsigned long ulOutIncr;
363 unsigned long ulInIncr;
364 unsigned long ulTxDummy;
365 unsigned long ulRxDummy;
368 // Initialize the variables.
374 // Check if count is multiple of word
382 // Compute the number of words to be transferd
387 // Check if output buffer pointer is 0
392 ulTxDummy = 0xFFFFFFFF;
397 // Check if input buffer pointer is 0
407 // Load the register addresses.
409 ulReadReg = (ulBase + MCSPI_O_RX0);
410 ulWriteReg = (ulBase + MCSPI_O_TX0);
411 ulStatReg = (ulBase + MCSPI_O_CH0STAT);
414 // Enable CS based on Flag
416 if( ulFlags & SPI_CS_ENABLE)
418 HWREG( ulBase + MCSPI_O_CH0CONF) |= MCSPI_CH0CONF_FORCE;
424 // Wait for space in output register/FIFO.
426 while( !(HWREG(ulStatReg) & MCSPI_CH0STAT_TXS) )
433 HWREG(ulWriteReg) = *ulDout;
436 // Wait for data in input register/FIFO.
438 while( !( HWREG(ulStatReg) & MCSPI_CH0STAT_RXS) )
445 *ulDin = HWREG(ulReadReg);
448 // Increment pointers.
450 ulDout = ulDout + ulOutIncr;
451 ulDin = ulDin + ulInIncr;
454 // Decrement the count.
460 // Disable CS based on Flag
462 if( ulFlags & SPI_CS_DISABLE)
464 HWREG( ulBase + MCSPI_O_CH0CONF) &= ~MCSPI_CH0CONF_FORCE;
470 //*****************************************************************************
473 //! Gets the SPI interrupt number.
475 //! \param ulBase is the base address of the SPI module
477 //! Given a SPI base address, returns the corresponding interrupt number.
479 //! \return Returns a SPI interrupt number, or -1 if \e ulBase is invalid.
481 //*****************************************************************************
483 SPIIntNumberGet(unsigned long ulBase)
488 // Loop through the table that maps SPI base addresses to interrupt
491 for(ulIdx = 0; ulIdx < (sizeof(g_ppulSPIIntMap) /
492 sizeof(g_ppulSPIIntMap[0])); ulIdx++)
495 // See if this base address matches.
497 if(g_ppulSPIIntMap[ulIdx][0] == ulBase)
500 // Return the corresponding interrupt number.
502 return(g_ppulSPIIntMap[ulIdx][1]);
507 // The base address could not be found, so return an error.
512 //*****************************************************************************
515 //! Gets the SPI DMA interrupt mask bit.
517 //! \param ulBase is the base address of the SPI module
519 //! Given a SPI base address, DMA interrupt mask bit.
521 //! \return Returns a DMA interrupt mask bit, or -1 if \e ulBase is invalid.
523 //*****************************************************************************
525 SPIDmaMaskGet(unsigned long ulBase)
530 // Loop through the table that maps SPI base addresses to interrupt
533 for(ulIdx = 0; ulIdx < (sizeof(g_ulSPIDmaMaskMap) /
534 sizeof(g_ulSPIDmaMaskMap[0])); ulIdx++)
537 // See if this base address matches.
539 if(g_ulSPIDmaMaskMap[ulIdx][0] == ulBase)
542 // Return the corresponding interrupt number.
544 return(g_ulSPIDmaMaskMap[ulIdx][1]);
549 // The base address could not be found, so return an error.
554 //*****************************************************************************
556 //! Enables transmitting and receiving.
558 //! \param ulBase is the base address of the SPI module
560 //! This function enables the SPI channel for transmitting and receiving.
565 //*****************************************************************************
567 SPIEnable(unsigned long ulBase)
570 // Set Channel Enable Bit
572 HWREG(ulBase + MCSPI_O_CH0CTRL) |= MCSPI_CH0CTRL_EN;
575 //*****************************************************************************
577 //! Disables the transmitting and receiving.
579 //! \param ulBase is the base address of the SPI module
581 //! This function disables the SPI channel for transmitting and receiving.
586 //*****************************************************************************
588 SPIDisable(unsigned long ulBase)
591 // Reset Channel Enable Bit
593 HWREG(ulBase + MCSPI_O_CH0CTRL) &= ~MCSPI_CH0CTRL_EN;
597 //*****************************************************************************
599 //! Enables the SPI DMA operation for transmitting and/or receving.
601 //! \param ulBase is the base address of the SPI module
602 //! \param ulFlags selectes the DMA signal for transmit and/or receive.
604 //! This function enables transmit and/or receive DMA request based on the
605 //! \e ulFlags parameter.
607 //! The parameter \e ulFlags is the logical OR of one or more of
614 //*****************************************************************************
616 SPIDmaEnable(unsigned long ulBase, unsigned long ulFlags)
619 // Enable DMA based on ulFlags
621 HWREG(ulBase + MCSPI_O_CH0CONF) |= ulFlags;
624 //*****************************************************************************
626 //! Disables the SPI DMA operation for transmitting and/or receving.
628 //! \param ulBase is the base address of the SPI module
629 //! \param ulFlags selectes the DMA signal for transmit and/or receive.
631 //! This function disables transmit and/or receive DMA request based on the
632 //! \e ulFlags parameter.
634 //! The parameter \e ulFlags is the logical OR of one or more of
641 //*****************************************************************************
643 SPIDmaDisable(unsigned long ulBase, unsigned long ulFlags)
646 // Disable DMA based on ulFlags
648 HWREG(ulBase + MCSPI_O_CH0CONF) &= ~ulFlags;
651 //*****************************************************************************
653 //! Performs a software reset of the specified SPI module
655 //! \param ulBase is the base address of the SPI module
657 //! This function performs a software reset of the specified SPI module
661 //*****************************************************************************
663 SPIReset(unsigned long ulBase)
667 // Assert soft reset (auto clear)
669 HWREG(ulBase + MCSPI_O_SYSCONFIG) |= MCSPI_SYSCONFIG_SOFTRESET;
672 // wait until reset is done
674 while(!(HWREG(ulBase + MCSPI_O_SYSSTATUS)& MCSPI_SYSSTATUS_RESETDONE))
679 //*****************************************************************************
681 //! Sets the configuration of a SPI module
683 //! \param ulBase is the base address of the SPI module
684 //! \param ulSPIClk is the rate of clock supplied to the SPI module.
685 //! \param ulBitRate is the desired bit rate.(master mode)
686 //! \param ulMode is the mode of operation.
687 //! \param ulSubMode is one of the valid sub-modes.
688 //! \param ulConfig is logical OR of configuration paramaters.
690 //! This function configures SPI port for operation in specified sub-mode and
691 //! required bit rated as specified by \e ulMode and \e ulBitRate parameters
694 //! The SPI module can operate in either master or slave mode. The parameter
695 //! \e ulMode can be one of the following
696 //! -\b SPI_MODE_MASTER
697 //! -\b SPI_MODE_SLAVE
699 //! The SPI module supports 4 sub modes based on SPI clock polarity and phase.
702 //! Polarity Phase Sub-Mode
709 //! Required sub mode can be select by setting \e ulSubMode parameter to one
711 //! - \b SPI_SUB_MODE_0
712 //! - \b SPI_SUB_MODE_1
713 //! - \b SPI_SUB_MODE_2
714 //! - \b SPI_SUB_MODE_3
716 //! The parameter \e ulConfig is logical OR of five values: the word length,
717 //! active level for chip select, software or hardware controled chip select,
718 //! 3 or 4 pin mode and turbo mode.
721 //! SPI support 8, 16 and 32 bit word lengths defined by:-
726 //! Active state of Chip[ Selece can be defined by:-
727 //! - \b SPI_CS_ACTIVELOW
728 //! - \b SPI_CS_ACTIVEHIGH
730 //! SPI chip select can be configured to be controlled either by hardware or
735 //! The module can work in 3 or 4 pin mode defined by:-
736 //! - \b SPI_3PIN_MODE
737 //! - \b SPI_4PIN_MODE
739 //! Turbo mode can be set on or turned off using:-
740 //! - \b SPI_TURBO_MODE_ON
741 //! - \b SPI_TURBO_MODE_OFF
745 //*****************************************************************************
747 SPIConfigSetExpClk(unsigned long ulBase,unsigned long ulSPIClk,
748 unsigned long ulBitRate, unsigned long ulMode,
749 unsigned long ulSubMode, unsigned long ulConfig)
752 unsigned long ulRegData;
753 unsigned long ulDivider;
756 // Read MODULCTRL register
758 ulRegData = HWREG(ulBase + MCSPI_O_MODULCTRL);
761 // Set Master mode with h/w chip select
763 ulRegData &= ~(MCSPI_MODULCTRL_MS |
764 MCSPI_MODULCTRL_SINGLE);
767 // Enable software control Chip Select, Init delay
770 ulRegData |= (((ulConfig >> 24) | ulMode) & 0xFF);
773 // Write the configuration
775 HWREG(ulBase + MCSPI_O_MODULCTRL) = ulRegData;
778 // Set IS, DPE0, DPE1 based on master or slave mode
780 if(ulMode == SPI_MODE_MASTER)
782 ulRegData = 0x1 << 16;
786 ulRegData = 0x6 << 16;
790 // Mask the configurations and set clock divider granularity
793 ulRegData = (ulRegData & ~(MCSPI_CH0CONF_WL_M |
797 MCSPI_CH0CONF_TURBO ) |
801 // Get the divider value
803 ulDivider = ((ulSPIClk/ulBitRate) - 1);
806 // The least significant four bits of the divider is used fo configure
807 // CLKD in MCSPI_CHCONF next eight least significant bits are used to
808 // configure the EXTCLK in MCSPI_CHCTRL
810 ulRegData |= ((ulDivider & 0x0000000F) << 2);
811 HWREG(ulBase + MCSPI_O_CH0CTRL) = ((ulDivider & 0x00000FF0) << 4);
814 // Set the protocol, CS polarity, word length
817 ulRegData = ((ulRegData |
818 ulSubMode) | (ulConfig & 0x0008FFFF));
821 // Write back the CONF register
823 HWREG(ulBase + MCSPI_O_CH0CONF) = ulRegData;
827 //*****************************************************************************
829 //! Receives a word from the specified port.
831 //! \param ulBase is the base address of the SPI module.
832 //! \param pulData is pointer to receive data variable.
834 //! This function gets a SPI word from the receive FIFO for the specified
837 //! \return Returns the number of elements read from the receive FIFO.
839 //*****************************************************************************
841 SPIDataGetNonBlocking(unsigned long ulBase, unsigned long *pulData)
843 unsigned long ulRegVal;
846 // Read register status register
848 ulRegVal = HWREG(ulBase + MCSPI_O_CH0STAT);
851 // Check is data is available
853 if(ulRegVal & MCSPI_CH0STAT_RXS)
855 *pulData = HWREG(ulBase + MCSPI_O_RX0);
862 //*****************************************************************************
864 //! Waits for the word to be received on the specified port.
866 //! \param ulBase is the base address of the SPI module.
867 //! \param pulData is pointer to receive data variable.
869 //! This function gets a SPI word from the receive FIFO for the specified
870 //! port. If there is no word available, this function waits until a
871 //! word is received before returning.
873 //! \return Returns the word read from the specified port, cast as an
874 //! \e unsigned long.
876 //*****************************************************************************
878 SPIDataGet(unsigned long ulBase, unsigned long *pulData)
883 while(!(HWREG(ulBase + MCSPI_O_CH0STAT) & MCSPI_CH0STAT_RXS))
890 *pulData = HWREG(ulBase + MCSPI_O_RX0);
893 //*****************************************************************************
895 //! Transmits a word on the specified port.
897 //! \param ulBase is the base address of the SPI module
898 //! \param ulData is data to be transmitted.
900 //! This function transmits a SPI word on the transmit FIFO for the specified
903 //! \return Returns the number of elements written to the transmit FIFO.
905 //*****************************************************************************
907 SPIDataPutNonBlocking(unsigned long ulBase, unsigned long ulData)
909 unsigned long ulRegVal;
912 // Read status register
914 ulRegVal = HWREG(ulBase + MCSPI_O_CH0STAT);
917 // Write value into Tx register/FIFO
918 // if space is available
920 if(ulRegVal & MCSPI_CH0STAT_TXS)
922 HWREG(ulBase + MCSPI_O_TX0) = ulData;
929 //*****************************************************************************
931 //! Waits until the word is transmitted on the specified port.
933 //! \param ulBase is the base address of the SPI module
934 //! \param ulData is data to be transmitted.
936 //! This function transmits a SPI word on the transmit FIFO for the specified
937 //! port. This function waits until the space is available on transmit FIFO
941 //*****************************************************************************
943 SPIDataPut(unsigned long ulBase, unsigned long ulData)
946 // Wait for space in FIFO
948 while(!(HWREG(ulBase + MCSPI_O_CH0STAT)&MCSPI_CH0STAT_TXS))
955 HWREG(ulBase + MCSPI_O_TX0) = ulData;
958 //*****************************************************************************
960 //! Enables the transmit and/or receive FIFOs.
962 //! \param ulBase is the base address of the SPI module
963 //! \param ulFlags selects the FIFO(s) to be enabled
965 //! This function enables the transmit and/or receive FIFOs as specified by
967 //! The parameter \e ulFlags shoulde be logical OR of one or more of the
974 //*****************************************************************************
976 SPIFIFOEnable(unsigned long ulBase, unsigned long ulFlags)
979 // Set FIFO enable bits.
981 HWREG(ulBase + MCSPI_O_CH0CONF) |= ulFlags;
984 //*****************************************************************************
986 //! Disables the transmit and/or receive FIFOs.
988 //! \param ulBase is the base address of the SPI module
989 //! \param ulFlags selects the FIFO(s) to be enabled
991 //! This function disables transmit and/or receive FIFOs. as specified by
993 //! The parameter \e ulFlags shoulde be logical OR of one or more of the
1000 //*****************************************************************************
1002 SPIFIFODisable(unsigned long ulBase, unsigned long ulFlags)
1005 // Reset FIFO Enable bits.
1007 HWREG(ulBase + MCSPI_O_CH0CONF) &= ~(ulFlags);
1010 //*****************************************************************************
1012 //! Sets the FIFO level at which DMA requests or interrupts are generated.
1014 //! \param ulBase is the base address of the SPI module
1015 //! \param ulTxLevel is the Almost Empty Level for transmit FIFO.
1016 //! \param ulRxLevel is the Almost Full Level for the receive FIFO.
1018 //! This function Sets the FIFO level at which DMA requests or interrupts
1023 //*****************************************************************************
1024 void SPIFIFOLevelSet(unsigned long ulBase, unsigned long ulTxLevel,
1025 unsigned long ulRxLevel)
1027 unsigned long ulRegVal;
1030 // Read the current configuration
1032 ulRegVal = HWREG(ulBase + MCSPI_O_XFERLEVEL);
1035 // Mask and set new FIFO thresholds.
1037 ulRegVal = ((ulRegVal & 0xFFFF0000) | (((ulRxLevel-1) << 8) | (ulTxLevel-1)));
1040 // Set the transmit and receive FIFO thresholds.
1042 HWREG(ulBase + MCSPI_O_XFERLEVEL) = ulRegVal;
1046 //*****************************************************************************
1048 //! Gets the FIFO level at which DMA requests or interrupts are generated.
1050 //! \param ulBase is the base address of the SPI module
1051 //! \param pulTxLevel is a pointer to storage for the transmit FIFO level
1052 //! \param pulRxLevel is a pointer to storage for the receive FIFO level
1054 //! This function gets the FIFO level at which DMA requests or interrupts
1059 //*****************************************************************************
1061 SPIFIFOLevelGet(unsigned long ulBase, unsigned long *pulTxLevel,
1062 unsigned long *pulRxLevel)
1064 unsigned long ulRegVal;
1067 // Read the current configuration
1069 ulRegVal = HWREG(ulBase + MCSPI_O_XFERLEVEL);
1071 *pulTxLevel = (ulRegVal & 0xFF);
1073 *pulRxLevel = ((ulRegVal >> 8) & 0xFF);
1077 //*****************************************************************************
1079 //! Sets the word count.
1081 //! \param ulBase is the base address of the SPI module
1082 //! \param ulWordCount is number of SPI words to be transmitted.
1084 //! This function sets the word count, which is the number of SPI word to
1085 //! be transferred on channel when using the FIFO buffer.
1089 //*****************************************************************************
1091 SPIWordCountSet(unsigned long ulBase, unsigned long ulWordCount)
1093 unsigned long ulRegVal;
1096 // Read the current configuration
1098 ulRegVal = HWREG(ulBase + MCSPI_O_XFERLEVEL);
1101 // Mask and set the word count
1103 HWREG(ulBase + MCSPI_O_XFERLEVEL) = ((ulRegVal & 0x0000FFFF)|
1104 (ulWordCount & 0xFFFF) << 16);
1107 //*****************************************************************************
1109 //! Registers an interrupt handler for a SPI interrupt.
1111 //! \param ulBase is the base address of the SPI module
1112 //! \param pfnHandler is a pointer to the function to be called when the
1113 //! SPI interrupt occurs.
1115 //! This function does the actual registering of the interrupt handler. This
1116 //! function enables the global interrupt in the interrupt controller; specific
1117 //! SPI interrupts must be enabled via SPIIntEnable(). It is the interrupt
1118 //! handler's responsibility to clear the interrupt source.
1120 //! \sa IntRegister() for important information about registering interrupt
1125 //*****************************************************************************
1127 SPIIntRegister(unsigned long ulBase, void(*pfnHandler)(void))
1129 unsigned long ulInt;
1132 // Determine the interrupt number based on the SPI module
1134 ulInt = SPIIntNumberGet(ulBase);
1137 // Register the interrupt handler.
1139 IntRegister(ulInt, pfnHandler);
1142 // Enable the SPI interrupt.
1147 //*****************************************************************************
1149 //! Unregisters an interrupt handler for a SPI interrupt.
1151 //! \param ulBase is the base address of the SPI module
1153 //! This function does the actual unregistering of the interrupt handler. It
1154 //! clears the handler to be called when a SPI interrupt occurs. This
1155 //! function also masks off the interrupt in the interrupt controller so that
1156 //! the interrupt handler no longer is called.
1158 //! \sa IntRegister() for important information about registering interrupt
1163 //*****************************************************************************
1165 SPIIntUnregister(unsigned long ulBase)
1167 unsigned long ulInt;
1170 // Determine the interrupt number based on the SPI module
1172 ulInt = SPIIntNumberGet(ulBase);
1175 // Disable the interrupt.
1180 // Unregister the interrupt handler.
1182 IntUnregister(ulInt);
1185 //*****************************************************************************
1187 //! Enables individual SPI interrupt sources.
1189 //! \param ulBase is the base address of the SPI module
1190 //! \param ulIntFlags is the bit mask of the interrupt sources to be enabled.
1192 //! This function enables the indicated SPI interrupt sources. Only the
1193 //! sources that are enabled can be reflected to the processor interrupt;
1194 //! disabled sources have no effect on the processor.
1196 //! The \e ulIntFlags parameter is the logical OR of any of the following:
1198 //! - \b SPI_INT_DMATX
1199 //! - \b SPI_INT_DMARX
1200 //! - \b SPI_INT_EOW
1201 //! - \b SPI_INT_RX_OVRFLOW
1202 //! - \b SPI_INT_RX_FULL
1203 //! - \b SPI_INT_TX_UDRFLOW
1204 //! - \b SPI_INT_TX_EMPTY
1208 //*****************************************************************************
1210 SPIIntEnable(unsigned long ulBase, unsigned long ulIntFlags)
1212 unsigned long ulDmaMsk;
1215 // Enable DMA Tx Interrupt
1217 if(ulIntFlags & SPI_INT_DMATX)
1219 ulDmaMsk = SPIDmaMaskGet(ulBase);
1220 HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR) = ulDmaMsk;
1224 // Enable DMA Rx Interrupt
1226 if(ulIntFlags & SPI_INT_DMARX)
1228 ulDmaMsk = (SPIDmaMaskGet(ulBase) >> 1);
1229 HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_CLR) = ulDmaMsk;
1233 // Enable the specific Interrupts
1235 HWREG(ulBase + MCSPI_O_IRQENABLE) |= (ulIntFlags & 0x0003000F);
1239 //*****************************************************************************
1241 //! Disables individual SPI interrupt sources.
1243 //! \param ulBase is the base address of the SPI module
1244 //! \param ulIntFlags is the bit mask of the interrupt sources to be disabled.
1246 //! This function disables the indicated SPI interrupt sources. Only the
1247 //! sources that are enabled can be reflected to the processor interrupt;
1248 //! disabled sources have no effect on the processor.
1250 //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags
1251 //! parameter to SPIIntEnable().
1255 //*****************************************************************************
1257 SPIIntDisable(unsigned long ulBase, unsigned long ulIntFlags)
1259 unsigned long ulDmaMsk;
1262 // Disable DMA Tx Interrupt
1264 if(ulIntFlags & SPI_INT_DMATX)
1266 ulDmaMsk = SPIDmaMaskGet(ulBase);
1267 HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_SET) = ulDmaMsk;
1271 // Disable DMA Tx Interrupt
1273 if(ulIntFlags & SPI_INT_DMARX)
1275 ulDmaMsk = (SPIDmaMaskGet(ulBase) >> 1);
1276 HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_MASK_SET) = ulDmaMsk;
1280 // Disable the specific Interrupts
1282 HWREG(ulBase + MCSPI_O_IRQENABLE) &= ~(ulIntFlags & 0x0003000F);
1285 //*****************************************************************************
1287 //! Gets the current interrupt status.
1289 //! \param ulBase is the base address of the SPI module
1290 //! \param bMasked is \b false if the raw interrupt status is required and
1291 //! \b true if the masked interrupt status is required.
1293 //! This function returns the interrupt status for the specified SPI.
1294 //! The status of interrupts that are allowed to reflect to the processor can
1297 //! \return Returns the current interrupt status, enumerated as a bit field of
1298 //! values described in SPIIntEnable().
1300 //*****************************************************************************
1302 SPIIntStatus(unsigned long ulBase, tBoolean bMasked)
1304 unsigned long ulIntStat;
1305 unsigned long ulIntFlag;
1306 unsigned long ulDmaMsk;
1309 // Get SPI interrupt status
1311 ulIntFlag = HWREG(ulBase + MCSPI_O_IRQSTATUS) & 0x0003000F;
1315 ulIntFlag &= HWREG(ulBase + MCSPI_O_IRQENABLE);
1319 // Get the interrupt bit
1321 ulDmaMsk = SPIDmaMaskGet(ulBase);
1324 // Get the DMA interrupt status
1328 ulIntStat = HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_STS_MASKED);
1332 ulIntStat = HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_STS_RAW);
1336 // Get SPI Tx DMA done status
1338 if(ulIntStat & ulDmaMsk)
1340 ulIntFlag |= SPI_INT_DMATX;
1344 // Get SPI Rx DMA done status
1346 if(ulIntStat & (ulDmaMsk >> 1))
1348 ulIntFlag |= SPI_INT_DMARX;
1357 //*****************************************************************************
1359 //! Clears SPI interrupt sources.
1361 //! \param ulBase is the base address of the SPI module
1362 //! \param ulIntFlags is a bit mask of the interrupt sources to be cleared.
1364 //! The specified SPI interrupt sources are cleared, so that they no longer
1365 //! assert. This function must be called in the interrupt handler to keep the
1366 //! interrupt from being recognized again immediately upon exit.
1368 //! The \e ulIntFlags parameter has the same definition as the \e ulIntFlags
1369 //! parameter to SPIIntEnable().
1373 //*****************************************************************************
1375 SPIIntClear(unsigned long ulBase, unsigned long ulIntFlags)
1377 unsigned long ulDmaMsk;
1380 // Disable DMA Tx Interrupt
1382 if(ulIntFlags & SPI_INT_DMATX)
1384 ulDmaMsk = SPIDmaMaskGet(ulBase);
1385 HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_ACK) = ulDmaMsk;
1389 // Disable DMA Tx Interrupt
1391 if(ulIntFlags & SPI_INT_DMARX)
1393 ulDmaMsk = (SPIDmaMaskGet(ulBase) >> 1);
1394 HWREG(APPS_CONFIG_BASE + APPS_CONFIG_O_DMA_DONE_INT_ACK) = ulDmaMsk;
1400 HWREG(ulBase + MCSPI_O_IRQSTATUS) = (ulIntFlags & 0x0003000F);
1403 //*****************************************************************************
1405 //! Enables the chip select in software controlled mode
1407 //! \param ulBase is the base address of the SPI module.
1409 //! This function enables the Chip select in software controlled mode. The
1410 //! active state of CS will depend on the configuration done via
1411 //! \sa SPIConfigExpClkSet().
1415 //*****************************************************************************
1416 void SPICSEnable(unsigned long ulBase)
1419 // Set Chip Select enable bit.
1421 HWREG( ulBase+MCSPI_O_CH0CONF) |= MCSPI_CH0CONF_FORCE;
1424 //*****************************************************************************
1426 //! Disables the chip select in software controlled mode
1428 //! \param ulBase is the base address of the SPI module.
1430 //! This function disables the Chip select in software controlled mode. The
1431 //! active state of CS will depend on the configuration done via
1432 //! sa SPIConfigSetExpClk().
1436 //*****************************************************************************
1437 void SPICSDisable(unsigned long ulBase)
1440 // Reset Chip Select enable bit.
1442 HWREG( ulBase+MCSPI_O_CH0CONF) &= ~MCSPI_CH0CONF_FORCE;
1445 //*****************************************************************************
1447 //! Send/Receive data buffer over SPI channel
1449 //! \param ulBase is the base address of SPI module
1450 //! \param ucDout is the pointer to Tx data buffer or 0.
1451 //! \param ucDin is pointer to Rx data buffer or 0
1452 //! \param ulCount is the size of data in bytes.
1453 //! \param ulFlags controlls chip select toggling.
1455 //! This function transfers \e ulCount bytes of data over SPI channel. Since
1456 //! the API sends a SPI word at a time \e ulCount should be a multiple of
1457 //! word length set using SPIConfigSetExpClk().
1459 //! If the \e ucDout parameter is set to 0, the function will send 0xFF over
1460 //! the SPI MOSI line.
1462 //! If the \e ucDin parameter is set to 0, the function will ignore data on SPI
1465 //! The parameter \e ulFlags is logical OR of one or more of the following
1467 //! - \b SPI_CS_ENABLE if CS needs to be enabled at start of transfer.
1468 //! - \b SPI_CS_DISABLE if CS need to be disabled at the end of transfer.
1470 //! This function will not return until data has been transmitted
1472 //! \return Returns 0 on success, -1 otherwise.
1474 //*****************************************************************************
1475 long SPITransfer(unsigned long ulBase, unsigned char *ucDout,
1476 unsigned char *ucDin, unsigned long ulCount,
1477 unsigned long ulFlags)
1479 unsigned long ulWordLength;
1483 // Get the word length
1485 ulWordLength = (HWREG(ulBase + MCSPI_O_CH0CONF) & MCSPI_CH0CONF_WL_M);
1488 // Check for word length.
1490 if( !((ulWordLength == SPI_WL_8) || (ulWordLength == SPI_WL_16) ||
1491 (ulWordLength == SPI_WL_32)) )
1496 if( ulWordLength == SPI_WL_8 )
1501 lRet = SPITransfer8(ulBase,ucDout,ucDin,ulCount,ulFlags);
1503 else if( ulWordLength == SPI_WL_16 )
1507 // Do half-word transfer
1509 lRet = SPITransfer16(ulBase,(unsigned short *)ucDout,
1510 (unsigned short *)ucDin,ulCount,ulFlags);
1517 lRet = SPITransfer32(ulBase,(unsigned long *)ucDout,
1518 (unsigned long *)ucDin,ulCount,ulFlags);
1527 //*****************************************************************************
1529 // Close the Doxygen group.
1532 //*****************************************************************************