/*FUNCTION********************************************************************** * * Function Name : I2C_HAL_SlaveSendDataPolling * Description : Send out multiple bytes of data using polling method. * *END*/ i2c_status_t I2C_HAL_SlaveSendDataPolling(I2C_Type * base, const uint8_t* txBuff, uint32_t txSize) { #if FSL_FEATURE_I2C_HAS_START_STOP_DETECT /** Wait until start detected */ while(!I2C_HAL_GetStartFlag(base)) {} I2C_HAL_ClearStartFlag(base); #endif /** Wait until addressed as a slave */ while(!I2C_HAL_GetStatusFlag(base, kI2CAddressAsSlave)) {} /** Wait interrupt flag is set */ while(!I2C_HAL_IsIntPending(base)) {} /** Clear interrupt flag */ I2C_HAL_ClearInt(base); /** Set direction mode */ if (I2C_HAL_GetStatusFlag(base, kI2CSlaveTransmit)) { /** Switch to TX mode*/ I2C_HAL_SetDirMode(base, kI2CSend); } else { /** Switch to RX mode.*/ I2C_HAL_SetDirMode(base, kI2CReceive); /** Read dummy character.*/ I2C_HAL_ReadByte(base); } /** While loop to transmit data */ while(txSize--) { /** Write byte to data register */ I2C_HAL_WriteByte(base, *txBuff++); /** Wait tranfer byte complete */ while(!I2C_HAL_IsIntPending(base)) {} /** Clear interrupt flag */ I2C_HAL_ClearInt(base); /** if NACK received */ if ((I2C_HAL_GetStatusFlag(base, kI2CReceivedNak)) && (txSize != 0)) { return kStatus_I2C_ReceivedNak; } } /** Switch to RX mode.*/ I2C_HAL_SetDirMode(base, kI2CReceive); /** Read dummy character.*/ I2C_HAL_ReadByte(base); return kStatus_I2C_Success; }
int i2c_byte_read(i2c_t *obj, int last) { char data; uint32_t i2c_addrs[] = I2C_BASE_ADDRS; // set rx mode I2C_HAL_SetDirMode(i2c_addrs[obj->instance], kI2CReceive); // Setup read i2c_do_read(obj, &data, last); // set tx mode I2C_HAL_SetDirMode(i2c_addrs[obj->instance], kI2CSend); return I2C_HAL_ReadByte(i2c_addrs[obj->instance]); }
/*FUNCTION********************************************************************** * * Function Name : I2C_HAL_SlaveReceiveDataPolling * Description : Receive multiple bytes of data using polling method. * *END*/ i2c_status_t I2C_HAL_SlaveReceiveDataPolling(I2C_Type * base, uint8_t *rxBuff, uint32_t rxSize) { #if FSL_FEATURE_I2C_HAS_START_STOP_DETECT /** Wait until start detected */ while(!I2C_HAL_GetStartFlag(base)) {} I2C_HAL_ClearStartFlag(base); #endif /** Wait until addressed as a slave */ while(!I2C_HAL_GetStatusFlag(base, kI2CAddressAsSlave)) {} /** Wait interrupt flag is set */ while(!I2C_HAL_IsIntPending(base)) {} /** Clear interrupt flag */ I2C_HAL_ClearInt(base); /** Set direction mode */ if (I2C_HAL_GetStatusFlag(base, kI2CSlaveTransmit)) { /** Switch to TX mode*/ I2C_HAL_SetDirMode(base, kI2CSend); } else { /** Switch to RX mode.*/ I2C_HAL_SetDirMode(base, kI2CReceive); /** Read dummy character.*/ I2C_HAL_ReadByte(base); } /** While loop to receive data */ while(rxSize--) { /** Wait interrupt flag is set */ while(!I2C_HAL_IsIntPending(base)) {} /** Read byte from data register */ *rxBuff++ = I2C_HAL_ReadByte(base); /** Clear interrupt flag */ I2C_HAL_ClearInt(base); } return kStatus_I2C_Success; }
int i2c_slave_read(i2c_t *obj, char *data, int length) { uint8_t dummy_read; uint8_t *ptr; int count; uint32_t i2c_addrs[] = I2C_BASE_ADDRS; // set rx mode I2C_HAL_SetDirMode(i2c_addrs[obj->instance], kI2CSend); // first dummy read dummy_read = I2C_HAL_ReadByte(i2c_addrs[obj->instance]); if (i2c_wait_end_rx_transfer(obj)) return 0; // read address dummy_read = I2C_HAL_ReadByte(i2c_addrs[obj->instance]); if (i2c_wait_end_rx_transfer(obj)) return 0; // read (length - 1) bytes for (count = 0; count < (length - 1); count++) { data[count] = I2C_HAL_ReadByte(i2c_addrs[obj->instance]); if (i2c_wait_end_rx_transfer(obj)) return count; } // read last byte ptr = (length == 0) ? &dummy_read : (uint8_t *)&data[count]; *ptr = I2C_HAL_ReadByte(i2c_addrs[obj->instance]); return (length) ? (count + 1) : 0; }
int i2c_byte_write(i2c_t *obj, int data) { uint32_t i2c_addrs[] = I2C_BASE_ADDRS; // set tx mode I2C_HAL_SetDirMode(i2c_addrs[obj->instance], kI2CSend); return !i2c_do_write(obj, (data & 0xFF)); }
// // 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; }
int i2c_slave_write(i2c_t *obj, const char *data, int length) { int i, count = 0; uint32_t i2c_addrs[] = I2C_BASE_ADDRS; // set tx mode I2C_HAL_SetDirMode(i2c_addrs[obj->instance], kI2CSend); for (i = 0; i < length; i++) { if (i2c_do_write(obj, data[count++]) == 2) return i; } // set rx mode I2C_HAL_SetDirMode(i2c_addrs[obj->instance], kI2CReceive); // dummy rx transfer needed // otherwise the master cannot generate a stop bit I2C_HAL_ReadByte(i2c_addrs[obj->instance]); if (i2c_wait_end_rx_transfer(obj) == 2) return count; return count; }
bool TwoWire::sendAddress(uint16_t slaveAddress) { master_state = MASTER_STATE_IDLE; I2C_HAL_SetDirMode(instance, kI2CSend); if(master_send_stop) I2C_HAL_SendStart(instance); I2C_HAL_WriteByte(instance, slaveAddress); uint32_t t0 = millis(); while(master_state == MASTER_STATE_IDLE || master_state == MASTER_STATE_ARB_LOST) { if(millis() - t0 >= 25 || master_state == MASTER_STATE_ARB_LOST) { I2C_HAL_SendStop(instance); I2C_HAL_SetDirMode(instance, kI2CReceive); return false; //timeout } } return 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; } }
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { int count; char dummy_read, *ptr; if (i2c_start(obj)) { i2c_stop(obj); return I2C_ERROR_BUS_BUSY; } if (i2c_do_write(obj, (address | 0x01))) { i2c_stop(obj); return I2C_ERROR_NO_SLAVE; } // set rx mode uint32_t i2c_addrs[] = I2C_BASE_ADDRS; I2C_HAL_SetDirMode(i2c_addrs[obj->instance], kI2CReceive); // Read in bytes for (count = 0; count < (length); count++) { ptr = (count == 0) ? &dummy_read : &data[count - 1]; uint8_t stop_ = (count == (length - 1)) ? 1 : 0; if (i2c_do_read(obj, ptr, stop_)) { i2c_stop(obj); return count; } } // If not repeated start, send stop. if (stop) i2c_stop(obj); // last read data[count-1] = I2C_HAL_ReadByte(i2c_addrs[obj->instance]); return length; }
/*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 ; } } }
/*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; } }
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; } }
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 } }
/*FUNCTION********************************************************************** * * Function Name : I2C_HAL_MasterSendDataPolling * Description : Performs a polling send transaction on the I2C bus. * *END*/ i2c_status_t I2C_HAL_MasterSendDataPolling(I2C_Type * base, uint16_t slaveAddr, const uint8_t * cmdBuff, uint32_t cmdSize, const uint8_t * txBuff, uint32_t txSize) { uint16_t slaveAddress; slaveAddress = (slaveAddr << 1U) & 0x00FFU; /** Return if current I2C is already set as master. */ if (I2C_BRD_C1_MST(base)) { return kStatus_I2C_Busy; } /** Set direction to send. */ I2C_HAL_SetDirMode(base, kI2CSend); /** Generate START signal. */ I2C_HAL_SendStart(base); /** Send slave address */ if (!I2C_HAL_WriteByteBlocking(base, slaveAddress)) { /** Send STOP if no ACK received */ I2C_HAL_SendStop(base); return kStatus_I2C_ReceivedNak; } /** Send CMD buffer */ if (cmdBuff != NULL) { while (cmdSize--) { if (!I2C_HAL_WriteByteBlocking(base, *cmdBuff--)) { /** Send STOP if no ACK received */ I2C_HAL_SendStop(base); return kStatus_I2C_ReceivedNak; } } } /** Send data buffer */ while (txSize--) { if (!I2C_HAL_WriteByteBlocking(base, *txBuff++)) { /** Send STOP if no ACK received */ I2C_HAL_SendStop(base); return kStatus_I2C_ReceivedNak; } } /** Generate STOP signal. */ I2C_HAL_SendStop(base); /** Set direction back to receive. */ I2C_HAL_SetDirMode(base, kI2CReceive); return kStatus_I2C_Success; }
/*FUNCTION********************************************************************** * * Function Name : I2C_HAL_MasterReceiveDataPolling * Description : Performs a polling receive transaction on the I2C bus. * *END*/ i2c_status_t I2C_HAL_MasterReceiveDataPolling(I2C_Type * base, uint16_t slaveAddr, const uint8_t * cmdBuff, uint32_t cmdSize, uint8_t * rxBuff, uint32_t rxSize) { int32_t i; uint8_t directionBit, address; /** Return if current I2C is already set as master. */ if (I2C_BRD_C1_MST(base)) { return kStatus_I2C_Busy; } /** Get r/w bit according to CMD buffer setting * read is 1, write is 0. */ directionBit = (cmdBuff) ? 0x0U : 0x1U; address = (uint8_t)slaveAddr << 1U; /** Set direction to send */ I2C_HAL_SetDirMode(base, kI2CSend); /** Generate START signal. */ I2C_HAL_SendStart(base); /** Send slave address */ if (!I2C_HAL_WriteByteBlocking(base, address | directionBit)) { /** Send STOP if no ACK received */ I2C_HAL_SendStop(base); return kStatus_I2C_ReceivedNak; } /** Send CMD buffer */ if (cmdBuff != NULL) { while (cmdSize--) { if (!I2C_HAL_WriteByteBlocking(base, *cmdBuff--)) { /** Send STOP if no ACK received */ I2C_HAL_SendStop(base); return kStatus_I2C_ReceivedNak; } } /** Need to generate a repeat start before changing to receive. */ I2C_HAL_SendStart(base); /** Send slave address again */ if (!I2C_HAL_WriteByteBlocking(base, address | 1U)) { /** Send STOP if no ACK received */ I2C_HAL_SendStop(base); return kStatus_I2C_ReceivedNak; } } /** Change direction to receive. */ I2C_HAL_SetDirMode(base, kI2CReceive); /** Send NAK if only one byte to read. */ if (rxSize == 0x1U) { I2C_HAL_SendNak(base); } else { I2C_HAL_SendAck(base); } /** Dummy read to trigger receive of next byte. */ I2C_HAL_ReadByteBlocking(base); /** Receive data */ for(i=rxSize-1; i>=0; i--) { switch (i) { case 0x0U: /** Generate STOP signal. */ I2C_HAL_SendStop(base); break; case 0x1U: /** For the byte before last, we need to set NAK */ I2C_HAL_SendNak(base); break; default : I2C_HAL_SendAck(base); break; } /** Read recently received byte into buffer and update buffer index */ if (i==0) { *rxBuff++ = I2C_HAL_ReadByte(base); } else { *rxBuff++ = I2C_HAL_ReadByteBlocking(base); } } return kStatus_I2C_Success; }