コード例 #1
0
//
//	Originally, 'endTransmission' was an f(void) function.
//	It has been modified to take one parameter indicating
//	whether or not a STOP should be performed on the bus.
//	Calling endTransmission(false) allows a sketch to
//	perform a repeated start.
//
//	WARNING: Nothing in the library keeps track of whether
//	the bus tenure has been properly ended with a STOP. It
//	is very possible to leave the bus in a hung state if
//	no call to endTransmission(true) is made. Some I2C
//	devices will behave oddly if they do not see a STOP.
//
uint8_t TwoWire::endTransmission(uint8_t sendStop)
{
    /* Set direction to send for sending of address and data. */
    uint8_t result = (uint8_t)getWriteError();
    if(result != 0)
    {
        // reset tx buffer iterator vars
        txBufferIndex = 0;
        txBufferLength = 0;
        // indicate that we are done transmitting
        transmitting_master = false;
        return 1;
    }

    uint32_t t0 = millis();

    while(I2C_HAL_GetStatusFlag(instance, kI2CBusBusy) && !I2C_HAL_IsMaster(instance))
    {
        if(millis() - t0 >= 25)
            return 4; //timeout
    }

    uint16_t slaveAddress;
    slaveAddress = (txAddress << 1U) & 0x00FFU;
    bool sent = sendAddress(slaveAddress);
    //tx buffer also sent by interrupt

    // reset tx buffer iterator vars
    txBufferIndex = 0;
    txBufferLength = 0;
    // indicate that we are done transmitting
    transmitting_master = false;
    clearWriteError();

    result = 4;

    if(sent) //sent without timeout
    {
        if(master_state == MASTER_STATE_COMPLETE)
        {
            result = 0;
        }
        else if(master_state == MASTER_STATE_TX_NAK) //failed
        {
            result = (txBufferIndex == 0) ? 2 : 3; //address or data fail
            sendStop = true;
        }

        if(sendStop)
        {
            I2C_HAL_SendStop(instance);
        }
    }
    I2C_HAL_SetDirMode(instance, kI2CReceive);

    return result;
}
コード例 #2
0
ファイル: i2c_api.c プロジェクト: 1deus/tmk_keyboard
int i2c_stop(i2c_t *obj) {
    volatile uint32_t n = 0;
    uint32_t i2c_addrs[] = I2C_BASE_ADDRS;
    if (I2C_HAL_IsMaster(i2c_addrs[obj->instance]))
        I2C_HAL_SendStop(i2c_addrs[obj->instance]);
    
    // It seems that there are timing problems
    // when there is no waiting time after a STOP.
    // This wait is also included on the samples
    // code provided with the freedom board
    for (n = 0; n < 200; n++) __NOP();
    return 0;
}
コード例 #3
0
/*!
 * @brief Pass IRQ control to either the master or slave driver.
 *
 * The address of the IRQ handlers are checked to make sure they are non-zero before
 * they are called. If the IRQ handler's address is zero, it means that driver was
 * not present in the link (because the IRQ handlers are marked as weak). This would
 * actually be a program error, because it means the master/slave config for the IRQ
 * was set incorrectly.
 *
 * @param instance   Instance number of the I2C module.
 */
void I2C_DRV_IRQHandler(uint32_t instance)
{
    assert(instance < I2C_INSTANCE_COUNT);
    I2C_Type * base = g_i2cBase[instance];

    if (I2C_HAL_IsMaster(base))
    {
         /** Master mode.*/
        I2C_DRV_MasterIRQHandler(instance);
    }
    else
    {
         /** Slave mode.*/
        I2C_DRV_SlaveIRQHandler(instance);
    }
}
コード例 #4
0
/*!
 * @brief Pass IRQ control to either the master or slave driver.
 *
 * The address of the IRQ handlers are checked to make sure they are non-zero before
 * they are called. If the IRQ handler's address is zero, it means that driver was
 * not present in the link (because the IRQ handlers are marked as weak). This would
 * actually be a program error, because it means the master/slave config for the IRQ
 * was set incorrectly.
 *
 * @param instance   Instance number of the I2C module.
 */
void I2C_DRV_IRQHandler(uint32_t instance)
{
    assert(instance < I2C_INSTANCE_COUNT);
    I2C_Type * base = g_i2cBase[instance];
    if(I2C_HAL_GetStatusFlag(base, kI2CArbitrationLost))
    {
        /* Master mode.*/
        I2C_DRV_MasterIRQHandler(instance);
    }
	else
	{
	    if (I2C_HAL_IsMaster(base))
	    {
	        /* Master mode.*/
	        I2C_DRV_MasterIRQHandler(instance);
	    }
	    else
	    {
	        /* Slave mode.*/
	        I2C_DRV_SlaveIRQHandler(instance);
	    }
	}
}
コード例 #5
0
void TwoWire::onService(void)
{
    //interrupt handler
    uint8_t  i2cData  = 0x00;
    bool     wasArbLost = I2C_HAL_GetStatusFlag(instance, kI2CArbitrationLost);
    bool     addressed = I2C_HAL_GetStatusFlag(instance, kI2CAddressAsSlave);
    bool     stopIntEnabled = false;

    bool     startDetected = I2C_HAL_GetStartFlag(instance);
    bool     startIntEnabled = I2C_HAL_GetStartStopIntCmd(instance);
    bool     stopDetected = I2C_HAL_GetStopFlag(instance);
    stopIntEnabled = startIntEnabled;

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

    /*--------------- Handle START, STOP or REPEAT START ------------------*/
    if (stopIntEnabled && (startDetected || stopDetected))
    {
        if(startDetected)
            I2C_HAL_ClearStartFlag(instance);
        if(stopDetected)
            I2C_HAL_ClearStopFlag(instance);
        I2C_HAL_ClearInt(instance);
        if(slaveBufferLength)
        {
            if(onReceiveCallback)
            {
                receiving_slave = true;
                onReceiveCallback(slaveBufferLength);
                receiving_slave = false;
            }
            slaveBufferIndex = 0;
            slaveBufferLength = 0;
        }
        return;
    }

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

    if (wasArbLost)
    {
        I2C_HAL_ClearArbitrationLost(instance);
        if (!addressed)
        {
            master_state = MASTER_STATE_ARB_LOST;
            return;
        }
    }

    if(I2C_HAL_IsMaster(instance))
    {
        if (direction == kI2CSend)
        {
            //check for NAK
            /* Check whether we got an ACK or NAK from the former byte we sent */
            if (I2C_HAL_GetStatusFlag(instance, kI2CReceivedNak))
            {
                master_state = MASTER_STATE_TX_NAK;
            }
            else if(transmitting_master)
            {
                /* Continue send if still have data. TxSize/txBuff index need
                 * increment first because one byte is already sent in order
                 * to trigger interrupt */
                 if (txBufferIndex < txBufferLength)
                 {
                     /* Transmit next byte and update buffer index */
                     I2C_HAL_WriteByte(instance, txBuffer[txBufferIndex++]);
                 }
                 else
                 {
                     /* Finish send data, send STOP, disable interrupt */
                     master_state = MASTER_STATE_COMPLETE;
                 }
             }
             else
             {
                 master_state = MASTER_STATE_READ_READY; //address sent for a read
             }
        }
        else
        {
            switch (--rxBufferQuantity)
            {
                case 0x0U:
                    /* Finish receive data, send STOP, disable interrupt */
                    master_state = MASTER_STATE_COMPLETE;
                    if(master_send_stop)
                        I2C_HAL_SendStop(instance);
                    else
                        I2C_HAL_SendStart(instance);
                    break;
                case 0x1U:
                    /* For the byte before last, we need to set NAK */
                    I2C_HAL_SendNak(instance);
                    break;
                default :
                    I2C_HAL_SendAck(instance);
                    break;
            }

            rxBuffer[rxBufferLength++] = I2C_HAL_ReadByte(instance);
        }
        return;
    }

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

            transmitting_slave = true;
            slaveBufferIndex = 0;
            slaveBufferLength = 0;

            if (onRequestCallback)
                onRequestCallback(); //this needs to load the transmit buffer
            else
                // create a default 1-byte response
                write((uint8_t) 0);

        }
        else /* Master write to Slave. Slave receive.*/
        {
            /* Switch to RX mode.*/
            I2C_HAL_SetDirMode(instance, kI2CReceive);
            I2C_HAL_SendAck(instance);

            /* Read dummy character.*/
            I2C_HAL_ReadByte(instance);

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

                transmitting_slave = false;
                slaveBufferIndex = 0;
                slaveBufferLength = 0;
            }
            else /* ACK from receiver.*/
            {
                transmitting_slave = true;
            }
        }
        /* Handle receive */
        else
        {
            /* Get byte from data register */
            I2C_HAL_SendAck(instance);
            i2cData = I2C_HAL_ReadByte(instance);
            if(slaveBufferLength < BUFFER_LENGTH)
                slaveBuffer[slaveBufferLength++] = i2cData;
        }
    }

    if (transmitting_slave)
    {
        /* Send byte to data register */
        if (slaveBufferIndex < slaveBufferLength)
        {
            I2C_HAL_WriteByte(instance, slaveBuffer[slaveBufferIndex++]);
            if (slaveBufferIndex >= slaveBufferLength)
            {
                slaveBufferIndex = 0;
                slaveBufferLength = 0;
                transmitting_slave = false;
            }
        }
        else
            transmitting_slave = false;
    }
}
コード例 #6
0
uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
{
    if(quantity == 0) return 0;

    uint32_t t0 = millis();

    while(I2C_HAL_GetStatusFlag(instance, kI2CBusBusy) && !I2C_HAL_IsMaster(instance))
    {
        if(millis() - t0 >= 25)
            return 4; //timeout
    }

    if(quantity > BUFFER_LENGTH){
        quantity = BUFFER_LENGTH;
    }

    rxBufferQuantity = quantity;
    rxBufferIndex = 0;
    rxBufferLength = 0;

    uint16_t slaveAddr = (address << 1U) | 1;

    if(!sendAddress(slaveAddr) || master_state != MASTER_STATE_READ_READY)
    {
        I2C_HAL_SendStop(instance);
        I2C_HAL_SetDirMode(instance, kI2CReceive);
        return 0;
    }

    master_send_stop = sendStop;

    master_state = MASTER_STATE_IDLE;

    I2C_HAL_SetDirMode(instance, kI2CReceive);

    /* Send NAK if only one byte to read. */
    if (rxBufferQuantity == 0x1U)
    {
        I2C_HAL_SendNak(instance);
    }
    else
    {
        I2C_HAL_SendAck(instance);
    }

    I2C_HAL_ReadByte(instance);

    t0 = millis();

    while(master_state == MASTER_STATE_IDLE)
    {
        if(millis() - t0 >= 25)
        {
            rxBufferIndex = 0;
            rxBufferLength = 0;
            I2C_HAL_SendStop(instance);
            I2C_HAL_SetDirMode(instance, kI2CReceive);
            return 0; //timeout
        }
    }

    if(master_state == MASTER_STATE_COMPLETE)
    {
        rxBufferIndex = 0;
        return rxBufferLength;
    }
    else
    {
        rxBufferIndex = 0;
        rxBufferLength = 0;
        rxBufferQuantity = 0;
        I2C_HAL_SendStop(instance);
        I2C_HAL_SetDirMode(instance, kI2CReceive);
        return 0; //timeout
    }
}