SAMV71 Xplained Ultra Software Package 1.5

spid.c

00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
00028 /* ---------------------------------------------------------------------------- */
00029 
00030 //------------------------------------------------------------------------------
00031 //         Headers
00032 //------------------------------------------------------------------------------
00033 
00034 #include "spid.h"
00035 #include "board.h"
00036 
00037 //------------------------------------------------------------------------------
00038 //         Macros
00039 //------------------------------------------------------------------------------
00040 
00041 /// Write PMC register
00042 #define WRITE_PMC(pPmc, regName, value) pPmc->regName = (value)
00043 
00044 /// Write SPI register
00045 #define WRITE_SPI(pSpi, regName, value) pSpi->regName = (value)
00046 
00047 /// Read SPI registers
00048 #define READ_SPI(pSpi, regName) (pSpi->regName)
00049 
00050 //------------------------------------------------------------------------------
00051 //         Exported functions
00052 //------------------------------------------------------------------------------
00053 
00054 //------------------------------------------------------------------------------
00055 /// Initializes the Spid structure and the corresponding SPI hardware.
00056 /// Always returns 0.
00057 /// \param pSpid  Pointer to a Spid instance.
00058 /// \param pSpiHw  Associated SPI peripheral.
00059 /// \param spiId  SPI peripheral identifier.
00060 //------------------------------------------------------------------------------
00061 unsigned char SPID_Configure(Spid *pSpid, AT91S_SPI *pSpiHw,
00062                              unsigned char spiId)
00063 {
00064     // Initialize the SPI structure
00065     pSpid->pSpiHw = pSpiHw;
00066     pSpid->spiId  = spiId;
00067     pSpid->semaphore = 1;
00068     pSpid->pCurrentCommand = 0;
00069 
00070     // Enable the SPI clock
00071     WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << pSpid->spiId));
00072 
00073     // Execute a software reset of the SPI twice
00074     WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SWRST);
00075     WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SWRST);
00076 
00077     // Configure SPI in Master Mode with No CS selected !!!
00078     WRITE_SPI(pSpiHw, SPI_MR, AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | AT91C_SPI_PCS);
00079 
00080     // Disable the PDC transfer
00081     WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);
00082 
00083     // Enable the SPI
00084     WRITE_SPI(pSpiHw, SPI_CR, AT91C_SPI_SPIEN);
00085 
00086     // Enable the SPI clock
00087     WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << pSpid->spiId));
00088 
00089     return 0;
00090 }
00091 
00092 //------------------------------------------------------------------------------
00093 /// Configures the parameters for the device corresponding to the cs.
00094 /// \param pSpid  Pointer to a Spid instance.
00095 /// \param cs  number corresponding to the SPI chip select.
00096 /// \param csr  SPI_CSR value to setup.
00097 //------------------------------------------------------------------------------
00098 void SPID_ConfigureCS(Spid *pSpid, unsigned char cs, unsigned int csr)
00099 {
00100     AT91S_SPI *pSpiHw = pSpid->pSpiHw;
00101     WRITE_SPI(pSpiHw, SPI_CSR[cs], csr);
00102 }
00103 
00104 //------------------------------------------------------------------------------
00105 /// Starts a SPI master transfer. This is a non blocking function. It will
00106 /// return as soon as the transfer is started.
00107 /// Returns 0 if the transfer has been started successfully; otherwise returns
00108 /// SPID_ERROR_LOCK is the driver is in use, or SPID_ERROR if the command is not
00109 /// valid.
00110 /// \param pSpid  Pointer to a Spid instance.
00111 /// \param pCommand Pointer to the SPI command to execute.
00112 //------------------------------------------------------------------------------
00113 unsigned char SPID_SendCommand(Spid *pSpid, SpidCmd *pCommand)
00114 {
00115     AT91S_SPI *pSpiHw = pSpid->pSpiHw;
00116     unsigned int spiMr;
00117 
00118     // Try to get the dataflash semaphore
00119     if (pSpid->semaphore == 0)
00120 
00121         return SPID_ERROR_LOCK;
00122 
00123     pSpid->semaphore--;
00124 
00125     // Enable the SPI clock
00126     WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << pSpid->spiId));
00127 
00128     // Disable transmitter and receiver
00129     WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);
00130 
00131     // Write to the MR register
00132     spiMr = READ_SPI(pSpiHw, SPI_MR);
00133     spiMr |= AT91C_SPI_PCS;
00134     spiMr &= ~((1 << pCommand->spiCs) << 16);
00135     WRITE_SPI(pSpiHw, SPI_MR, spiMr);
00136 
00137     // Initialize the two SPI PDC buffer
00138     WRITE_SPI(pSpiHw, SPI_RPR, (int) pCommand->pCmd);
00139     WRITE_SPI(pSpiHw, SPI_RCR, pCommand->cmdSize);
00140     WRITE_SPI(pSpiHw, SPI_TPR, (int) pCommand->pCmd);
00141     WRITE_SPI(pSpiHw, SPI_TCR, pCommand->cmdSize);
00142 
00143     WRITE_SPI(pSpiHw, SPI_RNPR, (int) pCommand->pData);
00144     WRITE_SPI(pSpiHw, SPI_RNCR, pCommand->dataSize);
00145     WRITE_SPI(pSpiHw, SPI_TNPR, (int) pCommand->pData);
00146     WRITE_SPI(pSpiHw, SPI_TNCR, pCommand->dataSize);
00147 
00148     // Initialize the callback
00149     pSpid->pCurrentCommand = pCommand;
00150 
00151     // Enable transmitter and receiver
00152     WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTEN | AT91C_PDC_TXTEN);
00153 
00154     // Enable buffer complete interrupt
00155     WRITE_SPI(pSpiHw, SPI_IER, AT91C_SPI_RXBUFF);
00156 
00157     return 0;
00158 }
00159 
00160 //------------------------------------------------------------------------------
00161 /// The SPI_Handler must be called by the SPI Interrupt Service Routine with the
00162 /// corresponding Spi instance.
00163 /// The SPI_Handler will unlock the Spi semaphore and invoke the upper application
00164 /// callback.
00165 /// \param pSpid  Pointer to a Spid instance.
00166 //------------------------------------------------------------------------------
00167 void SPID_Handler(Spid *pSpid)
00168 {
00169     SpidCmd *pSpidCmd = pSpid->pCurrentCommand;
00170     AT91S_SPI *pSpiHw = pSpid->pSpiHw;
00171     volatile unsigned int spiSr;
00172 
00173     // Read the status register
00174     spiSr = READ_SPI(pSpiHw, SPI_SR);
00175 
00176     if (spiSr & AT91C_SPI_RXBUFF) {
00177         // Disable transmitter and receiver
00178         WRITE_SPI(pSpiHw, SPI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);
00179 
00180         // Disable the SPI clock
00181         WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << pSpid->spiId));
00182 
00183         // Disable buffer complete interrupt
00184         WRITE_SPI(pSpiHw, SPI_IDR, AT91C_SPI_RXBUFF);
00185 
00186         // Release the dataflash semaphore
00187         pSpid->semaphore++;
00188 
00189         // Invoke the callback associated with the current command
00190         if (pSpidCmd && pSpidCmd->callback)
00191 
00192             pSpidCmd->callback(0, pSpidCmd->pArgument);
00193 
00194         // Nothing must be done after. A new DF operation may have been started
00195         // in the callback function.
00196     }
00197 }
00198 
00199 //------------------------------------------------------------------------------
00200 /// Returns 1 if the SPI driver is currently busy executing a command; otherwise
00201 /// returns 0.
00202 /// \param pSpid  Pointer to a SPI driver instance.
00203 //------------------------------------------------------------------------------
00204 unsigned char SPID_IsBusy(const Spid *pSpid)
00205 {
00206     if (pSpid->semaphore == 0)
00207         return 1;
00208     else
00209         return 0;
00210 }
00211 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines