static int i2c_do_read(i2c_t *obj, char * data, int last) { uint32_t i2c_addrs[] = I2C_BASE_ADDRS; if (last) { I2C_HAL_SendNak(i2c_addrs[obj->instance]); } else { I2C_HAL_SendAck(i2c_addrs[obj->instance]); } *data = (I2C_HAL_ReadByte(i2c_addrs[obj->instance]) & 0xFF); // start rx transfer and wait the end of the transfer return i2c_wait_end_rx_transfer(obj); }
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_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; }