blob: e111a26a7a1ac7756452a1eb9ad39ffa2f50f1ef [file] [log] [blame]
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <assert.h>
/*----------------------------------------------------------------------------
* Definition
*----------------------------------------------------------------------------*/
#define TWITIMEOUTMAX 400
static uint32_t dmaWriteChannel,dmaReadChannel;
/*----------------------------------------------------------------------------
* Types
*----------------------------------------------------------------------------*/
/** TWI driver callback function.*/
typedef void (*TwiCallback)(Async *);
/** \brief TWI asynchronous transfer descriptor.*/
typedef struct _AsyncTwi {
/** Asynchronous transfer status. */
volatile uint8_t status;
/** Callback function to invoke when transfer completes or fails.*/
TwiCallback callback;
/** Pointer to the data buffer.*/
uint8_t *pData;
/** Total number of bytes to transfer.*/
uint32_t num;
/** Number of already transferred bytes.*/
uint32_t transferred;
} AsyncTwi;
/**
* \brief Initializes a TWI DMA Read channel.
*/
static void TWID_DmaInitializeRead(TwihsDma *pTwiXdma)
{
/* Allocate a XDMA channel, Read accesses into TWI_THR */
dmaReadChannel = XDMAD_AllocateChannel( pTwiXdma->pTwiDma, pTwiXdma->Twi_id,
XDMAD_TRANSFER_MEMORY);
if ( dmaReadChannel == XDMAD_ALLOC_FAILED ) {
printf("-E- Can't allocate XDMA channel\n\r");
}
XDMAD_PrepareChannel(pTwiXdma->pTwiDma, dmaReadChannel );
}
/**
* \brief Initializes a TWI DMA write channel.
*/
static void TWID_DmaInitializeWrite(TwihsDma *pTwiXdma)
{
/* Allocate a XDMA channel, Write accesses into TWI_THR */
dmaWriteChannel = XDMAD_AllocateChannel( pTwiXdma->pTwiDma, XDMAD_TRANSFER_MEMORY,
pTwiXdma->Twi_id);
if ( dmaWriteChannel == XDMAD_ALLOC_FAILED ) {
printf("-E- Can't allocate XDMA channel\n\r");
}
XDMAD_PrepareChannel(pTwiXdma->pTwiDma, dmaWriteChannel );
}
/**
* \brief Configure xDMA write linker list for TWI transfer.
*/
static uint8_t TWID_XdmaConfigureWrite(TwihsDma *pTwiXdma, uint8_t *buf, uint32_t len)
{
uint32_t xdmaCndc, Thr, xdmaInt;
sXdmadCfg xdmadTxCfg;
Thr = (uint32_t)&(TWIHS0->TWIHS_THR);
if(pTwiXdma->Twi_id==ID_TWIHS1) {
Thr = (uint32_t)&(TWIHS1->TWIHS_THR);
}
if(pTwiXdma->Twi_id==ID_TWIHS2) {
Thr = (uint32_t)&(TWIHS2->TWIHS_THR);
}
xdmadTxCfg.mbr_ubc = XDMA_UBC_NVIEW_NDV0 |
XDMA_UBC_NDE_FETCH_DIS|
XDMA_UBC_NSEN_UPDATED | len;
xdmadTxCfg.mbr_sa = (uint32_t)buf;
xdmadTxCfg.mbr_da = Thr;
xdmadTxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
XDMAC_CC_MBSIZE_SINGLE |
XDMAC_CC_DSYNC_MEM2PER |
XDMAC_CC_CSIZE_CHK_1 |
XDMAC_CC_DWIDTH_BYTE|
XDMAC_CC_SIF_AHB_IF0 |
XDMAC_CC_DIF_AHB_IF1 |
XDMAC_CC_SAM_INCREMENTED_AM |
XDMAC_CC_DAM_FIXED_AM |
XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(
pTwiXdma->Twi_id, XDMAD_TRANSFER_TX ));
xdmadTxCfg.mbr_bc = 0;
xdmadTxCfg.mbr_sus = 0;
xdmadTxCfg.mbr_dus =0;
xdmaCndc = 0;
xdmaInt = (XDMAC_CIE_BIE |
XDMAC_CIE_RBIE |
XDMAC_CIE_WBIE );
if (XDMAD_ConfigureTransfer( pTwiXdma->pTwiDma, dmaWriteChannel,
&xdmadTxCfg, xdmaCndc, 0, xdmaInt) )
return USARTD_ERROR;
return 0;
}
/**
* \brief Configure xDMA read linker list for TWI transfer.
*/
static uint8_t TWID_XdmaConfigureRead(TwihsDma *pTwiXdma, uint8_t *buf, uint32_t len)
{
uint32_t xdmaCndc, Rhr, xdmaInt;
sXdmadCfg xdmadRxCfg;
Rhr = (uint32_t)&(TWIHS0->TWIHS_RHR);
if(pTwiXdma->Twi_id==ID_TWIHS1) {
Rhr = (uint32_t)&(TWIHS1->TWIHS_RHR);
}
if(pTwiXdma->Twi_id==ID_TWIHS2) {
Rhr = (uint32_t)&(TWIHS2->TWIHS_RHR);
}
xdmadRxCfg.mbr_ubc = XDMA_UBC_NVIEW_NDV0 |
XDMA_UBC_NDE_FETCH_DIS|
XDMA_UBC_NDEN_UPDATED |
len;
xdmadRxCfg.mbr_da = (uint32_t)buf;
xdmadRxCfg.mbr_sa = Rhr;
xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN |
XDMAC_CC_MBSIZE_SINGLE |
XDMAC_CC_DSYNC_PER2MEM |
XDMAC_CC_CSIZE_CHK_1 |
XDMAC_CC_DWIDTH_BYTE |
XDMAC_CC_SIF_AHB_IF1 |
XDMAC_CC_DIF_AHB_IF0 |
XDMAC_CC_SAM_FIXED_AM |
XDMAC_CC_DAM_INCREMENTED_AM |
XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber(
pTwiXdma->Twi_id , XDMAD_TRANSFER_RX ));
xdmadRxCfg.mbr_bc = 0;
xdmadRxCfg.mbr_sus = 0;
xdmadRxCfg.mbr_dus =0;
xdmaCndc = 0;
xdmaInt = (XDMAC_CIE_BIE |
XDMAC_CIE_RBIE |
XDMAC_CIE_WBIE );
if (XDMAD_ConfigureTransfer( pTwiXdma->pTwiDma, dmaReadChannel,
&xdmadRxCfg, xdmaCndc, 0, xdmaInt))
return 1;
return 0;
}
/*----------------------------------------------------------------------------
* Global functions
*----------------------------------------------------------------------------*/
/**
* \brief Returns 1 if the given transfer has ended; otherwise returns 0.
* \param pAsync Pointer to an Async instance.
*/
uint32_t ASYNC_IsFinished( Async* pAsync )
{
return (pAsync->status != ASYNC_STATUS_PENDING) ;
}
/**
* \brief Initializes a TWI driver instance, using the given TWI peripheral.
* \note The peripheral must have been initialized properly before calling this
* function.
* \param pTwid Pointer to the Twid instance to initialize.
* \param pTwi Pointer to the TWI peripheral to use.
*/
void TWID_Initialize(Twid *pTwid, Twihs *pTwi)
{
TRACE_DEBUG( "TWID_Initialize()\n\r" ) ;
assert( pTwid != NULL ) ;
assert( pTwi != NULL ) ;
/* Initialize driver. */
pTwid->pTwi = pTwi;
pTwid->pTransfer = 0;
}
/**
* \brief Interrupt handler for a TWI peripheral. Manages asynchronous transfer
* occurring on the bus. This function MUST be called by the interrupt service
* routine of the TWI peripheral if asynchronous read/write are needed.
* \param pTwid Pointer to a Twid instance.
*/
void TWID_Handler( Twid *pTwid )
{
uint8_t status;
AsyncTwi *pTransfer ;
Twihs *pTwi ;
assert( pTwid != NULL ) ;
pTransfer = (AsyncTwi*)pTwid->pTransfer ;
assert( pTransfer != NULL ) ;
pTwi = pTwid->pTwi ;
assert( pTwi != NULL ) ;
/* Retrieve interrupt status */
status = TWI_GetMaskedStatus(pTwi);
/* Byte received */
if (TWI_STATUS_RXRDY(status)) {
pTransfer->pData[pTransfer->transferred] = TWI_ReadByte(pTwi);
pTransfer->transferred++;
/* check for transfer finish */
if (pTransfer->transferred == pTransfer->num) {
TWI_DisableIt(pTwi, TWIHS_IDR_RXRDY);
TWI_EnableIt(pTwi, TWIHS_IER_TXCOMP);
}
/* Last byte? */
else if (pTransfer->transferred == (pTransfer->num - 1)) {
TWI_Stop(pTwi);
}
}
/* Byte sent*/
else if (TWI_STATUS_TXRDY(status)) {
/* Transfer finished ? */
if (pTransfer->transferred == pTransfer->num) {
TWI_DisableIt(pTwi, TWIHS_IDR_TXRDY);
TWI_EnableIt(pTwi, TWIHS_IER_TXCOMP);
TWI_SendSTOPCondition(pTwi);
}
/* Bytes remaining */
else {
TWI_WriteByte(pTwi, pTransfer->pData[pTransfer->transferred]);
pTransfer->transferred++;
}
}
/* Transfer complete*/
else if (TWI_STATUS_TXCOMP(status)) {
TWI_DisableIt(pTwi, TWIHS_IDR_TXCOMP);
pTransfer->status = 0;
if (pTransfer->callback) {
pTransfer->callback((Async *) pTransfer);
}
pTwid->pTransfer = 0;
}
}
/**
* \brief Asynchronously reads data from a slave on the TWI bus. An optional
* callback function is triggered when the transfer is complete.
* \param pTwid Pointer to a Twid instance.
* \param address TWI slave address.
* \param iaddress Optional slave internal address.
* \param isize Internal address size in bytes.
* \param pData Data buffer for storing received bytes.
* \param num Number of bytes to read.
* \param pAsync Asynchronous transfer descriptor.
* \return 0 if the transfer has been started; otherwise returns a TWI error code.
*/
uint8_t TWID_Read(
Twid *pTwid,
uint8_t address,
uint32_t iaddress,
uint8_t isize,
uint8_t *pData,
uint32_t num,
Async *pAsync)
{
Twihs *pTwi;
AsyncTwi *pTransfer;
uint32_t startTime;
assert( pTwid != NULL ) ;
pTwi = pTwid->pTwi;
pTransfer = (AsyncTwi *) pTwid->pTransfer;
assert( (address & 0x80) == 0 ) ;
assert( (iaddress & 0xFF000000) == 0 ) ;
assert( isize < 4 ) ;
/* Check that no transfer is already pending*/
if (pTransfer) {
TRACE_ERROR("TWID_Read: A transfer is already pending\n\r");
return TWID_ERROR_BUSY;
}
/* Set STOP signal if only one byte is sent*/
if (num == 1) {
TWI_Stop(pTwi);
}
/* Asynchronous transfer*/
if (pAsync) {
/* Update the transfer descriptor */
pTwid->pTransfer = pAsync;
pTransfer = (AsyncTwi *) pAsync;
pTransfer->status = ASYNC_STATUS_PENDING;
pTransfer->pData = pData;
pTransfer->num = num;
pTransfer->transferred = 0;
/* Enable read interrupt and start the transfer */
TWI_EnableIt(pTwi, TWIHS_IER_RXRDY);
TWI_StartRead(pTwi, address, iaddress, isize);
}
/* Synchronous transfer*/
else {
/* Start read*/
TWI_StartRead(pTwi, address, iaddress, isize);
/* Read all bytes, setting STOP before the last byte*/
while (num > 0) {
/* Last byte ?*/
if (num == 1) {
TWI_Stop(pTwi);
}
/* Wait for byte then read and store it*/
startTime = GetTicks();
while( !TWI_ByteReceived(pTwi)) {
if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
TRACE_ERROR("TWID Timeout BR\n\r");
break;
}
}
*pData++ = TWI_ReadByte(pTwi);
num--;
}
/* Wait for transfer to be complete */
startTime = GetTicks();
while( !TWI_TransferComplete(pTwi) ) {
if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
TRACE_ERROR("TWID Timeout TC\n\r");
break;
}
}
}
return 0;
}
/**
* \brief Asynchronously sends data to a slave on the TWI bus. An optional
* callback function is invoked whenever the transfer is complete.
* \param pTwid Pointer to a Twid instance.
* \param address TWI slave address.
* \param iaddress Optional slave internal address.
* \param isize Number of internal address bytes.
* \param pData Data buffer for storing received bytes.
* \param num Data buffer to send.
* \param pAsync Asynchronous transfer descriptor.
* \return 0 if the transfer has been started; otherwise returns a TWI error code.
*/
uint8_t TWID_Write(
Twid *pTwid,
uint8_t address,
uint32_t iaddress,
uint8_t isize,
uint8_t *pData,
uint32_t num,
Async *pAsync)
{
Twihs *pTwi = pTwid->pTwi;
uint32_t startTime;
AsyncTwi *pTransfer = (AsyncTwi *) pTwid->pTransfer;
assert( pTwi != NULL ) ;
assert( (address & 0x80) == 0 ) ;
assert( (iaddress & 0xFF000000) == 0 ) ;
assert( isize < 4 ) ;
/* Check that no transfer is already pending */
if (pTransfer) {
TRACE_ERROR("TWI_Write: A transfer is already pending\n\r");
return TWID_ERROR_BUSY;
}
/* Asynchronous transfer */
if (pAsync) {
/* Update the transfer descriptor */
pTwid->pTransfer = pAsync;
pTransfer = (AsyncTwi *) pAsync;
pTransfer->status = ASYNC_STATUS_PENDING;
pTransfer->pData = pData;
pTransfer->num = num;
pTransfer->transferred = 1;
/* Enable write interrupt and start the transfer */
TWI_StartWrite(pTwi, address, iaddress, isize, *pData);
TWI_EnableIt(pTwi, TWIHS_IER_TXRDY);
} else {
/* Synchronous transfer*/
// Start write
TWI_StartWrite(pTwi, address, iaddress, isize, *pData++);
num--;
/* Send all bytes */
while (num > 0) {
/* Wait before sending the next byte */
startTime = GetTicks();
while( !TWI_ByteSent(pTwi) ) {
if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
TRACE_ERROR("TWID Timeout BS\n\r");
break;
}
}
TWI_WriteByte(pTwi, *pData++);
num--;
}
/* Wait for actual end of transfer */
startTime = GetTicks();
/* Send a STOP condition */
TWI_SendSTOPCondition(pTwi);
while( !TWI_TransferComplete(pTwi) ) {
if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
TRACE_ERROR("TWID Timeout TC2\n\r");
break;
}
}
}
return 0;
}
/**
* \brief Initializes a TWI driver instance, using the given TWI peripheral.
* \note The peripheral must have been initialized properly before calling this
* function.
* \param pTwid Pointer to the Twid instance to initialize.
* \param pTwi Pointer to the TWI peripheral to use.
*/
void TWID_DmaInitialize(TwihsDma *pTwidma, Twihs *pTwi, uint8_t bPolling)
{
TRACE_DEBUG( "TWID_Initialize()\n\r" ) ;
assert( pTwidma != NULL ) ;
if ((unsigned int)pTwi == (unsigned int)TWIHS0 ) pTwidma->Twi_id = ID_TWIHS0;
if ((unsigned int)pTwi == (unsigned int)TWIHS1 ) pTwidma->Twi_id = ID_TWIHS1;
if ((unsigned int)pTwi == (unsigned int)TWIHS2 ) pTwidma->Twi_id = ID_TWIHS2;
/* Initialize driver. */
pTwidma->pTwid->pTwi = pTwi;
pTwidma->pTwid->pTransfer = 0;
if(!bPolling) {
/* Enable XDMA interrupt and give it priority over any other peripheral
interrupt */
NVIC_ClearPendingIRQ(XDMAC_IRQn);
NVIC_SetPriority(XDMAC_IRQn, 1);
NVIC_EnableIRQ( XDMAC_IRQn );
}
/* Initialize XDMA driver instance with polling mode */
XDMAD_Initialize( pTwidma->pTwiDma, bPolling );
}
/**
* \brief Asynchronously reads data from a slave on the TWI bus. An optional
* callback function is triggered when the transfer is complete.
* \param pTwid Pointer to a Twid instance.
* \param address TWI slave address.
* \param iaddress Optional slave internal address.
* \param isize Internal address size in bytes.
* \param pData Data buffer for storing received bytes.
* \param num Number of bytes to read.
* \param pAsync Asynchronous transfer descriptor.
* \param TWI_ID TWI ID for TWI0, TWIHS1, TWIHS2.
* \return 0 if the transfer has been started; otherwise returns a TWI error code.
*/
uint8_t TWID_DmaRead(
TwihsDma *pTwiXdma,
uint8_t address,
uint32_t iaddress,
uint8_t isize,
uint8_t *pData,
uint32_t num,
Async *pAsync)
{
Twihs *pTwi;
AsyncTwi *pTransfer;
uint32_t status, startTime;
assert( pTwiXdma->pTwid != NULL ) ;
pTwi = pTwiXdma->pTwid->pTwi;
pTransfer = (AsyncTwi *) pTwiXdma->pTwid->pTransfer;
assert( (address & 0x80) == 0 ) ;
assert( (iaddress & 0xFF000000) == 0 ) ;
assert( isize < 4 ) ;
/* Check that no transfer is already pending*/
if (pTransfer) {
TRACE_ERROR("TWID_Read: A transfer is already pending\n\r");
return TWID_ERROR_BUSY;
}
/* Asynchronous transfer*/
if (pAsync) {
/* Update the transfer descriptor */
pTwiXdma->pTwid->pTransfer = pAsync;
pTransfer = (AsyncTwi *) pAsync;
pTransfer->status = ASYNC_STATUS_PENDING;
pTransfer->pData = pData;
pTransfer->num = num;
pTransfer->transferred = 0;
/* Enable read interrupt and start the transfer */
TWI_EnableIt(pTwi, TWIHS_IER_RXRDY);
TWI_StartRead(pTwi, address, iaddress, isize);
} else {
/* Synchronous transfer*/
TWID_DmaInitializeRead(pTwiXdma);
TWID_XdmaConfigureRead(pTwiXdma, pData, (num - 2));
// cache maintenance before starting DMA Xfr
SCB_CleanInvalidateDCache();
/* Start read*/
XDMAD_StartTransfer( pTwiXdma->pTwiDma, dmaReadChannel );
TWI_StartRead(pTwi, address, iaddress, isize);
startTime = GetTicks();
while( XDMAD_IsTransferDone(pTwiXdma->pTwiDma, dmaReadChannel) ) {
if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
TRACE_ERROR("TWID DMA not done\n\r");
break;
}
}
status = TWI_GetStatus(pTwi);
startTime = GetTicks();
while( !(status & TWIHS_SR_RXRDY)) {
status = TWI_GetStatus(pTwi);
if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
TRACE_ERROR("TWID DMA not done\n\r");
break;
}
}
TWI_Stop(pTwi);
pData[num - 2] = TWI_ReadByte(pTwi);
status = TWI_GetStatus(pTwi);
startTime = GetTicks();
while( !(status & TWIHS_SR_RXRDY)) {
status = TWI_GetStatus(pTwi);
if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
TRACE_ERROR("TWID Timeout Read\n\r");
break;
}
}
pData[num-1] = TWI_ReadByte(pTwi);
status = TWI_GetStatus(pTwi);
startTime = GetTicks();
while( !(status & TWIHS_SR_TXCOMP)) {
status = TWI_GetStatus(pTwi);
if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
TRACE_ERROR("TWID Timeout Read\n\r");
break;
}
}
XDMAD_StopTransfer( pTwiXdma->pTwiDma, dmaReadChannel );
XDMAD_FreeChannel(pTwiXdma->pTwiDma, dmaWriteChannel);
}
return 0;
}
/**
* \brief Asynchronously sends data to a slave on the TWI bus. An optional
* callback function is invoked whenever the transfer is complete.
* \param pTwid Pointer to a Twid instance.
* \param address TWI slave address.
* \param iaddress Optional slave internal address.
* \param isize Number of internal address bytes.
* \param pData Data buffer for storing received bytes.
* \param num Data buffer to send.
* \param pAsync Asynchronous transfer descriptor.
* \param TWI_ID TWIHS ID for TWIHS0, TWIHS1, TWIHS2.
* \return 0 if the transfer has been started; otherwise returns a TWI error code.
*/
uint8_t TWID_DmaWrite(
TwihsDma *pTwiXdma,
uint8_t address,
uint32_t iaddress,
uint8_t isize,
uint8_t *pData,
uint32_t num,
Async *pAsync)
{
Twihs *pTwi = pTwiXdma->pTwid->pTwi;
AsyncTwi *pTransfer = (AsyncTwi *) pTwiXdma->pTwid->pTransfer;
uint32_t status, startTime;
//uint8_t singleTransfer = 0;
assert( pTwi != NULL ) ;
assert( (address & 0x80) == 0 ) ;
assert( (iaddress & 0xFF000000) == 0 ) ;
assert( isize < 4 ) ;
// if(num == 1) singleTransfer = 1;
/* Check that no transfer is already pending */
if (pTransfer) {
TRACE_ERROR("TWI_Write: A transfer is already pending\n\r");
return TWID_ERROR_BUSY;
}
/* Asynchronous transfer */
if (pAsync) {
/* Update the transfer descriptor */
pTwiXdma->pTwid->pTransfer = pAsync;
pTransfer = (AsyncTwi *) pAsync;
pTransfer->status = ASYNC_STATUS_PENDING;
pTransfer->pData = pData;
pTransfer->num = num;
pTransfer->transferred = 1;
/* Enable write interrupt and start the transfer */
TWI_StartWrite(pTwi, address, iaddress, isize, *pData);
TWI_EnableIt(pTwi, TWIHS_IER_TXRDY);
} else {
/* Synchronous transfer*/
TWID_DmaInitializeWrite(pTwiXdma);
TWID_XdmaConfigureWrite(pTwiXdma, pData, (num - 1) );
/* Set slave address and number of internal address bytes. */
pTwi->TWIHS_MMR = 0;
pTwi->TWIHS_MMR = (isize << 8) | (address << 16);
/* Set internal address bytes. */
pTwi->TWIHS_IADR = 0;
pTwi->TWIHS_IADR = iaddress;
// cache maintenance before starting DMA Xfr
SCB_CleanInvalidateDCache();
startTime = GetTicks();
XDMAD_StartTransfer( pTwiXdma->pTwiDma, dmaWriteChannel );
while( (XDMAD_IsTransferDone(pTwiXdma->pTwiDma, dmaWriteChannel)) ) {
if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
TRACE_ERROR("TWID DMA not done, Channel State is %d\n\r",
pTwiXdma->pTwiDma->XdmaChannels[dmaWriteChannel].state);
break;
}
}
status = TWI_GetStatus(pTwi);
startTime = GetTicks();
while( !(status & TWIHS_SR_TXRDY)) {
status = TWI_GetStatus(pTwi);
if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
TRACE_ERROR("TWID Timeout TXRDY\n\r");
break;
}
}
/* Send a STOP condition */
TWI_Stop(pTwi);
TWI_WriteByte(pTwi, pData[num-1]);
status = TWI_GetStatus(pTwi);
startTime = GetTicks();
while( !(status & TWIHS_SR_TXCOMP)) {
status = TWI_GetStatus(pTwi);
if ( (GetDelayInTicks(startTime, GetTicks() ) ) > TWITIMEOUTMAX) {
TRACE_ERROR("TWID Timeout Write\n\r");
break;
}
}
XDMAD_StopTransfer(pTwiXdma->pTwiDma, dmaWriteChannel );
XDMAD_FreeChannel(pTwiXdma->pTwiDma, dmaWriteChannel);
}
return 0;
}