Platform/ECM3532/M3/hw/hal/ecm3532/spi_slave/src/spi_slave_hal.c
/**
 * SPI Slave send and receive routine, works in half-duplex mode.
 *
 * For Send should be called with valid Xmit buffer and count
 * For Receive should be called with valid Receive buffer and count.
 *
 *
 * In send mode TX buffer contain data to be send, transfer count specify the send
 * data length in bytes,
 * In receive mode RX count specify the byte length to be  receive in receive buffer
 *
 * If called with valid (non zero) callback function, it will be a non blocking
 * call and callback function will be called after completion from interrupt
 * context, callback function must only be used for signal of completion as it
 * is called from interrupt context
 * if callback function is NULL, API will be blocking API and will retun after
 * comletetion of SPI transfer
 *
 * @param ui8Spi        SPI interface to use
 * @param ui8TxBuf      Pointer to buffer where values to transmit are stored.
 * @param ui32TxCnt     Transmit byte count.
 * @param ui8Rxbuf      Pointer to buffer to store values received from slave.
 * @param ui32TxCnt     Receive byte count.
 * @param fXferDoneCb   callback function pointer, for async call.
 * @param vCbArg        Argument for callback funct pointer
 *
 * @return int 0 on success, non-zero error code on failure.
 */
SPI Slave send and receive routine, works in half-duplex mode.
For Send should be called with valid Xmit buffer and count
For Receive should be called with valid Receive buffer and count.

In send mode TX buffer contain data to be send, transfer count specify the send
data length in bytes,
In receive mode RX count specify the byte length to be  receive in receive buffer

If called with valid (non zero) callback function, it will be a non blocking
call and callback function will be called after completion from interrupt
context, callback function must only be used for signal of completion as it
is called from interrupt context
if callback function is NULL, API will be blocking API and will retun after
comletetion of SPI transfer

@param ui8Spi        SPI interface to use
@param ui8TxBuf      Pointer to buffer where values to transmit are stored.
@param ui32TxCnt     Transmit byte count.
@param ui8Rxbuf      Pointer to buffer to store values received from slave.
@param ui32TxCnt     Receive byte count.
@param fXferDoneCb   callback function pointer, for async call.
@param vCbArg        Argument for callback funct pointer

@return int 0 on success, non-zero error code on failure.
SPI Slave send and receive routine works in half - duplex mode . For Send should be called with valid Xmit buffer and count For Receive should be called with valid Receive buffer and count . In send mode TX buffer contain data to be send transfer count specify the send data length in bytes In receive mode RX count specify the byte length to be receive in receive buffer If called with valid ( non zero ) callback function it will be a non blocking call and callback function will be called after completion from interrupt context callback function must only be used for signal of completion as it is called from interrupt context if callback function is NULL API will be blocking API and will retun after comletetion of SPI transfer @param ui8Spi SPI interface to use @param ui8TxBuf Pointer to buffer where values to transmit are stored . @param ui32TxCnt Transmit byte count . @param ui8Rxbuf Pointer to buffer to store values received from slave . @param ui32TxCnt Receive byte count . @param fXferDoneCb callback function pointer for async call . @param vCbArg Argument for callback funct pointer @return int 0 on success non - zero error code on failure .
int32_t HalSpiSlaveXfer(uint8_t ui8Spi, uint8_t *ui8TxBuf,
                    uint32_t ui32TxCnt, uint8_t *ui8RxBuf, uint32_t ui32RxCnt,
                    tHalSpiXferDoneCb fSpiCb, void *vCbArg)
{
    struct sDevSpiSlv *sDev;
    int32_t i32Ret = 0;
    uint8_t bFlush ;
    uint8_t ui8Cnt= 0, ui8Data;
    (void)ui8Data;
    sDev = SpiGetDev(ui8Spi);
    if (sDev == NULL) {
        return -EINVAL;
    }
    xSemaphoreTake(sDev->SpiLock, portMAX_DELAY);
    if (sDev->ui8SpiState != HalSpiCmdDone)
    {
        i32Ret = -EBUSY;
        goto err_exit;
    }
    else if (ui8TxBuf && ui32TxCnt)
    {
        sDev->ui8SpiState = HalSpiInTx;
        sDev->ui32TxByteCnt = ui32TxCnt;
        sDev->ui8TxBuf = ui8TxBuf;
    }
    else if (ui8RxBuf || ui32RxCnt)
    {
        sDev->ui8SpiState = HalSpiInRx;
        sDev->ui32RxByteCnt = ui32RxCnt;
        sDev->ui8RxBuf = ui8RxBuf;
    }
    else
    {
        i32Ret = -EBUSY;
        goto err_exit;
    }
    if (fSpiCb)
    {
        sDev->fXferDoneCb = fSpiCb;
        sDev->vSpiCbArg = vCbArg;
    }
    if (sDev->ui8SpiState == HalSpiInTx)
    {
        SpiSlaveXmit(sDev);
        if (sDev->ui32TxByteCnt > (sDev->ui8FifoDepth - 2))
                REG_SPI_CONFIG(ui8Spi).BF.FIFO_LEVEL_TRIG =
                            sDev->ui8FifoDepth - 2 ;
            else
                REG_SPI_CONFIG(ui8Spi).BF.FIFO_LEVEL_TRIG =
                            sDev->ui32TxByteCnt;
        EnableSpiIntr(ui8Spi,SPI_TX_INTR);
        bFlush = 1;
    }
    else if (sDev->ui8SpiState == HalSpiInRx)
    {
        if (sDev->ui32RxByteCnt > sDev->ui8FifoDepth)
            REG_SPI_CONFIG(ui8Spi).BF.FIFO_LEVEL_TRIG =
                sDev->ui8FifoDepth;
        else
            REG_SPI_CONFIG(ui8Spi).BF.FIFO_LEVEL_TRIG =
                sDev->ui32RxByteCnt;
        sDev->ui8SpiState = HalSpiInRx;
        EnableSpiIntr(ui8Spi, BM_SPI_INT_EN_RX_DATA_EN0);
    }
    if(!sDev->fXferDoneCb)
    {
        if (sDev->ui8SpiState == HalSpiInRx)
        {
            xSemaphoreTake(sDev->SpiCmdDoneLock, portMAX_DELAY);
        }
        else
        {
            do {
            } while (pdTRUE != xSemaphoreTake(sDev->SpiCmdDoneLock, 1));
        }
    }
    if (bFlush)
    {
        ui8Cnt = MEMIO8(REG_SPI_RX_FIFO_DEBUG_ADDR(sDev->ui8Spi)) &
                BM_SPI_RX_FIFO_DEBUG_ENTRIES;
            while(ui8Cnt)
            {
                ui8Data = REG_SPI_TXRX_1BYTE_FIFO_DATA(ui8Spi).V;
                ui8Cnt--;
            }
    }
err_exit:
    xSemaphoreGive(sDev->SpiLock);
    return i32Ret;
}
int32_t HalSpiSlaveXfer ( uint8_t ui8Spi , uint8_t * ui8TxBuf , uint32_t ui32TxCnt , uint8_t * ui8RxBuf , uint32_t ui32RxCnt , tHalSpiXferDoneCb fSpiCb , void * vCbArg ) { struct sDevSpiSlv * sDev ; int32_t i32Ret = 0 ; uint8_t bFlush ; uint8_t ui8Cnt = 0 , ui8Data ; ( void ) ui8Data ; sDev = SpiGetDev ( ui8Spi ) ; if ( sDev == NULL ) { return - EINVAL ; } xSemaphoreTake ( sDev -> SpiLock , portMAX_DELAY ) ; if ( sDev -> ui8SpiState != HalSpiCmdDone ) { i32Ret = - EBUSY ; goto err_exit ; } else if ( ui8TxBuf && ui32TxCnt ) { sDev -> ui8SpiState = HalSpiInTx ; sDev -> ui32TxByteCnt = ui32TxCnt ; sDev -> ui8TxBuf = ui8TxBuf ; } else if ( ui8RxBuf || ui32RxCnt ) { sDev -> ui8SpiState = HalSpiInRx ; sDev -> ui32RxByteCnt = ui32RxCnt ; sDev -> ui8RxBuf = ui8RxBuf ; } else { i32Ret = - EBUSY ; goto err_exit ; } if ( fSpiCb ) { sDev -> fXferDoneCb = fSpiCb ; sDev -> vSpiCbArg = vCbArg ; } if ( sDev -> ui8SpiState == HalSpiInTx ) { SpiSlaveXmit ( sDev ) ; if ( sDev -> ui32TxByteCnt > ( sDev -> ui8FifoDepth - 2 ) ) REG_SPI_CONFIG ( ui8Spi ) . BF . FIFO_LEVEL_TRIG = sDev -> ui8FifoDepth - 2 ; else REG_SPI_CONFIG ( ui8Spi ) . BF . FIFO_LEVEL_TRIG = sDev -> ui32TxByteCnt ; EnableSpiIntr ( ui8Spi , SPI_TX_INTR ) ; bFlush = 1 ; } else if ( sDev -> ui8SpiState == HalSpiInRx ) { if ( sDev -> ui32RxByteCnt > sDev -> ui8FifoDepth ) REG_SPI_CONFIG ( ui8Spi ) . BF . FIFO_LEVEL_TRIG = sDev -> ui8FifoDepth ; else REG_SPI_CONFIG ( ui8Spi ) . BF . FIFO_LEVEL_TRIG = sDev -> ui32RxByteCnt ; sDev -> ui8SpiState = HalSpiInRx ; EnableSpiIntr ( ui8Spi , BM_SPI_INT_EN_RX_DATA_EN0 ) ; } if ( ! sDev -> fXferDoneCb ) { if ( sDev -> ui8SpiState == HalSpiInRx ) { xSemaphoreTake ( sDev -> SpiCmdDoneLock , portMAX_DELAY ) ; } else { do { } while ( pdTRUE != xSemaphoreTake ( sDev -> SpiCmdDoneLock , 1 ) ) ; } } if ( bFlush ) { ui8Cnt = MEMIO8 ( REG_SPI_RX_FIFO_DEBUG_ADDR ( sDev -> ui8Spi ) ) & BM_SPI_RX_FIFO_DEBUG_ENTRIES ; while ( ui8Cnt ) { ui8Data = REG_SPI_TXRX_1BYTE_FIFO_DATA ( ui8Spi ) . V ; ui8Cnt -- ; } } err_exit : xSemaphoreGive ( sDev -> SpiLock ) ; return i32Ret ; }
SPI Slave send and receive routine, works in half-duplex mode.
SPI Slave send and receive routine works in half - duplex mode .
/* Enable RX interrupt to get notified of RX */