SAMV71 Xplained Ultra Software Package 1.5

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