diff options
Diffstat (limited to 'c/src/lib/libbsp/arm/atsam/libraries/libchip/source/twid.c')
-rw-r--r-- | c/src/lib/libbsp/arm/atsam/libraries/libchip/source/twid.c | 752 |
1 files changed, 0 insertions, 752 deletions
diff --git a/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/twid.c b/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/twid.c deleted file mode 100644 index 4f770691c5..0000000000 --- a/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/twid.c +++ /dev/null @@ -1,752 +0,0 @@ -/* ---------------------------------------------------------------------------- */ -/* Atmel Microcontroller Software Support */ -/* SAM Software Package License */ -/* ---------------------------------------------------------------------------- */ -/* Copyright (c) 2015, Atmel Corporation */ -/* */ -/* All rights reserved. */ -/* */ -/* Redistribution and use in source and binary forms, with or without */ -/* modification, are permitted provided that the following condition is 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; - -extern uint32_t twi_send_stop; - -/*---------------------------------------------------------------------------- - * 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_IF1 | - 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_IF1 | - 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; - } - - /* In single data byte master read, the START and STOP must both be set */ - twi_send_stop = (num == 1) ? 1 : 0; - - /* 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; - - assert(!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)); - - /* Start read*/ - XDMAD_StartTransfer(pTwiXdma->pTwiDma, dmaReadChannel); - TWI_StartRead(pTwi, address, iaddress, isize); - - startTime = GetTicks(); - status = XDMAD_IsTransferDone(pTwiXdma->pTwiDma, dmaReadChannel); - - while (status != XDMAD_OK) { - status = XDMAD_IsTransferDone(pTwiXdma->pTwiDma, dmaReadChannel); - - if ((GetDelayInTicks(startTime, GetTicks())) > TWITIMEOUTMAX) { - TRACE_ERROR("TWID DMA not done\n\r"); - break; - } - } - - if (XDMAD_OK == status) - SCB_InvalidateDCache_by_Addr((uint32_t *)pData, (num - 2)); - - 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_CleanDCache_by_Addr((uint32_t *)pData, (num - 1)); - 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; -} |