SAMV71 Xplained Ultra Software Package 1.4

twid.c

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 
00031 /*----------------------------------------------------------------------------
00032  *        Headers
00033  *----------------------------------------------------------------------------*/
00034 #include "chip.h"
00035 
00036 #include <assert.h>
00037 
00038 /*----------------------------------------------------------------------------
00039  *        Definition
00040  *----------------------------------------------------------------------------*/
00041 #define TWITIMEOUTMAX 400
00042 static uint32_t dmaWriteChannel,dmaReadChannel;
00043 
00044 extern uint32_t twi_send_stop;
00045 
00046 /*----------------------------------------------------------------------------
00047  *        Types
00048  *----------------------------------------------------------------------------*/
00049 
00050 /** TWI driver callback function.*/
00051 typedef void (*TwiCallback)(Async *);
00052 
00053 /** \brief TWI asynchronous transfer descriptor.*/
00054 typedef struct _AsyncTwi {
00055 
00056     /** Asynchronous transfer status. */
00057     volatile uint8_t status;
00058     /** Callback function to invoke when transfer completes or fails.*/
00059     TwiCallback callback;
00060     /** Pointer to the data buffer.*/
00061     uint8_t *pData;
00062     /** Total number of bytes to transfer.*/
00063     uint32_t num;
00064     /** Number of already transferred bytes.*/
00065     uint32_t transferred;
00066 
00067 } AsyncTwi;
00068 
00069 /**
00070  * \brief Initializes a TWI DMA Read channel.
00071  */
00072 static void TWID_DmaInitializeRead(TwihsDma *pTwiXdma)
00073 {
00074     /* Allocate a XDMA channel, Read accesses into TWI_THR */
00075     dmaReadChannel = XDMAD_AllocateChannel( pTwiXdma->pTwiDma, pTwiXdma->Twi_id, 
00076             XDMAD_TRANSFER_MEMORY);
00077     if ( dmaReadChannel == XDMAD_ALLOC_FAILED ) {
00078         printf("-E- Can't allocate XDMA channel\n\r");
00079     }
00080     XDMAD_PrepareChannel(pTwiXdma->pTwiDma, dmaReadChannel );
00081 }
00082 
00083 /**
00084  * \brief Initializes a TWI DMA write channel.
00085  */
00086 static void TWID_DmaInitializeWrite(TwihsDma *pTwiXdma)
00087 {
00088     /* Allocate a XDMA channel, Write accesses into TWI_THR */
00089     dmaWriteChannel = XDMAD_AllocateChannel( pTwiXdma->pTwiDma, XDMAD_TRANSFER_MEMORY,
00090             pTwiXdma->Twi_id);
00091     if ( dmaWriteChannel == XDMAD_ALLOC_FAILED ) {
00092         printf("-E- Can't allocate XDMA channel\n\r");
00093     }
00094     XDMAD_PrepareChannel(pTwiXdma->pTwiDma, dmaWriteChannel );
00095 }
00096 
00097 /**
00098  * \brief Configure xDMA write linker list for TWI transfer.
00099  */
00100 static uint8_t TWID_XdmaConfigureWrite(TwihsDma *pTwiXdma, uint8_t *buf, uint32_t len)
00101 {
00102     uint32_t xdmaCndc, Thr, xdmaInt;
00103     sXdmadCfg xdmadTxCfg;
00104 
00105     Thr = (uint32_t)&(TWIHS0->TWIHS_THR);
00106     if(pTwiXdma->Twi_id==ID_TWIHS1) {
00107         Thr = (uint32_t)&(TWIHS1->TWIHS_THR);
00108     }
00109     if(pTwiXdma->Twi_id==ID_TWIHS2) {
00110         Thr = (uint32_t)&(TWIHS2->TWIHS_THR);
00111     }
00112     xdmadTxCfg.mbr_ubc =      XDMA_UBC_NVIEW_NDV0 |
00113                              XDMA_UBC_NDE_FETCH_DIS|
00114                              XDMA_UBC_NSEN_UPDATED |  len;
00115       
00116     xdmadTxCfg.mbr_sa = (uint32_t)buf;
00117     xdmadTxCfg.mbr_da = Thr;
00118     xdmadTxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
00119                          XDMAC_CC_MBSIZE_SINGLE |
00120                          XDMAC_CC_DSYNC_MEM2PER |
00121                          XDMAC_CC_CSIZE_CHK_1 |
00122                          XDMAC_CC_DWIDTH_BYTE|
00123                          XDMAC_CC_SIF_AHB_IF0 |
00124                          XDMAC_CC_DIF_AHB_IF1 |
00125                          XDMAC_CC_SAM_INCREMENTED_AM |
00126                          XDMAC_CC_DAM_FIXED_AM |
00127                          XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber( 
00128                             pTwiXdma->Twi_id, XDMAD_TRANSFER_TX ));
00129     
00130     xdmadTxCfg.mbr_bc = 0;
00131     xdmadTxCfg.mbr_sus = 0;
00132     xdmadTxCfg.mbr_dus =0;
00133     xdmaCndc = 0;
00134     
00135     xdmaInt =  (XDMAC_CIE_BIE |
00136                XDMAC_CIE_RBIE  |
00137                XDMAC_CIE_WBIE );
00138     if (XDMAD_ConfigureTransfer( pTwiXdma->pTwiDma, dmaWriteChannel, 
00139             &xdmadTxCfg, xdmaCndc, 0, xdmaInt) )
00140       return USARTD_ERROR;
00141 
00142     return 0;
00143 }
00144 
00145 
00146 /**
00147  * \brief Configure xDMA read linker list for TWI transfer.
00148  */
00149 static uint8_t TWID_XdmaConfigureRead(TwihsDma *pTwiXdma, uint8_t *buf, uint32_t len)
00150 {
00151     uint32_t xdmaCndc, Rhr, xdmaInt;
00152     sXdmadCfg xdmadRxCfg;
00153 
00154     Rhr = (uint32_t)&(TWIHS0->TWIHS_RHR);
00155     if(pTwiXdma->Twi_id==ID_TWIHS1) {
00156         Rhr = (uint32_t)&(TWIHS1->TWIHS_RHR);
00157     }
00158     if(pTwiXdma->Twi_id==ID_TWIHS2) {
00159         Rhr = (uint32_t)&(TWIHS2->TWIHS_RHR);
00160     }
00161     xdmadRxCfg.mbr_ubc = XDMA_UBC_NVIEW_NDV0 |
00162                           XDMA_UBC_NDE_FETCH_DIS|
00163                           XDMA_UBC_NDEN_UPDATED |
00164                           len;
00165     
00166     xdmadRxCfg.mbr_da = (uint32_t)buf;
00167     xdmadRxCfg.mbr_sa = Rhr;
00168     
00169     xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
00170                            XDMAC_CC_MBSIZE_SINGLE |
00171                            XDMAC_CC_DSYNC_PER2MEM |
00172                            XDMAC_CC_CSIZE_CHK_1 |
00173                            XDMAC_CC_DWIDTH_BYTE |
00174                            XDMAC_CC_SIF_AHB_IF1 |
00175                            XDMAC_CC_DIF_AHB_IF0 |
00176                            XDMAC_CC_SAM_FIXED_AM |
00177                            XDMAC_CC_DAM_INCREMENTED_AM |
00178                            XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber( 
00179                                 pTwiXdma->Twi_id , XDMAD_TRANSFER_RX ));
00180       
00181     xdmadRxCfg.mbr_bc = 0;
00182     xdmadRxCfg.mbr_sus = 0;
00183     xdmadRxCfg.mbr_dus =0;
00184     xdmaCndc = 0;
00185     xdmaInt =  (XDMAC_CIE_BIE |
00186                XDMAC_CIE_RBIE  |
00187                XDMAC_CIE_WBIE );
00188         
00189     if (XDMAD_ConfigureTransfer( pTwiXdma->pTwiDma, dmaReadChannel, 
00190             &xdmadRxCfg, xdmaCndc, 0, xdmaInt))
00191       return 1;
00192     return 0;
00193 }
00194 
00195 /*----------------------------------------------------------------------------
00196  *        Global functions
00197  *----------------------------------------------------------------------------*/
00198 
00199 /**
00200  * \brief Returns 1 if the given transfer has ended; otherwise returns 0.
00201  * \param pAsync  Pointer to an Async instance.
00202  */
00203 uint32_t ASYNC_IsFinished( Async* pAsync )
00204 {
00205     return (pAsync->status != ASYNC_STATUS_PENDING) ;
00206 }
00207 
00208 /**
00209  * \brief Initializes a TWI driver instance, using the given TWI peripheral.
00210  * \note The peripheral must have been initialized properly before calling this
00211  * function.
00212  * \param pTwid  Pointer to the Twid instance to initialize.
00213  * \param pTwi  Pointer to the TWI peripheral to use.
00214  */
00215 void TWID_Initialize(Twid *pTwid, Twihs *pTwi)
00216 {
00217     TRACE_DEBUG( "TWID_Initialize()\n\r" ) ;
00218     assert( pTwid != NULL ) ;
00219     assert( pTwi != NULL ) ;
00220 
00221     /* Initialize driver. */
00222     pTwid->pTwi = pTwi;
00223     pTwid->pTransfer = 0;
00224 }
00225 
00226 /**
00227  * \brief Interrupt handler for a TWI peripheral. Manages asynchronous transfer
00228  * occurring on the bus. This function MUST be called by the interrupt service
00229  * routine of the TWI peripheral if asynchronous read/write are needed.
00230  * \param pTwid  Pointer to a Twid instance.
00231  */
00232 void TWID_Handler( Twid *pTwid )
00233 {
00234     uint8_t status;
00235     AsyncTwi *pTransfer ;
00236     Twihs *pTwi ;
00237 
00238     assert( pTwid != NULL ) ;
00239 
00240     pTransfer = (AsyncTwi*)pTwid->pTransfer ;
00241     assert( pTransfer != NULL ) ;
00242     pTwi = pTwid->pTwi ;
00243     assert( pTwi != NULL ) ;
00244 
00245     /* Retrieve interrupt status */
00246     status = TWI_GetMaskedStatus(pTwi);
00247 
00248     /* Byte received */
00249     if (TWI_STATUS_RXRDY(status)) {
00250 
00251         pTransfer->pData[pTransfer->transferred] = TWI_ReadByte(pTwi);
00252         pTransfer->transferred++;
00253 
00254         /* check for transfer finish */
00255         if (pTransfer->transferred == pTransfer->num) {
00256 
00257             TWI_DisableIt(pTwi, TWIHS_IDR_RXRDY);
00258             TWI_EnableIt(pTwi, TWIHS_IER_TXCOMP);
00259         }
00260         /* Last byte? */
00261         else if (pTransfer->transferred == (pTransfer->num - 1)) {
00262 
00263             TWI_Stop(pTwi);
00264         }
00265     }
00266     /* Byte sent*/
00267     else if (TWI_STATUS_TXRDY(status)) {
00268 
00269         /* Transfer finished ? */
00270         if (pTransfer->transferred == pTransfer->num) {
00271 
00272             TWI_DisableIt(pTwi, TWIHS_IDR_TXRDY);
00273             TWI_EnableIt(pTwi, TWIHS_IER_TXCOMP);
00274             TWI_SendSTOPCondition(pTwi);
00275         }
00276         /* Bytes remaining */
00277         else {
00278 
00279             TWI_WriteByte(pTwi, pTransfer->pData[pTransfer->transferred]);
00280             pTransfer->transferred++;
00281         }
00282     }
00283     /* Transfer complete*/
00284     else if (TWI_STATUS_TXCOMP(status)) {
00285 
00286         TWI_DisableIt(pTwi, TWIHS_IDR_TXCOMP);
00287         pTransfer->status = 0;
00288         if (pTransfer->callback) {
00289             pTransfer->callback((Async *) pTransfer);
00290         }
00291         pTwid->pTransfer = 0;
00292     }
00293 }
00294 
00295 /**
00296  * \brief Asynchronously reads data from a slave on the TWI bus. An optional
00297  * callback function is triggered when the transfer is complete.
00298  * \param pTwid  Pointer to a Twid instance.
00299  * \param address  TWI slave address.
00300  * \param iaddress  Optional slave internal address.
00301  * \param isize  Internal address size in bytes.
00302  * \param pData  Data buffer for storing received bytes.
00303  * \param num  Number of bytes to read.
00304  * \param pAsync  Asynchronous transfer descriptor.
00305  * \return 0 if the transfer has been started; otherwise returns a TWI error code.
00306  */
00307 uint8_t TWID_Read(
00308         Twid *pTwid,
00309         uint8_t address,
00310         uint32_t iaddress,
00311         uint8_t isize,
00312         uint8_t *pData,
00313         uint32_t num,
00314         Async *pAsync)
00315 {
00316     Twihs *pTwi;
00317     AsyncTwi *pTransfer;
00318     uint32_t startTime;
00319     assert( pTwid != NULL ) ;
00320     pTwi = pTwid->pTwi;
00321     pTransfer = (AsyncTwi *) pTwid->pTransfer;
00322 
00323     assert( (address & 0x80) == 0 ) ;
00324     assert( (iaddress & 0xFF000000) == 0 ) ;
00325     assert( isize < 4 ) ;
00326 
00327     /* Check that no transfer is already pending*/
00328     if (pTransfer) {
00329 
00330         TRACE_ERROR("TWID_Read: A transfer is already pending\n\r");
00331         return TWID_ERROR_BUSY;
00332     }
00333 
00334     /* In single data byte master read, the START and STOP must both be set */
00335     twi_send_stop = (num == 1) ? 1 : 0;
00336 
00337     /* Asynchronous transfer*/
00338     if (pAsync) {
00339 
00340         /* Update the transfer descriptor */
00341         pTwid->pTransfer = pAsync;
00342         pTransfer = (AsyncTwi *) pAsync;
00343         pTransfer->status = ASYNC_STATUS_PENDING;
00344         pTransfer->pData = pData;
00345         pTransfer->num = num;
00346         pTransfer->transferred = 0;
00347 
00348         /* Enable read interrupt and start the transfer */
00349         TWI_EnableIt(pTwi, TWIHS_IER_RXRDY);
00350         TWI_StartRead(pTwi, address, iaddress, isize);
00351     }
00352     /* Synchronous transfer*/
00353     else {
00354 
00355         /* Start read*/
00356         TWI_StartRead(pTwi, address, iaddress, isize);
00357 
00358         /* Read all bytes, setting STOP before the last byte*/
00359         while (num > 0) {
00360 
00361             /* Last byte ?*/
00362             if (num == 1) {
00363                 TWI_Stop(pTwi);
00364             }
00365             /* Wait for byte then read and store it*/
00366             startTime = GetTicks();
00367             while( !TWI_ByteReceived(pTwi)) {
00368                 if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
00369                     TRACE_ERROR("TWID Timeout BR\n\r");
00370                     break;
00371                 }
00372             }
00373             
00374             *pData++ = TWI_ReadByte(pTwi);
00375             num--;
00376         }
00377 
00378         /* Wait for transfer to be complete */
00379         startTime = GetTicks();
00380         while( !TWI_TransferComplete(pTwi) ) {
00381             if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
00382                 TRACE_ERROR("TWID Timeout TC\n\r");
00383                 break;
00384             }
00385         }
00386     }
00387     return 0;
00388 }
00389 
00390 /**
00391  * \brief Asynchronously sends data to a slave on the TWI bus. An optional 
00392  * callback function is invoked whenever the transfer is complete.
00393  * \param pTwid  Pointer to a Twid instance.
00394  * \param address  TWI slave address.
00395  * \param iaddress  Optional slave internal address.
00396  * \param isize  Number of internal address bytes.
00397  * \param pData  Data buffer for storing received bytes.
00398  * \param num  Data buffer to send.
00399  * \param pAsync  Asynchronous transfer descriptor.
00400  * \return 0 if the transfer has been started; otherwise returns a TWI error code.
00401  */
00402 uint8_t TWID_Write(
00403         Twid *pTwid,
00404         uint8_t address,
00405         uint32_t iaddress,
00406         uint8_t isize,
00407         uint8_t *pData,
00408         uint32_t num,
00409         Async *pAsync)
00410 {
00411     Twihs *pTwi = pTwid->pTwi;
00412     uint32_t startTime;
00413     AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer;
00414 
00415     assert( pTwi != NULL ) ;
00416     assert( (address & 0x80) == 0 ) ;
00417     assert( (iaddress & 0xFF000000) == 0 ) ;
00418     assert( isize < 4 ) ;
00419 
00420     /* Check that no transfer is already pending */
00421     if (pTransfer) {
00422         TRACE_ERROR("TWI_Write: A transfer is already pending\n\r");
00423         return TWID_ERROR_BUSY;
00424     }
00425 
00426     /* Asynchronous transfer */
00427     if (pAsync) {
00428         /* Update the transfer descriptor */
00429         pTwid->pTransfer = pAsync;
00430         pTransfer = (AsyncTwi *) pAsync;
00431         pTransfer->status = ASYNC_STATUS_PENDING;
00432         pTransfer->pData = pData;
00433         pTransfer->num = num;
00434         pTransfer->transferred = 1;
00435 
00436         /* Enable write interrupt and start the transfer */
00437         TWI_StartWrite(pTwi, address, iaddress, isize, *pData);
00438         TWI_EnableIt(pTwi, TWIHS_IER_TXRDY);
00439         
00440     } else {
00441         /* Synchronous transfer*/
00442         // Start write
00443         TWI_StartWrite(pTwi, address, iaddress, isize, *pData++);
00444         num--;
00445         /* Send all bytes */
00446         while (num > 0) {
00447             /* Wait before sending the next byte */
00448             startTime = GetTicks();
00449             while( !TWI_ByteSent(pTwi) ) {
00450                 if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
00451                     TRACE_ERROR("TWID Timeout BS\n\r");
00452                     break;
00453                 }
00454             }
00455             TWI_WriteByte(pTwi, *pData++);
00456             num--;
00457         }
00458         /* Wait for actual end of transfer */
00459         startTime = GetTicks();
00460         /* Send a STOP condition */
00461         TWI_SendSTOPCondition(pTwi);
00462         while( !TWI_TransferComplete(pTwi) ) {
00463             if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
00464                 TRACE_ERROR("TWID Timeout TC2\n\r");
00465                 break;
00466             }
00467         }  
00468     }
00469     return 0;
00470 }
00471 
00472 /**
00473  * \brief Initializes a TWI driver instance, using the given TWI peripheral.
00474  * \note The peripheral must have been initialized properly before calling this
00475  * function.
00476  * \param pTwid  Pointer to the Twid instance to initialize.
00477  * \param pTwi  Pointer to the TWI peripheral to use.
00478  */
00479 void TWID_DmaInitialize(TwihsDma *pTwidma, Twihs *pTwi, uint8_t bPolling)
00480 {
00481     TRACE_DEBUG( "TWID_Initialize()\n\r" ) ;
00482     assert( pTwidma != NULL ) ;
00483 
00484     if ((unsigned int)pTwi == (unsigned int)TWIHS0 ) pTwidma->Twi_id = ID_TWIHS0;
00485     if ((unsigned int)pTwi == (unsigned int)TWIHS1 ) pTwidma->Twi_id = ID_TWIHS1;
00486     if ((unsigned int)pTwi == (unsigned int)TWIHS2 ) pTwidma->Twi_id = ID_TWIHS2;
00487     
00488     /* Initialize driver. */
00489     pTwidma->pTwid->pTwi = pTwi;
00490     pTwidma->pTwid->pTransfer = 0;
00491     
00492     if(!bPolling) {
00493       /* Enable XDMA interrupt and give it priority over any other peripheral 
00494         interrupt */
00495       NVIC_ClearPendingIRQ(XDMAC_IRQn);
00496       NVIC_SetPriority(XDMAC_IRQn, 1);
00497       NVIC_EnableIRQ( XDMAC_IRQn );
00498     }
00499     /* Initialize XDMA driver instance with polling mode */
00500     XDMAD_Initialize( pTwidma->pTwiDma, bPolling );
00501 }
00502 
00503 /**
00504  * \brief Asynchronously reads data from a slave on the TWI bus. An optional
00505  * callback function is triggered when the transfer is complete.
00506  * \param pTwid  Pointer to a Twid instance.
00507  * \param address  TWI slave address.
00508  * \param iaddress  Optional slave internal address.
00509  * \param isize  Internal address size in bytes.
00510  * \param pData  Data buffer for storing received bytes.
00511  * \param num  Number of bytes to read.
00512  * \param pAsync  Asynchronous transfer descriptor.
00513  * \param TWI_ID  TWI ID for TWI0, TWIHS1, TWIHS2.
00514  * \return 0 if the transfer has been started; otherwise returns a TWI error code.
00515  */
00516 uint8_t TWID_DmaRead(
00517         TwihsDma *pTwiXdma,
00518         uint8_t address,
00519         uint32_t iaddress,
00520         uint8_t isize,
00521         uint8_t *pData,
00522         uint32_t num,
00523         Async *pAsync)
00524 {
00525     Twihs *pTwi;
00526     AsyncTwi *pTransfer;
00527     uint32_t status, startTime;
00528 
00529     assert( pTwiXdma->pTwid != NULL ) ;
00530     pTwi = pTwiXdma->pTwid->pTwi;
00531     pTransfer = (AsyncTwi *) pTwiXdma->pTwid->pTransfer;
00532 
00533     assert( (address & 0x80) == 0 ) ;
00534     assert( (iaddress & 0xFF000000) == 0 ) ;
00535     assert( isize < 4 ) ;
00536 
00537     /* Check that no transfer is already pending*/
00538     if (pTransfer) {
00539 
00540         TRACE_ERROR("TWID_Read: A transfer is already pending\n\r");
00541         return TWID_ERROR_BUSY;
00542     }
00543     /* Asynchronous transfer*/
00544     if (pAsync) {
00545         /* Update the transfer descriptor */
00546         pTwiXdma->pTwid->pTransfer = pAsync;
00547         pTransfer = (AsyncTwi *) pAsync;
00548         pTransfer->status = ASYNC_STATUS_PENDING;
00549         pTransfer->pData = pData;
00550         pTransfer->num = num;
00551         pTransfer->transferred = 0;
00552 
00553         /* Enable read interrupt and start the transfer */
00554         TWI_EnableIt(pTwi, TWIHS_IER_RXRDY);
00555         TWI_StartRead(pTwi, address, iaddress, isize);
00556     } else {
00557     /* Synchronous transfer*/
00558         TWID_DmaInitializeRead(pTwiXdma);
00559         TWID_XdmaConfigureRead(pTwiXdma, pData, (num - 2));
00560         
00561         // cache maintenance before starting DMA Xfr 
00562         SCB_CleanInvalidateDCache();
00563         /* Start read*/
00564         XDMAD_StartTransfer( pTwiXdma->pTwiDma, dmaReadChannel );
00565         TWI_StartRead(pTwi, address, iaddress, isize);
00566 
00567         startTime = GetTicks();
00568         while( XDMAD_IsTransferDone(pTwiXdma->pTwiDma, dmaReadChannel) )    {
00569             if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
00570                 TRACE_ERROR("TWID DMA not done\n\r");
00571                 break;
00572             }
00573         }  
00574 
00575         status = TWI_GetStatus(pTwi);
00576         startTime = GetTicks();
00577         
00578         while( !(status & TWIHS_SR_RXRDY)) {
00579             status = TWI_GetStatus(pTwi);
00580             if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
00581                 TRACE_ERROR("TWID DMA not done\n\r");
00582                 break;
00583             }
00584         }
00585         TWI_Stop(pTwi);
00586         
00587         pData[num - 2] = TWI_ReadByte(pTwi);
00588         status = TWI_GetStatus(pTwi);
00589         startTime = GetTicks();
00590         
00591         while( !(status & TWIHS_SR_RXRDY)) {
00592             status = TWI_GetStatus(pTwi);
00593             if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
00594                 TRACE_ERROR("TWID Timeout Read\n\r");
00595                 break;
00596             }
00597         }
00598         pData[num-1] = TWI_ReadByte(pTwi);
00599         status = TWI_GetStatus(pTwi);
00600         startTime = GetTicks();
00601         while( !(status & TWIHS_SR_TXCOMP)) {
00602             status = TWI_GetStatus(pTwi);
00603             if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
00604                 TRACE_ERROR("TWID Timeout Read\n\r");
00605                 break;
00606             }
00607         }
00608         
00609         XDMAD_StopTransfer( pTwiXdma->pTwiDma, dmaReadChannel );
00610         XDMAD_FreeChannel(pTwiXdma->pTwiDma, dmaWriteChannel);
00611     }
00612     return 0;
00613 }
00614 
00615 /**
00616  * \brief Asynchronously sends data to a slave on the TWI bus. An optional 
00617  * callback function is invoked whenever the transfer is complete.
00618  * \param pTwid  Pointer to a Twid instance.
00619  * \param address  TWI slave address.
00620  * \param iaddress  Optional slave internal address.
00621  * \param isize  Number of internal address bytes.
00622  * \param pData  Data buffer for storing received bytes.
00623  * \param num  Data buffer to send.
00624  * \param pAsync  Asynchronous transfer descriptor.
00625  * \param TWI_ID  TWIHS ID for TWIHS0, TWIHS1, TWIHS2.
00626  * \return 0 if the transfer has been started; otherwise returns a TWI error code.
00627  */
00628 uint8_t TWID_DmaWrite(
00629         TwihsDma *pTwiXdma,
00630         uint8_t address,
00631         uint32_t iaddress,
00632         uint8_t isize,
00633         uint8_t *pData,
00634         uint32_t num,
00635         Async *pAsync)
00636 {
00637     Twihs *pTwi = pTwiXdma->pTwid->pTwi;
00638     AsyncTwi *pTransfer = (AsyncTwi *) pTwiXdma->pTwid->pTransfer;
00639     uint32_t status, startTime;
00640     //uint8_t singleTransfer = 0;
00641     assert( pTwi != NULL ) ;
00642     assert( (address & 0x80) == 0 ) ;
00643     assert( (iaddress & 0xFF000000) == 0 ) ;
00644     assert( isize < 4 ) ;
00645 
00646     //    if(num == 1) singleTransfer = 1;
00647     /* Check that no transfer is already pending */
00648     if (pTransfer) {
00649 
00650         TRACE_ERROR("TWI_Write: A transfer is already pending\n\r");
00651         return TWID_ERROR_BUSY;
00652     }
00653 
00654     /* Asynchronous transfer */
00655     if (pAsync) {
00656 
00657         /* Update the transfer descriptor */
00658         pTwiXdma->pTwid->pTransfer = pAsync;
00659         pTransfer = (AsyncTwi *) pAsync;
00660         pTransfer->status = ASYNC_STATUS_PENDING;
00661         pTransfer->pData = pData;
00662         pTransfer->num = num;
00663         pTransfer->transferred = 1;
00664 
00665         /* Enable write interrupt and start the transfer */
00666         TWI_StartWrite(pTwi, address, iaddress, isize, *pData);
00667         TWI_EnableIt(pTwi, TWIHS_IER_TXRDY);
00668     } else {
00669     /* Synchronous transfer*/
00670         TWID_DmaInitializeWrite(pTwiXdma);
00671         TWID_XdmaConfigureWrite(pTwiXdma, pData, (num - 1) );
00672         /* Set slave address and number of internal address bytes. */
00673         pTwi->TWIHS_MMR = 0;
00674         pTwi->TWIHS_MMR = (isize << 8) | (address << 16);
00675 
00676         /* Set internal address bytes. */
00677         pTwi->TWIHS_IADR = 0;
00678         pTwi->TWIHS_IADR = iaddress;
00679         
00680         // cache maintenance before starting DMA Xfr 
00681         SCB_CleanInvalidateDCache();
00682        
00683         startTime = GetTicks();
00684         
00685         XDMAD_StartTransfer( pTwiXdma->pTwiDma, dmaWriteChannel );
00686         
00687         while( (XDMAD_IsTransferDone(pTwiXdma->pTwiDma, dmaWriteChannel)) ) {
00688             if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
00689                 TRACE_ERROR("TWID DMA not done, Channel State is %d\n\r", 
00690                         pTwiXdma->pTwiDma->XdmaChannels[dmaWriteChannel].state);
00691                 break;
00692             }
00693         }
00694         status = TWI_GetStatus(pTwi);
00695         startTime = GetTicks();
00696         
00697         while( !(status & TWIHS_SR_TXRDY)) {
00698             status = TWI_GetStatus(pTwi);
00699             if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
00700                 TRACE_ERROR("TWID Timeout TXRDY\n\r");
00701                 break;
00702             }
00703         }
00704         /* Send a STOP condition */
00705         TWI_Stop(pTwi);
00706 
00707         TWI_WriteByte(pTwi, pData[num-1]);
00708         status = TWI_GetStatus(pTwi);
00709         startTime = GetTicks();
00710         
00711         while( !(status & TWIHS_SR_TXCOMP)) {
00712             status = TWI_GetStatus(pTwi);
00713             if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
00714                 TRACE_ERROR("TWID Timeout Write\n\r");
00715                 break;
00716             }
00717         }
00718         XDMAD_StopTransfer(pTwiXdma->pTwiDma, dmaWriteChannel );
00719         XDMAD_FreeChannel(pTwiXdma->pTwiDma, dmaWriteChannel);
00720         
00721     } 
00722     return 0;
00723 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines