1 /* ----------------------------------------------------------------------------
\r
2 * SAM Software Package License
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2011, Atmel Corporation
\r
6 * All rights reserved.
\r
8 * Redistribution and use in source and binary forms, with or without
\r
9 * modification, are permitted provided that the following conditions are met:
\r
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\r
14 * Atmel's name may not be used to endorse or promote products derived from
\r
15 * this software without specific prior written permission.
\r
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
\r
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
\r
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
\r
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
\r
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
27 * ----------------------------------------------------------------------------
\r
30 /** \addtogroup spi_module Working with SPI
\r
31 * The SPI driver provides the interface to configure and use the SPI
\r
34 * The Serial Peripheral Interface (SPI) circuit is a synchronous serial
\r
35 * data link that provides communication with external devices in Master
\r
38 * To use the SPI, the user has to follow these few steps:
\r
39 * -# Enable the SPI pins required by the application (see pio.h).
\r
40 * -# Configure the SPI using the \ref SPI_Configure(). This enables the
\r
41 * peripheral clock. The mode register is loaded with the given value.
\r
42 * -# Configure all the necessary chip selects with \ref SPI_ConfigureNPCS().
\r
43 * -# Enable the SPI by calling \ref SPI_Enable().
\r
44 * -# Send/receive data using \ref SPI_Write() and \ref SPI_Read(). Note that \ref SPI_Read()
\r
45 * must be called after \ref SPI_Write() to retrieve the last value read.
\r
46 * -# Disable the SPI by calling \ref SPI_Disable().
\r
48 * For more accurate information, please look at the SPI section of the
\r
61 * Implementation of Serial Peripheral Interface (SPI) controller.
\r
65 /*----------------------------------------------------------------------------
\r
67 *----------------------------------------------------------------------------*/
\r
73 /*----------------------------------------------------------------------------
\r
74 * Exported functions
\r
75 *----------------------------------------------------------------------------*/
\r
78 * \brief Enables a SPI peripheral.
\r
80 * \param spi Pointer to an Spi instance.
\r
82 extern void SPI_Enable( Spi* spi )
\r
84 spi->SPI_CR = SPI_CR_SPIEN ;
\r
88 * \brief Disables a SPI peripheral.
\r
90 * \param spi Pointer to an Spi instance.
\r
92 extern void SPI_Disable( Spi* spi )
\r
94 spi->SPI_CR = SPI_CR_SPIDIS ;
\r
98 * \brief Enables one or more interrupt sources of a SPI peripheral.
\r
100 * \param spi Pointer to an Spi instance.
\r
101 * \param sources Bitwise OR of selected interrupt sources.
\r
103 extern void SPI_EnableIt( Spi* spi, uint32_t dwSources )
\r
105 spi->SPI_IER = dwSources ;
\r
109 * \brief Disables one or more interrupt sources of a SPI peripheral.
\r
111 * \param spi Pointer to an Spi instance.
\r
112 * \param sources Bitwise OR of selected interrupt sources.
\r
114 extern void SPI_DisableIt( Spi* spi, uint32_t dwSources )
\r
116 spi->SPI_IDR = dwSources ;
\r
120 * \brief Configures a SPI peripheral as specified. The configuration can be computed
\r
121 * using several macros (see \ref spi_configuration_macros).
\r
123 * \param spi Pointer to an Spi instance.
\r
124 * \param id Peripheral ID of the SPI.
\r
125 * \param configuration Value of the SPI configuration register.
\r
127 extern void SPI_Configure( Spi* spi, uint32_t dwId, uint32_t dwConfiguration )
\r
129 PMC_EnablePeripheral( dwId ) ;
\r
131 spi->SPI_CR = SPI_CR_SPIDIS ;
\r
133 /* Execute a software reset of the SPI twice */
\r
134 spi->SPI_CR = SPI_CR_SWRST ;
\r
135 spi->SPI_CR = SPI_CR_SWRST ;
\r
136 spi->SPI_MR = dwConfiguration ;
\r
140 * \brief Configures SPI chip select.
\r
142 * \param spi Pointer to an Spi instance.
\r
143 * \param cS Chip select of NPSCx.
\r
145 extern void SPI_ChipSelect( Spi* spi, uint8_t cS)
\r
147 spi->SPI_MR |= SPI_MR_PCS_Msk ;
\r
148 spi->SPI_MR &= ~(SPI_MR_PCS ( cS )) ;
\r
152 * \brief Configures SPI Mode Register.
\r
154 * \param spi Pointer to an Spi instance.
\r
155 * \param configuration Value of the SPI mode register.
\r
157 extern void SPI_SetMode( Spi* spi,
\r
158 uint32_t dwConfiguration )
\r
160 spi->SPI_MR = dwConfiguration ;
\r
164 * \brief Configures SPI to release last used CS line.
\r
166 * \param spi Pointer to an Spi instance.
\r
168 extern void SPI_ReleaseCS( Spi* spi )
\r
170 spi->SPI_CR = SPI_CR_LASTXFER ;
\r
175 * \brief Configures a chip select of a SPI peripheral. The chip select configuration
\r
176 * is computed using several macros (see \ref spi_configuration_macros).
\r
178 * \param spi Pointer to an Spi instance.
\r
179 * \param npcs Chip select to configure (0, 1, 2 or 3).
\r
180 * \param configuration Desired chip select configuration.
\r
182 void SPI_ConfigureNPCS( Spi* spi, uint32_t dwNpcs, uint32_t dwConfiguration )
\r
184 spi->SPI_CSR[dwNpcs] = dwConfiguration ;
\r
188 * \brief Configures a chip select active mode of a SPI peripheral.
\r
190 * \param spi Pointer to an Spi instance.
\r
191 * \param dwNpcs Chip select to configure (0, 1, 2 or 3).
\r
192 * \param bReleaseOnLast CS controlled by last transfer.
\r
193 * SPI_ReleaseCS() is used to deactive CS.
\r
195 void SPI_ConfigureCSMode( Spi* spi, uint32_t dwNpcs, uint32_t bReleaseOnLast )
\r
197 if (bReleaseOnLast)
\r
199 spi->SPI_CSR[dwNpcs] |= SPI_CSR_CSAAT;
\r
203 spi->SPI_CSR[dwNpcs] &= ~SPI_CSR_CSAAT;
\r
208 * \brief Get the current status register of the given SPI peripheral.
\r
209 * \note This resets the internal value of the status register, so further
\r
210 * read may yield different values.
\r
211 * \param spi Pointer to a Spi instance.
\r
212 * \return SPI status register.
\r
214 extern uint32_t SPI_GetStatus( Spi* spi )
\r
216 return spi->SPI_SR ;
\r
220 * \brief Reads and returns the last word of data received by a SPI peripheral. This
\r
221 * method must be called after a successful SPI_Write call.
\r
223 * \param spi Pointer to an Spi instance.
\r
225 * \return readed data.
\r
227 extern uint32_t SPI_Read( Spi* spi )
\r
229 while ( (spi->SPI_SR & SPI_SR_RDRF) == 0 ) ;
\r
231 return spi->SPI_RDR & 0xFFFF ;
\r
235 * \brief Sends data through a SPI peripheral. If the SPI is configured to use a fixed
\r
236 * peripheral select, the npcs value is meaningless. Otherwise, it identifies
\r
237 * the component which shall be addressed.
\r
239 * \param spi Pointer to an Spi instance.
\r
240 * \param npcs Chip select of the component to address (0, 1, 2 or 3).
\r
241 * \param data Word of data to send.
\r
243 extern void SPI_Write( Spi* spi, uint32_t dwNpcs, uint16_t wData )
\r
246 while ( (spi->SPI_SR & SPI_SR_TXEMPTY) == 0 ) ;
\r
247 spi->SPI_TDR = wData | SPI_PCS( dwNpcs ) ;
\r
248 while ( (spi->SPI_SR & SPI_SR_TDRE) == 0 ) ;
\r
252 * \brief Sends last data through a SPI peripheral.
\r
253 * If the SPI is configured to use a fixed peripheral select, the npcs value is
\r
254 * meaningless. Otherwise, it identifies the component which shall be addressed.
\r
256 * \param spi Pointer to an Spi instance.
\r
257 * \param npcs Chip select of the component to address (0, 1, 2 or 3).
\r
258 * \param data Word of data to send.
\r
260 extern void SPI_WriteLast( Spi* spi, uint32_t dwNpcs, uint16_t wData )
\r
263 while ( (spi->SPI_SR & SPI_SR_TXEMPTY) == 0 ) ;
\r
264 spi->SPI_TDR = wData | SPI_PCS( dwNpcs ) | SPI_TDR_LASTXFER ;
\r
265 while ( (spi->SPI_SR & SPI_SR_TDRE) == 0 ) ;
\r
269 * \brief Check if SPI transfer finish.
\r
271 * \param spi Pointer to an Spi instance.
\r
273 * \return Returns 1 if there is no pending write operation on the SPI; otherwise
\r
276 extern uint32_t SPI_IsFinished( Spi* spi )
\r
278 return ((spi->SPI_SR & SPI_SR_TXEMPTY) != 0) ;
\r