SAMV71 Xplained Ultra Software Package 1.3

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