SAMV71 Xplained Ultra Software Package 1.3

twi.c

Go to the documentation of this file.
00001 /* ----------------------------------------------------------------------------
00002  *         SAM Software Package License
00003  * ----------------------------------------------------------------------------
00004  * Copyright (c) 2011, Atmel Corporation
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *
00011  * - Redistributions of source code must retain the above copyright notice,
00012  * this list of conditions and the disclaimer below.
00013  *
00014  * Atmel's name may not be used to endorse or promote products derived from
00015  * this software without specific prior written permission.
00016  *
00017  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
00020  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00022  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
00023  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00026  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  * ----------------------------------------------------------------------------
00028  */
00029 
00030 /** \addtogroup twi_module Working with TWI
00031  *  \ingroup peripherals_module
00032  * The TWI driver provides the interface to configure and use the TWI
00033  * peripheral.
00034  *
00035  * \section Usage
00036  * <ul>
00037  * <li> Configures a TWI peripheral to operate in master mode, at the given
00038  * frequency (in Hz) using TWI_Configure(). </li>
00039  * <li> Sends a STOP condition on the TWI using TWI_Stop().</li>
00040  * <li> Starts a read operation on the TWI bus with the specified slave using
00041  * TWI_StartRead(). Data must then be read using TWI_ReadByte() whenever
00042  * a byte is available (poll using TWI_ByteReceived()).</li>
00043  * <li> Starts a write operation on the TWI to access the selected slave using
00044  * TWI_StartWrite(). A byte of data must be provided to start the write;
00045  * other bytes are written next.</li>
00046  * <li> Sends a byte of data to one of the TWI slaves on the bus using 
00047  * TWI_WriteByte().
00048  * This function must be called once before TWI_StartWrite() with the first 
00049  * byte of data
00050  * to send, then it shall be called repeatedly after that to send the 
00051  * remaining bytes.</li>
00052  * <li> Check if a byte has been received and can be read on the given TWI
00053  * peripheral using TWI_ByteReceived().<
00054  * Check if a byte has been sent using TWI_ByteSent().</li>
00055  * <li> Check if the current transmission is complete (the STOP has been sent)
00056  * using TWI_TransferComplete().</li>
00057  * <li> Enables & disable the selected interrupts sources on a TWI peripheral
00058  * using TWI_EnableIt() and TWI_DisableIt().</li>
00059  * <li> Get current status register of the given TWI peripheral using
00060  * TWI_GetStatus(). Get current status register of the given TWI peripheral, but
00061  * masking interrupt sources which are not currently enabled using
00062  * TWI_GetMaskedStatus().</li>
00063  * </ul>
00064  * For more accurate information, please look at the TWI section of the
00065  * Datasheet.
00066  *
00067  * Related files :\n
00068  * \ref twi.c\n
00069  * \ref twi.h.\n
00070  */
00071 /*@{*/
00072 /*@}*/
00073 
00074 /**
00075  * \file
00076  *
00077  * Implementation of Two Wire Interface (TWI).
00078  *
00079  */
00080 
00081 /*----------------------------------------------------------------------------
00082  *        Headers
00083  *----------------------------------------------------------------------------*/
00084 
00085 #include "chip.h"
00086 
00087 #include <assert.h>
00088 
00089 #define TWIHS_IT    ( TWIHS_IER_TXCOMP | TWIHS_IER_TXCOMP | TWIHS_IER_RXRDY \
00090                     | TWIHS_IER_TXRDY | TWIHS_IER_SVACC | TWIHS_IER_GACC | \
00091                       TWIHS_IER_OVRE | TWIHS_IER_UNRE | TWIHS_IER_NACK | \
00092                       TWIHS_IER_ARBLST | TWIHS_IER_SCL_WS | TWIHS_IER_EOSACC | \
00093                       TWIHS_IER_MCACK | TWIHS_IER_TOUT | TWIHS_IER_PECERR |\
00094                       TWIHS_IER_SMBDAM | TWIHS_IER_SMBHHM)
00095                       
00096 /*----------------------------------------------------------------------------
00097  *        Exported functions
00098  *----------------------------------------------------------------------------*/
00099 
00100 /**
00101  * \brief Configures a TWI peripheral to operate in master mode, at the given
00102  * frequency (in Hz). The duty cycle of the TWI clock is set to 50%.
00103  * \param pTwi  Pointer to an Twihs instance.
00104  * \param twck  Desired TWI clock frequency.
00105  * \param mck  Master clock frequency.
00106  */
00107 void TWI_ConfigureMaster( Twihs *pTwi, uint32_t dwTwCk, uint32_t dwMCk )
00108 {
00109     uint32_t dwCkDiv = 0 ;
00110     uint32_t dwClDiv ;
00111     uint32_t dwOk = 0 ;
00112 
00113     TRACE_DEBUG( "TWI_ConfigureMaster()\n\r" ) ;
00114     assert( pTwi ) ;
00115 
00116     /* SVEN: TWI Slave Mode Enabled */
00117     pTwi->TWIHS_CR = TWIHS_CR_SVEN ;
00118     /* Reset the TWI */
00119     pTwi->TWIHS_CR = TWIHS_CR_SWRST ;
00120     pTwi->TWIHS_RHR ;
00121 
00122     /* TWI Slave Mode Disabled, TWI Master Mode Disabled. */
00123     pTwi->TWIHS_CR = TWIHS_CR_SVDIS ;
00124     pTwi->TWIHS_CR = TWIHS_CR_MSDIS ;
00125 
00126     /* Set master mode */
00127     pTwi->TWIHS_CR = TWIHS_CR_MSEN ;
00128 
00129     /* Configure clock */
00130     while ( !dwOk ) {
00131         dwClDiv = ((dwMCk / (2 * dwTwCk)) - 4) / (1<<dwCkDiv) ;
00132 
00133         if ( dwClDiv <= 255 ) {
00134             dwOk = 1 ;
00135         } else {
00136             dwCkDiv++ ;
00137         }
00138     }
00139     assert( dwCkDiv < 8 ) ;
00140     TRACE_DEBUG( "Using CKDIV = %u and CLDIV/CHDIV = %u\n\r", dwCkDiv, dwClDiv ) ;
00141 
00142     pTwi->TWIHS_CWGR = 0 ;
00143     pTwi->TWIHS_CWGR = (dwCkDiv << 16) | (dwClDiv << 8) | dwClDiv ;
00144 }
00145 
00146 /**
00147  * \brief Configures a TWI peripheral to operate in slave mode.
00148  * \param pTwi  Pointer to an Twihs instance.
00149  * \param slaveAddress Slave address.
00150  */
00151 void TWI_ConfigureSlave(Twihs *pTwi, uint8_t slaveAddress)
00152 {
00153     uint32_t i;
00154 
00155     /* TWI software reset */
00156     pTwi->TWIHS_CR = TWIHS_CR_SWRST;
00157     pTwi->TWIHS_RHR;
00158 
00159     /* Wait at least 10 ms */
00160     for (i=0; i < 1000000; i++);
00161 
00162     /* TWI Slave Mode Disabled, TWI Master Mode Disabled*/
00163     pTwi->TWIHS_CR = TWIHS_CR_SVDIS | TWIHS_CR_MSDIS;
00164 
00165     /* Configure slave address. */
00166     pTwi->TWIHS_SMR = 0;
00167     pTwi->TWIHS_SMR = TWIHS_SMR_SADR(slaveAddress);
00168 
00169     /* SVEN: TWI Slave Mode Enabled */
00170     pTwi->TWIHS_CR = TWIHS_CR_SVEN;
00171 
00172     /* Wait at least 10 ms */
00173     for (i=0; i < 1000000; i++);
00174     assert( (pTwi->TWIHS_CR & TWIHS_CR_SVDIS)!= TWIHS_CR_SVDIS ) ;
00175 }
00176 
00177 /**
00178  * \brief Sends a STOP condition on the TWI.
00179  * \param pTwi  Pointer to an Twihs instance.
00180  */
00181 void TWI_Stop( Twihs *pTwi )
00182 {
00183     assert( pTwi != NULL ) ;
00184 
00185     pTwi->TWIHS_CR = TWIHS_CR_STOP;
00186 }
00187 
00188 /**
00189  * \brief Starts a read operation on the TWI bus with the specified slave, it 
00190  * returns immediately. Data must then be read using TWI_ReadByte() whenever a
00191  * byte is available (poll using TWI_ByteReceived()).
00192  * \param pTwi  Pointer to an Twihs instance.
00193  * \param address  Slave address on the bus.
00194  * \param iaddress  Optional internal address bytes.
00195  * \param isize  Number of internal address bytes.
00196  */
00197 void TWI_StartRead(
00198         Twihs *pTwi,
00199         uint8_t address,
00200         uint32_t iaddress,
00201         uint8_t isize)
00202 {
00203     assert( pTwi != NULL ) ;
00204     assert( (address & 0x80) == 0 ) ;
00205     assert( (iaddress & 0xFF000000) == 0 ) ;
00206     assert( isize < 4 ) ;
00207 
00208     /* Set slave address and number of internal address bytes. */
00209     pTwi->TWIHS_MMR = 0;
00210     pTwi->TWIHS_MMR = (isize << 8) | TWIHS_MMR_MREAD | (address << 16);
00211 
00212     /* Set internal address bytes */
00213     pTwi->TWIHS_IADR = 0;
00214     pTwi->TWIHS_IADR = iaddress;
00215 
00216     /* Send START condition */
00217     pTwi->TWIHS_CR = TWIHS_CR_START;
00218 }
00219 
00220 /**
00221  * \brief Reads a byte from the TWI bus. The read operation must have been started
00222  * using TWI_StartRead() and a byte must be available (check with TWI_ByteReceived()).
00223  * \param pTwi  Pointer to an Twihs instance.
00224  * \return byte read.
00225  */
00226 uint8_t TWI_ReadByte(Twihs *pTwi)
00227 {
00228     assert( pTwi != NULL ) ;
00229 
00230     return pTwi->TWIHS_RHR;
00231 }
00232 
00233 /**
00234  * \brief Sends a byte of data to one of the TWI slaves on the bus.
00235  * \note This function must be called once before TWI_StartWrite() with
00236  * the first byte of data  to send, then it shall be called repeatedly
00237  * after that to send the remaining bytes.
00238  * \param pTwi  Pointer to an Twihs instance.
00239  * \param byte  Byte to send.
00240  */
00241 void TWI_WriteByte(Twihs *pTwi, uint8_t byte)
00242 {
00243     assert( pTwi != NULL ) ;
00244 
00245     pTwi->TWIHS_THR = byte;
00246 }
00247 
00248 /**
00249  * \brief Starts a write operation on the TWI to access the selected slave, then
00250  *  returns immediately. A byte of data must be provided to start the write;
00251  * other bytes are written next.
00252  * after that to send the remaining bytes.
00253  * \param pTwi  Pointer to an Twihs instance.
00254  * \param address  Address of slave to acccess on the bus.
00255  * \param iaddress  Optional slave internal address.
00256  * \param isize  Number of internal address bytes.
00257  * \param byte  First byte to send.
00258  */
00259 void TWI_StartWrite(
00260         Twihs *pTwi,
00261         uint8_t address,
00262         uint32_t iaddress,
00263         uint8_t isize,
00264         uint8_t byte)
00265 {
00266     assert( pTwi != NULL ) ;
00267     assert( (address & 0x80) == 0 ) ;
00268     assert( (iaddress & 0xFF000000) == 0 ) ;
00269     assert( isize < 4 ) ;
00270 
00271     /* Set slave address and number of internal address bytes. */
00272     pTwi->TWIHS_MMR = 0;
00273     pTwi->TWIHS_MMR = (isize << 8) | (address << 16);
00274 
00275     /* Set internal address bytes. */
00276     pTwi->TWIHS_IADR = 0;
00277     pTwi->TWIHS_IADR = iaddress;
00278 
00279     /* Write first byte to send.*/
00280     TWI_WriteByte(pTwi, byte);
00281 }
00282 
00283 /**
00284  * \brief Check if a byte have been received from TWI.
00285  * \param pTwi  Pointer to an Twihs instance.
00286  * \return 1 if a byte has been received and can be read on the given TWI
00287  * peripheral; otherwise, returns 0. This function resets the status register.
00288  */
00289 uint8_t TWI_ByteReceived(Twihs *pTwi)
00290 {
00291     return ((pTwi->TWIHS_SR & TWIHS_SR_RXRDY) == TWIHS_SR_RXRDY);
00292 }
00293 
00294 /**
00295  * \brief Check if a byte have been sent to TWI.
00296  * \param pTwi  Pointer to an Twihs instance.
00297  * \return 1 if a byte has been sent  so another one can be stored for
00298  * transmission; otherwise returns 0. This function clears the status register.
00299  */
00300 uint8_t TWI_ByteSent(Twihs *pTwi)
00301 {
00302     return ((pTwi->TWIHS_SR & TWIHS_SR_TXRDY) == TWIHS_SR_TXRDY);
00303 }
00304 
00305 /**
00306  * \brief Check if current transmission is completed.
00307  * \param pTwi  Pointer to an Twihs instance.
00308  * \return  1 if the current transmission is complete (the STOP has been sent);
00309  * otherwise returns 0.
00310  */
00311 uint8_t TWI_TransferComplete(Twihs *pTwi)
00312 {
00313     return ((pTwi->TWIHS_SR & TWIHS_SR_TXCOMP) == TWIHS_SR_TXCOMP);
00314 }
00315 
00316 /**
00317  * \brief Enables the selected interrupts sources on a TWI peripheral.
00318  * \param pTwi  Pointer to an Twihs instance.
00319  * \param sources  Bitwise OR of selected interrupt sources.
00320  */
00321 void TWI_EnableIt(Twihs *pTwi, uint32_t sources)
00322 {
00323     assert( pTwi != NULL ) ;
00324     assert( (sources & TWIHS_IT) ) ;
00325 
00326     pTwi->TWIHS_IER = sources;
00327 }
00328 
00329 /**
00330  * \brief Disables the selected interrupts sources on a TWI peripheral.
00331  * \param pTwi  Pointer to an Twihs instance.
00332  * \param sources  Bitwise OR of selected interrupt sources.
00333  */
00334 void TWI_DisableIt(Twihs *pTwi, uint32_t sources)
00335 {
00336     assert( pTwi != NULL ) ;
00337     assert(sources & TWIHS_IT ) ;
00338 
00339     pTwi->TWIHS_IDR = sources;
00340 }
00341 
00342 /**
00343  * \brief Get the current status register of the given TWI peripheral.
00344  * \note This resets the internal value of the status register, so further
00345  * read may yield different values.
00346  * \param pTwi  Pointer to an Twihs instance.
00347  * \return  TWI status register.
00348  */
00349 uint32_t TWI_GetStatus(Twihs *pTwi)
00350 {
00351     assert( pTwi != NULL ) ;
00352 
00353     return pTwi->TWIHS_SR;
00354 }
00355 
00356 /**
00357  * \brief Returns the current status register of the given TWI peripheral, but
00358  * masking interrupt sources which are not currently enabled.
00359  * \note This resets the internal value of the status register, so further
00360  * read may yield different values.
00361  * \param pTwi  Pointer to an Twihs instance.
00362  */
00363 uint32_t TWI_GetMaskedStatus(Twihs *pTwi)
00364 {
00365     uint32_t status;
00366 
00367     assert( pTwi != NULL ) ;
00368 
00369     status = pTwi->TWIHS_SR;
00370     status &= pTwi->TWIHS_IMR;
00371 
00372     return status;
00373 }
00374 
00375 /**
00376  * \brief  Sends a STOP condition. STOP Condition is sent just after completing
00377  *  the current byte transmission in master read mode.
00378  * \param pTwi  Pointer to an Twihs instance.
00379  */
00380 void TWI_SendSTOPCondition(Twihs *pTwi)
00381 {
00382     assert( pTwi != NULL ) ;
00383 
00384     pTwi->TWIHS_CR |= TWIHS_CR_STOP;
00385 }
00386 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines