/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_DRV_SlaveSendDataBlocking
 * Description   : Send the data using a blocking method.
 * This function set buffer pointer and length to Tx buffer & Tx Size.
 * Then wait until the transmission is end ( NAK is detected)
 *
 *END**************************************************************************/
i2c_status_t I2C_DRV_SlaveSendDataBlocking(uint32_t instance,
                                           const uint8_t * txBuff,
                                           uint32_t txSize,
                                           uint32_t timeout_ms)
{
    assert(txBuff);
    assert(instance < HW_I2C_INSTANCE_COUNT);

    i2c_slave_state_t * i2cSlaveState = (i2c_slave_state_t *)g_i2cStatePtr[instance];

    if(!i2cSlaveState->slaveListening)
    {
        event_flags_t i2cIrqSetFlags;
        osa_status_t syncStatus;

        if (i2cSlaveState->isTxBusy)
        {
            return kStatus_I2C_Busy;
        }

        /* Initialize the module driver state structure. */
        i2cSlaveState->txBuff = txBuff;
        i2cSlaveState->txSize = txSize;
        i2cSlaveState->isTxBusy = true;
        i2cSlaveState->isTxBlocking = true;

#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT
        I2C_HAL_ClearStartFlag(g_i2cBaseAddr[instance]);
#endif
        I2C_HAL_ClearInt(g_i2cBaseAddr[instance]);
        I2C_HAL_SetIntCmd(g_i2cBaseAddr[instance], true);

        /* Wait until the transmit is complete. */
        do
        {
            syncStatus = OSA_EventWait(&i2cSlaveState->irqEvent,
                                       kI2CSlaveTxNAK | kI2CSlaveAbort,
                                       false,
                                       timeout_ms,
                                       &i2cIrqSetFlags);
        } while(syncStatus == kStatus_OSA_Idle);

        if (syncStatus != kStatus_OSA_Success)
        {
            I2C_HAL_SetIntCmd(g_i2cBaseAddr[instance], false);
            i2cSlaveState->status = kStatus_I2C_Timeout;
        }

        i2cSlaveState->isTxBlocking = false;

        return i2cSlaveState->status;
    }
    else /* i2cSlaveState->slaveListening */
    {
        return kStatus_I2C_Fail;
    }
}
Пример #2
0
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_DRV_SlaveAbortSendData
 * Description   : This function is used to abort sending of I2C slave
 *
 *END*/
i2c_status_t I2C_DRV_SlaveAbortSendData(uint32_t instance, uint32_t *txSize)
{
    assert(instance < I2C_INSTANCE_COUNT);
    i2c_slave_state_t * i2cSlaveState = (i2c_slave_state_t *)g_i2cStatePtr[instance];

    *txSize = i2cSlaveState->txSize;

     /** Check if a transfer is running. */
    if (!i2cSlaveState->isTxBusy)
    {
        return kStatus_I2C_NoSendInProgress;
    }

     /** Stop the running transfer. */
    i2cSlaveState->isTxBusy = false;
    i2cSlaveState->txBuff = NULL;
    i2cSlaveState->txSize = 0;

    if(!i2cSlaveState->slaveListening)
    {
         /** Disable I2C interrupt in the peripheral.*/
        I2C_HAL_SetIntCmd(g_i2cBase[instance], false);

        if (i2cSlaveState->isTxBlocking)
        {
             /** Set kI2CSlaveTxEmpty event to notify that the sending is done */
            OSA_EventSet(&i2cSlaveState->irqEvent, kI2CSlaveAbort);
        }
    }

    return kStatus_I2C_Success;
}
Пример #3
0
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_DRV_SlaveSendData
 * Description   : Send the data using a non-blocking method.
 * This function set buffer pointer and length to Tx buffer & Tx Size
 * A non-blocking (also known as synchronous) function means that the function
 * returns immediately after initiating the receive function. The application
 * has to get the receive status to see when the receive is complete.
 *
 *END*/
i2c_status_t I2C_DRV_SlaveSendData(uint32_t instance,
                                   const uint8_t * txBuff,
                                   uint32_t txSize)
{
    assert(txBuff);
    assert(instance < I2C_INSTANCE_COUNT);

    i2c_slave_state_t * i2cSlaveState = (i2c_slave_state_t *)g_i2cStatePtr[instance];

    if(!i2cSlaveState->slaveListening)
    {
        if (i2cSlaveState->isTxBusy)
        {
            return kStatus_I2C_Busy;
        }

         /** Initialize the module driver state structure. */
        i2cSlaveState->txBuff = txBuff;
        i2cSlaveState->txSize = txSize;
        i2cSlaveState->isTxBusy = true;

        I2C_HAL_SetIntCmd(g_i2cBase[instance], true);

        return kStatus_I2C_Success;
    }
    else  /** i2cSlaveState->slaveListening */
    {
        return kStatus_I2C_Fail;
    }
}
// Public Methods //////////////////////////////////////////////////////////////
void TwoWire::begin(uint8_t address)
{
    rxBufferIndex = 0;
    rxBufferLength = 0;

    txBufferIndex = 0;
    txBufferLength = 0;

    slaveBufferIndex = 0;
    slaveBufferLength = 0;

    transmitting_master = false;
    transmitting_slave = false;
    receiving_slave = false;

    SIM_HAL_EnableClock(SIM, gate_name);

    PORT_CLOCK_ENABLE(sda);
    PORT_CLOCK_ENABLE(scl);
    PORT_BWR_PCR_ODE(PERIPH_PORT(sda), PINS_PIN(sda), true); //set as open drain
    PORT_BWR_PCR_ODE(PERIPH_PORT(scl), PINS_PIN(scl), true); //set as open drain
    PORT_SET_MUX_I2C(sda);
    PORT_SET_MUX_I2C(scl);
    I2C_HAL_Init(instance);

    I2C_HAL_SetAddress7bit(instance, address);
    I2C_HAL_SetStartStopIntCmd(instance, true);
    I2C_HAL_SetIntCmd(instance, true);
    NVIC_EnableIRQ(irqNumber);
    I2C_HAL_Enable(instance);
    setClock(100000);
}
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_DRV_SlaveInit
 * Description   : initializes the I2C module.
 * This function will save the application callback info, turn on the clock of
 * I2C instance, setup according to user configuration.
 *
 *END**************************************************************************/
void I2C_DRV_SlaveInit(uint32_t instance,
                       const i2c_slave_user_config_t * userConfigPtr,
                       i2c_slave_state_t * slave)
{
    assert(slave);
    assert(instance < HW_I2C_INSTANCE_COUNT);

    uint32_t baseAddr = g_i2cBaseAddr[instance];

    /* Exit if current instance is already initialized. */
    if (g_i2cStatePtr[instance])
    {
        return;
    }

    /* Init driver instance structure */
    memset(slave, 0, sizeof(i2c_slave_state_t));
    slave->slaveListening = userConfigPtr->slaveListening;
    slave->slaveCallback = userConfigPtr->slaveCallback;
    slave->callbackParam = userConfigPtr->callbackParam;

    /* Enable clock for I2C.*/
    CLOCK_SYS_EnableI2cClock(instance);

    /* Init instance to known state. */
    I2C_HAL_Init(baseAddr);

    /* Set slave address.*/
    I2C_HAL_SetAddress7bit(baseAddr, userConfigPtr->address);

    /* Save runtime structure pointer.*/
    g_i2cStatePtr[instance] = slave;

    /* Create Event for irqSync */
    OSA_EventCreate(&slave->irqEvent, kEventAutoClear);

#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT
    /* Enable I2C START&STOP signal detect interrupt in the peripheral.*/
    if(userConfigPtr->startStopDetect)
    {
        I2C_HAL_SetStartStopIntCmd(baseAddr,true);
    }
#endif
#if FSL_FEATURE_I2C_HAS_STOP_DETECT
    /* Enable STOP signal detect interrupt in the peripheral.*/
    if(userConfigPtr->stopDetect)
    {
        I2C_HAL_SetStopIntCmd(baseAddr,true);
    }
#endif

    /* Enable I2C interrupt as default if setup slave listening mode */
    I2C_HAL_SetIntCmd(baseAddr, slave->slaveListening);

    /* Enable I2C interrupt from NVIC */
    INT_SYS_EnableIRQ(g_i2cIrqId[instance]);

    /* Enable the peripheral operation.*/
    I2C_HAL_Enable(baseAddr);
}
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_DRV_SlaveSendData
 * Description   : Send the data using a non-blocking method.
 * This function set buffer pointer and length to Tx buffer & Tx Size
 * A non-blocking (also known as synchronous) function means that the function
 * returns immediately after initiating the receive function. The application
 * has to get the receive status to see when the receive is complete.
 *
 *END**************************************************************************/
i2c_status_t I2C_DRV_SlaveSendData(uint32_t instance,
                                   const uint8_t * txBuff,
                                   uint32_t txSize)
{
    assert(txBuff);
    assert(instance < HW_I2C_INSTANCE_COUNT);

    i2c_slave_state_t * i2cSlaveState = (i2c_slave_state_t *)g_i2cStatePtr[instance];

    if(!i2cSlaveState->slaveListening)
    {
        if (i2cSlaveState->isTxBusy)
        {
            return kStatus_I2C_Busy;
        }

        /* Initialize the module driver state structure. */
        i2cSlaveState->txBuff = txBuff;
        i2cSlaveState->txSize = txSize;
        i2cSlaveState->isTxBusy = true;

#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT
        I2C_HAL_ClearStartFlag(g_i2cBaseAddr[instance]);
#endif
        I2C_HAL_ClearInt(g_i2cBaseAddr[instance]);
        I2C_HAL_SetIntCmd(g_i2cBaseAddr[instance], true);

        return kStatus_I2C_Success;
    }
    else /* i2cSlaveState->slaveListening */
    {
        return kStatus_I2C_Fail;
    }
}
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_DRV_SlaveDeinit
 * Description   : Shuts down the I2C slave driver.
 * This function will clear the control register and turn off the clock to the
 * module.
 *
 *END**************************************************************************/
void I2C_DRV_SlaveDeinit(uint32_t instance)
{
    assert(instance < HW_I2C_INSTANCE_COUNT);

    uint32_t baseAddr = g_i2cBaseAddr[instance];
    i2c_slave_state_t * i2cSlaveState = (i2c_slave_state_t *)g_i2cStatePtr[instance];

#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT
    /* Disable I2C START&STOP signal detect interrupt in the peripheral.*/
    I2C_HAL_SetStartStopIntCmd(baseAddr,false);
#endif
#if FSL_FEATURE_I2C_HAS_STOP_DETECT
    /* Disable STOP signal detect interrupt in the peripheral.*/
    I2C_HAL_SetStopIntCmd(baseAddr,false);
#endif

    /* Disable I2C interrupt. */
    I2C_HAL_SetIntCmd(baseAddr, false);

    /* Turn off I2C.*/
    I2C_HAL_Disable(baseAddr);

    /* Disable clock for I2C.*/
    CLOCK_SYS_DisableI2cClock(instance);

    /* Disable I2C NVIC interrupt */
    INT_SYS_DisableIRQ(g_i2cIrqId[instance]);

    /* Destroy sema. */
    OSA_EventDestroy(&i2cSlaveState->irqEvent);

    /* Clear runtime structure poniter.*/
    g_i2cStatePtr[instance] = NULL;
}
Пример #8
0
void i2c_slave_mode(i2c_t *obj, int enable_slave) {
    uint32_t i2c_addrs[] = I2C_BASE_ADDRS;
    if (enable_slave) {
        // set slave mode
        BW_I2C_C1_MST(i2c_addrs[obj->instance], 0);
        I2C_HAL_SetIntCmd(i2c_addrs[obj->instance], true);
    } else {
        // set master mode
        BW_I2C_C1_MST(i2c_addrs[obj->instance], 1);
    }
}
Пример #9
0
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_DRV_SlaveDeinit
 * Description   : Shuts down the I2C slave driver.
 * This function will clear the control register and turn off the clock to the
 * module.
 *
 *END*/
i2c_status_t I2C_DRV_SlaveDeinit(uint32_t instance)
{
    assert(instance < I2C_INSTANCE_COUNT);

     /** Exit if current instance is already de-initialized or is gated.*/
    if ((!g_i2cStatePtr[instance]) || (!CLOCK_SYS_GetI2cGateCmd(instance)))
    {
        return kStatus_I2C_Fail;
    }

    I2C_Type * base = g_i2cBase[instance];
    i2c_slave_state_t * i2cSlaveState = (i2c_slave_state_t *)g_i2cStatePtr[instance];

#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT
     /** Disable I2C START&STOP signal detect interrupt in the peripheral.*/
    I2C_HAL_SetStartStopIntCmd(base,false);
#endif
#if FSL_FEATURE_I2C_HAS_STOP_DETECT
     /** Disable STOP signal detect interrupt in the peripheral.*/
    I2C_HAL_SetStopIntCmd(base,false);
#endif

     /** Disable I2C interrupt. */
    I2C_HAL_SetIntCmd(base, false);

     /** Turn off I2C.*/
    I2C_HAL_Disable(base);

     /** Disable clock for I2C.*/
    CLOCK_SYS_DisableI2cClock(instance);

     /** Disable I2C NVIC interrupt */
    INT_SYS_DisableIRQ(g_i2cIrqId[instance]);

     /** Destroy sema. */
    OSA_EventDestroy(&i2cSlaveState->irqEvent);

     /** Clear runtime structure poniter.*/
    g_i2cStatePtr[instance] = NULL;

    return kStatus_I2C_Success;
}
Пример #10
0
void i2c_init(i2c_t *obj, PinName sda, PinName scl) {
    uint32_t i2c_sda = pinmap_peripheral(sda, PinMap_I2C_SDA);
    uint32_t i2c_scl = pinmap_peripheral(scl, PinMap_I2C_SCL);
    obj->instance = pinmap_merge(i2c_sda, i2c_scl);
    MBED_ASSERT((int)obj->instance != NC);

    CLOCK_SYS_EnableI2cClock(obj->instance);
    uint32_t i2c_addrs[] = I2C_BASE_ADDRS;
    I2C_HAL_Init(i2c_addrs[obj->instance]);
    I2C_HAL_Enable(i2c_addrs[obj->instance]);
    I2C_HAL_SetIntCmd(i2c_addrs[obj->instance], true);
    i2c_frequency(obj, 100000);

    pinmap_pinout(sda, PinMap_I2C_SDA);
    pinmap_pinout(scl, PinMap_I2C_SCL);

    uint32_t port_addrs[] = PORT_BASE_ADDRS;
    PORT_HAL_SetOpenDrainCmd(port_addrs[sda >> GPIO_PORT_SHIFT], sda & 0xFF, true);
    PORT_HAL_SetOpenDrainCmd(port_addrs[scl >> GPIO_PORT_SHIFT], scl & 0xFF, true);
}
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_DRV_SlaveReceiveData
 * Description   : Receive the data using a non-blocking method.
 * This function set buffer pointer and length to Rx buffer & Rx Size
 * A non-blocking (also known as synchronous) function means that the function
 * returns immediately after initiating the receive function. The application
 * has to get the receive status to see when the receive is complete.
 *
 *END**************************************************************************/
i2c_status_t I2C_DRV_SlaveReceiveData(uint32_t instance,
                                      uint8_t * rxBuff,
                                      uint32_t rxSize)
{
    assert(rxBuff);
    assert(instance < HW_I2C_INSTANCE_COUNT);

    i2c_slave_state_t * i2cSlaveState = (i2c_slave_state_t *)g_i2cStatePtr[instance];

    if(!i2cSlaveState->slaveListening)
    {
        if (i2cSlaveState->isRxBusy)
        {
            return kStatus_I2C_Busy;
        }

        i2cSlaveState->rxBuff = rxBuff;
        i2cSlaveState->rxSize = rxSize;
        i2cSlaveState->isRxBusy = true;

        /* If IAAS event already comes, read dummy to release the bus.*/
        if(I2C_HAL_GetStatusFlag(g_i2cBaseAddr[instance], kI2CAddressAsSlave))
        {
             /* Switch to RX mode.*/
            I2C_HAL_SetDirMode(g_i2cBaseAddr[instance], kI2CReceive);
            I2C_HAL_ReadByte(g_i2cBaseAddr[instance]);
        }

#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT
        I2C_HAL_ClearStartFlag(g_i2cBaseAddr[instance]);
#endif
        I2C_HAL_ClearInt(g_i2cBaseAddr[instance]);
        I2C_HAL_SetIntCmd(g_i2cBaseAddr[instance], true);

        return kStatus_I2C_Success;
    }
    else /* i2cSlaveState->slaveListening */
    {
        return kStatus_I2C_Fail;
    }
}
Пример #12
0
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_DRV_SlaveIRQHandler
 * Description   : I2C Slave Generic ISR.
 * ISR action be called inside I2C IRQ handler entry.
 *
 *END*/
void I2C_DRV_SlaveIRQHandler(uint32_t instance)
{
    assert(instance < I2C_INSTANCE_COUNT);

    I2C_Type * base = g_i2cBase[instance];
    uint8_t  i2cData  = 0x00;
    bool     doTransmit = false;
    bool     wasArbLost = I2C_HAL_GetStatusFlag(base, kI2CArbitrationLost);
    bool     addressed = I2C_HAL_GetStatusFlag(base, kI2CAddressAsSlave);
    bool     stopIntEnabled = false;

#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT
    bool     startDetected = I2C_HAL_GetStartFlag(base);
    bool     startIntEnabled = I2C_HAL_GetStartStopIntCmd(base);
    bool     stopDetected = I2C_HAL_GetStopFlag(base);
    stopIntEnabled = startIntEnabled;
#endif

#if FSL_FEATURE_I2C_HAS_STOP_DETECT
    bool     stopDetected = I2C_HAL_GetStopFlag(base);
    stopIntEnabled = I2C_HAL_GetStopIntCmd(base);
#endif

     /** Get current runtime structure */
    i2c_slave_state_t * i2cSlaveState = (i2c_slave_state_t *)g_i2cStatePtr[instance];

     /** Get current slave transfer direction */
    i2c_direction_t direction = I2C_HAL_GetDirMode(base);

#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT
    /*--------------- Handle START ------------------*/
    if (startIntEnabled && startDetected)
    {
        I2C_HAL_ClearStartFlag(base);
        I2C_HAL_ClearInt(base);

        if(i2cSlaveState->slaveCallback != NULL)
        {
            /*Call callback to handle when the driver detect START signal*/
            i2cSlaveState->slaveCallback(instance,
                                         kI2CSlaveStartDetect,
                                         i2cSlaveState->callbackParam);
        }

        return;
    }
#endif

#if FSL_FEATURE_I2C_HAS_START_STOP_DETECT || FSL_FEATURE_I2C_HAS_STOP_DETECT
    /*--------------- Handle STOP ------------------*/
    if (stopIntEnabled && stopDetected)
    {
        I2C_HAL_ClearStopFlag(base);
        I2C_HAL_ClearInt(base);

        if(!i2cSlaveState->slaveListening)
        {
             /** Disable I2C interrupt in the peripheral.*/
            I2C_HAL_SetIntCmd(base, false);
        }

        if(i2cSlaveState->slaveCallback != NULL)
        {
             /*Call callback to handle when the driver detect STOP signal*/
            i2cSlaveState->slaveCallback(instance,
                                         kI2CSlaveStopDetect,
                                         i2cSlaveState->callbackParam);
        }

        if (i2cSlaveState->isRxBlocking)
        {
            OSA_EventSet(&i2cSlaveState->irqEvent, kI2CSlaveStopDetect);
        }

        i2cSlaveState->status = kStatus_I2C_Idle;

        return;
    }
#endif

     /** Clear I2C IRQ.*/
    I2C_HAL_ClearInt(base);

    if (wasArbLost)
    {
        I2C_HAL_ClearArbitrationLost(base);
        if (!addressed)
        {
            i2cSlaveState->status = kStatus_I2C_AribtrationLost;
            if(!i2cSlaveState->slaveListening)
            {
                 /** Disable I2C interrupt in the peripheral.*/
                I2C_HAL_SetIntCmd(base, false);
            }
            return;
        }
    }

    /*--------------- Handle Address ------------------*/
     /** Addressed only happens when receiving address. */
    if (addressed)  /** Slave is addressed. */
    {
         /** Master read from Slave. Slave transmit.*/
        if (I2C_HAL_GetStatusFlag(base, kI2CSlaveTransmit))
        {
             /** Switch to TX mode*/
            I2C_HAL_SetDirMode(base, kI2CSend);

            if(i2cSlaveState->slaveCallback != NULL)
            {
                /*Call callback to handle when the driver get read request*/
                i2cSlaveState->slaveCallback(instance,
                                             kI2CSlaveTxReq,
                                             i2cSlaveState->callbackParam);
            }

            doTransmit = true;
        }
        else  /** Master write to Slave. Slave receive.*/
        {
             /** Switch to RX mode.*/
            I2C_HAL_SetDirMode(base, kI2CReceive);

            if(i2cSlaveState->slaveCallback != NULL)
            {
                /*Call callback to handle when the driver get write request*/
                i2cSlaveState->slaveCallback(instance,
                                             kI2CSlaveRxReq,
                                             i2cSlaveState->callbackParam);
            }

             /** Read dummy character.*/
            I2C_HAL_ReadByte(base);
        }
    }
    /*--------------- Handle Transfer ------------------*/
    else
    {
         /** Handle transmit */
        if (direction == kI2CSend)
        {
            if (I2C_HAL_GetStatusFlag(base, kI2CReceivedNak))
            {
                 /** Switch to RX mode.*/
                I2C_HAL_SetDirMode(base, kI2CReceive);
                 /** Read dummy character to release bus */
                I2C_HAL_ReadByte(base);

                if ((!i2cSlaveState->slaveListening) && (!stopIntEnabled))
                {
                     /** Disable I2C interrupt in the peripheral.*/
                    I2C_HAL_SetIntCmd(base, false);
                }

                if(i2cSlaveState->slaveCallback != NULL)
                {
                      /** Receive TX NAK, mean transaction is finished, call callback to handle */
                    i2cSlaveState->slaveCallback(instance,
                                                 kI2CSlaveTxNAK,
                                                 i2cSlaveState->callbackParam);
                }

                if (i2cSlaveState->isTxBlocking)
                {
                    OSA_EventSet(&i2cSlaveState->irqEvent, kI2CSlaveTxNAK);
                }

                i2cSlaveState->txSize = 0;
                i2cSlaveState->txBuff = NULL;
                i2cSlaveState->isTxBusy = false;
            }
            else  /** ACK from receiver.*/
            {
                doTransmit = true;
            }
        }
         /** Handle receive */
        else
        {
             /** Get byte from data register */
            i2cData = I2C_HAL_ReadByte(base);

            if (i2cSlaveState->rxSize)
            {
                *(i2cSlaveState->rxBuff) = i2cData;
                ++ i2cSlaveState->rxBuff;
                -- i2cSlaveState->rxSize;

                if (!i2cSlaveState->rxSize)
                {
                    if (!stopIntEnabled)
                    {
                        if(!i2cSlaveState->slaveListening)
                        {
                             /** Disable I2C interrupt in the peripheral.*/
                            I2C_HAL_SetIntCmd(base, false);
                        }

                         /** All bytes are received, so we're done with this transfer */
                        if (i2cSlaveState->isRxBlocking)
                        {
                            OSA_EventSet(&i2cSlaveState->irqEvent, kI2CSlaveRxFull);
                        }
                    }

                    i2cSlaveState->isRxBusy = false;
                    i2cSlaveState->rxBuff = NULL;

                    if(i2cSlaveState->slaveCallback != NULL)
                    {
                         /** Rx buffer is full, call callback to handle */
                        i2cSlaveState->slaveCallback(instance,
                                                     kI2CSlaveRxFull,
                                                     i2cSlaveState->callbackParam);
                    }
                }
            }
            else
            {
                 /** The Rxbuff is full --> Set kStatus_I2C_SlaveRxOverrun*/
                i2cSlaveState->status = kStatus_I2C_SlaveRxOverrun;
            }
        }
    }

     /** DO TRANSMIT*/
    if (doTransmit)
    {
         /** Send byte to data register */
        if (i2cSlaveState->txSize)
        {
            i2cData = *(i2cSlaveState->txBuff);
            I2C_HAL_WriteByte(base, i2cData);
            ++ i2cSlaveState->txBuff;
            -- i2cSlaveState->txSize;
            if (!i2cSlaveState->txSize)
            {
                 /** All bytes are received, so we're done with this transfer */
                i2cSlaveState->txBuff = NULL;
                i2cSlaveState->isTxBusy = false;

                if(i2cSlaveState->slaveCallback != NULL)
                {
                     /** Tx buffer is empty, finish transaction, call callback to handle */
                    i2cSlaveState->slaveCallback(instance,
                                                 kI2CSlaveTxEmpty,
                                                 i2cSlaveState->callbackParam);
                }

            }
        }
        else
        {
             /** The Txbuff is empty --> set kStatus_I2C_SlaveTxUnderrun*/
            i2cSlaveState->status = kStatus_I2C_SlaveTxUnderrun ;
        }
    }
}
Пример #13
0
/*FUNCTION**********************************************************************
 *
 * Function Name : I2C_DRV_SlaveReceiveDataBlocking
 * Description   : Receive the data using a blocking method.
 * This function set buffer pointer and length to Rx buffer &Rx Size. Then wait
 * until the transmission is end (all data are received or STOP signal is
 * detected)
 *
 *END*/
i2c_status_t I2C_DRV_SlaveReceiveDataBlocking(uint32_t instance,
                                              uint8_t * rxBuff,
                                              uint32_t rxSize,
                                              uint32_t timeout_ms)
{
    assert(rxBuff);
    assert(instance < I2C_INSTANCE_COUNT);

    i2c_slave_state_t * i2cSlaveState = (i2c_slave_state_t *)g_i2cStatePtr[instance];

    if(!i2cSlaveState->slaveListening)
    {
        event_flags_t i2cIrqSetFlags;
        osa_status_t syncStatus;

        if (i2cSlaveState->isRxBusy)
        {
            return kStatus_I2C_Busy;
        }

        i2cSlaveState->rxBuff = rxBuff;
        i2cSlaveState->rxSize = rxSize;
        i2cSlaveState->isRxBusy = true;
        i2cSlaveState->isRxBlocking = true;

         /** If IAAS event already comes, read dummy to release the bus.*/
        if(I2C_HAL_GetStatusFlag(g_i2cBase[instance], kI2CAddressAsSlave))
        {
             /** Switch to RX mode.*/
            I2C_HAL_SetDirMode(g_i2cBase[instance], kI2CReceive);
            I2C_HAL_ReadByte(g_i2cBase[instance]);
        }

        I2C_HAL_SetIntCmd(g_i2cBase[instance], true);

         /** Wait until the transmit is complete. */
        do
        {
            syncStatus = OSA_EventWait(&i2cSlaveState->irqEvent,
                                       #if (FSL_FEATURE_I2C_HAS_START_STOP_DETECT || FSL_FEATURE_I2C_HAS_STOP_DETECT)
                                       kI2CSlaveStopDetect |
                                       #endif
                                       kI2CSlaveRxFull | kI2CSlaveAbort,
                                       false,
                                       timeout_ms,
                                       &i2cIrqSetFlags);
        } while(syncStatus == kStatus_OSA_Idle);

        if (syncStatus != kStatus_OSA_Success)
        {
            I2C_HAL_SetIntCmd(g_i2cBase[instance], false);
            i2cSlaveState->status = kStatus_I2C_Timeout;
        }

        i2cSlaveState->isRxBlocking = false;

        return i2cSlaveState->status;
    }
    else  /** i2cSlaveState->slaveListening */
    {
        return kStatus_I2C_Fail;
    }
}