static void I2C_MasterTransferCallbackEDMA(edma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds) { i2c_master_edma_private_handle_t *i2cPrivateHandle = (i2c_master_edma_private_handle_t *)userData; status_t result = kStatus_Success; /* Disable DMA. */ I2C_EnableDMA(i2cPrivateHandle->base, false); /* Send stop if kI2C_TransferNoStop flag is not asserted. */ if (!(i2cPrivateHandle->handle->transfer.flags & kI2C_TransferNoStopFlag)) { if (i2cPrivateHandle->handle->transfer.direction == kI2C_Read) { /* Change to send NAK at the last byte. */ i2cPrivateHandle->base->C1 |= I2C_C1_TXAK_MASK; /* Wait the last data to be received. */ while (!(i2cPrivateHandle->base->S & kI2C_TransferCompleteFlag)) { } /* Send stop signal. */ result = I2C_MasterStop(i2cPrivateHandle->base); /* Read the last data byte. */ *(i2cPrivateHandle->handle->transfer.data + i2cPrivateHandle->handle->transfer.dataSize - 1) = i2cPrivateHandle->base->D; } else { /* Wait the last data to be sent. */ while (!(i2cPrivateHandle->base->S & kI2C_TransferCompleteFlag)) { } /* Send stop signal. */ result = I2C_MasterStop(i2cPrivateHandle->base); } } i2cPrivateHandle->handle->state = kIdleState; if (i2cPrivateHandle->handle->completionCallback) { i2cPrivateHandle->handle->completionCallback(i2cPrivateHandle->base, i2cPrivateHandle->handle, result, i2cPrivateHandle->handle->userData); } }
int i2c_stop(i2c_t *obj) { if (I2C_MasterStop(i2c_addrs[obj->instance]) != kStatus_Success) { obj->next_repeated_start = 0; return 1; } return 0; }
void I2C_MASTER_IRQHandler(void) { /* Clear pending flag. */ EXAMPLE_I2C_MASTER_BASEADDR->S = kI2C_IntPendingFlag; if (g_masterReadBegin) { /* Change direction to read direction and automatically send ACK. */ EXAMPLE_I2C_MASTER_BASEADDR->C1 &= ~(I2C_C1_TX_MASK | I2C_C1_TXAK_MASK); /* Read dummy to free the bus. */ EXAMPLE_I2C_MASTER_BASEADDR->D; g_masterReadBegin = false; return; } /* If tx Index < I2C_DATA_LENGTH, master send->slave receive transfer is ongoing. */ if (g_masterTxIndex < I2C_DATA_LENGTH) { EXAMPLE_I2C_MASTER_BASEADDR->D = g_master_buff[g_masterTxIndex]; g_masterTxIndex++; } /* If rx Index < I2C_DATA_LENGTH, master receive->slave send transfer is ongoing. */ if (g_masterRxIndex < I2C_DATA_LENGTH) { /* Send STOP after receiving the last byte. */ if (g_masterRxIndex == (I2C_DATA_LENGTH - 1U)) { I2C_MasterStop(EXAMPLE_I2C_MASTER_BASEADDR); } g_master_buff[g_masterRxIndex] = EXAMPLE_I2C_MASTER_BASEADDR->D; g_masterRxIndex++; /* Send NAK at the last byte. */ if (g_masterRxIndex == (I2C_DATA_LENGTH - 1U)) { EXAMPLE_I2C_MASTER_BASEADDR->C1 |= I2C_C1_TXAK_MASK; } } }
status_t I2C_MasterTransferEDMA(I2C_Type *base, i2c_master_edma_handle_t *handle, i2c_master_transfer_t *xfer) { assert(handle); assert(xfer); status_t result; uint8_t tmpReg; volatile uint8_t dummy = 0; /* Add this to avoid build warning. */ dummy++; /* Disable dma xfer. */ I2C_EnableDMA(base, false); /* Send address and command buffer(if there is), until senddata phase or receive data phase. */ result = I2C_InitTransferStateMachineEDMA(base, handle, xfer); if (result) { /* Send stop if received Nak. */ if (result == kStatus_I2C_Nak) { if (I2C_MasterStop(base) != kStatus_Success) { result = kStatus_I2C_Timeout; } } /* Reset the state to idle state. */ handle->state = kIdleState; return result; } /* Configure dma transfer. */ /* For i2c send, need to send 1 byte first to trigger the dma, for i2c read, need to send stop before reading the last byte, so the dma transfer size should be (xSize - 1). */ if (handle->transfer.dataSize > 1) { I2C_MasterTransferEDMAConfig(base, handle); if (handle->transfer.direction == kI2C_Read) { /* Change direction for receive. */ base->C1 &= ~I2C_C1_TX_MASK; /* Read dummy to release the bus. */ dummy = base->D; /* Enabe dma transfer. */ I2C_EnableDMA(base, true); } else { /* Enabe dma transfer. */ I2C_EnableDMA(base, true); /* Send the first data. */ base->D = *handle->transfer.data; } } else /* If transfer size is 1, use polling method. */ { if (handle->transfer.direction == kI2C_Read) { tmpReg = base->C1; /* Change direction to Rx. */ tmpReg &= ~I2C_C1_TX_MASK; /* Configure send NAK */ tmpReg |= I2C_C1_TXAK_MASK; base->C1 = tmpReg; /* Read dummy to release the bus. */ dummy = base->D; } else { base->D = *handle->transfer.data; } /* Wait until data transfer complete. */ while (!(base->S & kI2C_IntPendingFlag)) { } /* Clear pending flag. */ base->S = kI2C_IntPendingFlag; /* Send stop if kI2C_TransferNoStop flag is not asserted. */ if (!(handle->transfer.flags & kI2C_TransferNoStopFlag)) { result = I2C_MasterStop(base); } /* Read the last byte of data. */ if (handle->transfer.direction == kI2C_Read) { *handle->transfer.data = base->D; } /* Reset the state to idle. */ handle->state = kIdleState; } return result; }
/*! * @brief Main function */ int main(void) { i2c_slave_config_t slaveConfig; i2c_master_config_t masterConfig; uint32_t sourceClock; BOARD_InitPins(); BOARD_BootClockRUN(); BOARD_InitDebugConsole(); PRINTF("\r\nI2C example -- MasterFunctionalInterrupt_SlaveFunctionalInterrupt.\r\n"); /* Enable master and slave NVIC interrupt. */ EnableIRQ(I2C_MASTER_IRQ); EnableIRQ(I2C_SLAVE_IRQ); /* Set i2c slave interrupt priority higher. */ NVIC_SetPriority(I2C_SLAVE_IRQ, 0); NVIC_SetPriority(I2C_MASTER_IRQ, 1); /*1.Set up i2c slave first*/ /* * slaveConfig.addressingMode = kI2C_Address7bit; * slaveConfig.enableGeneralCall = false; * slaveConfig.enableWakeUp = false; * slaveConfig.enableHighDrive = false; * slaveConfig.enableBaudRateCtl = false; * slaveConfig.enableSlave = true; */ I2C_SlaveGetDefaultConfig(&slaveConfig); slaveConfig.addressingMode = kI2C_Address7bit; slaveConfig.slaveAddress = I2C_MASTER_SLAVE_ADDR_7BIT; I2C_SlaveInit(EXAMPLE_I2C_SLAVE_BASEADDR, &slaveConfig); for (uint32_t i = 0U; i < I2C_DATA_LENGTH; i++) { g_slave_buff[i] = 0; } /*2.Set up i2c master to send data to slave*/ for (uint32_t i = 0U; i < I2C_DATA_LENGTH; i++) { g_master_buff[i] = i; } PRINTF("Master will send data :"); for (uint32_t i = 0U; i < I2C_DATA_LENGTH; i++) { if (i % 8 == 0) { PRINTF("\r\n"); } PRINTF("0x%2x ", g_master_buff[i]); } PRINTF("\r\n\r\n"); /* * masterConfig.baudRate_Bps = 100000U; * masterConfig.enableHighDrive = false; * masterConfig.enableStopHold = false; * masterConfig.glitchFilterWidth = 0U; * masterConfig.enableMaster = true; */ I2C_MasterGetDefaultConfig(&masterConfig); masterConfig.baudRate_Bps = I2C_BAUDRATE; sourceClock = CLOCK_GetFreq(I2C_MASTER_CLK_SRC); I2C_MasterInit(EXAMPLE_I2C_MASTER_BASEADDR, &masterConfig, sourceClock); /* Master send address to slave. */ I2C_MasterStart(EXAMPLE_I2C_MASTER_BASEADDR, I2C_MASTER_SLAVE_ADDR_7BIT, kI2C_Write); /* Enable module interrupt. */ I2C_EnableInterrupts(EXAMPLE_I2C_MASTER_BASEADDR, kI2C_GlobalInterruptEnable); I2C_EnableInterrupts(EXAMPLE_I2C_SLAVE_BASEADDR, kI2C_GlobalInterruptEnable); /* Wait slave receive finished. */ while (g_slaveRxIndex < I2C_DATA_LENGTH) { } /* Disable module interrupt. */ I2C_DisableInterrupts(EXAMPLE_I2C_MASTER_BASEADDR, kI2C_GlobalInterruptEnable); I2C_DisableInterrupts(EXAMPLE_I2C_SLAVE_BASEADDR, kI2C_GlobalInterruptEnable); /* Master send stop command. */ I2C_MasterStop(EXAMPLE_I2C_MASTER_BASEADDR); /*3.Transfer completed. Check the data.*/ for (uint32_t i = 0U; i < I2C_DATA_LENGTH; i++) { if (g_slave_buff[i] != g_master_buff[i]) { PRINTF("\r\nError occured in this transfer ! \r\n"); break; } } PRINTF("Slave received data :"); for (uint32_t i = 0U; i < I2C_DATA_LENGTH; i++) { if (i % 8 == 0) { PRINTF("\r\n"); } PRINTF("0x%2x ", g_slave_buff[i]); } PRINTF("\r\n\r\n"); /*4.Set up slave ready to send data to master.*/ for (uint32_t i = 0U; i < I2C_DATA_LENGTH; i++) { g_slave_buff[i] = ~g_slave_buff[i]; } PRINTF("This time , slave will send data: :"); for (uint32_t i = 0U; i < I2C_DATA_LENGTH; i++) { if (i % 8 == 0) { PRINTF("\r\n"); } PRINTF("0x%2x ", g_slave_buff[i]); } PRINTF("\r\n\r\n"); /* Already setup the slave transfer ready in item 1. */ /* 5.Set up master to receive data from slave. */ for (uint32_t i = 0U; i < I2C_DATA_LENGTH; i++) { g_master_buff[i] = 0; } /* Master send address to slave. */ I2C_MasterStart(EXAMPLE_I2C_MASTER_BASEADDR, I2C_MASTER_SLAVE_ADDR_7BIT, kI2C_Read); /* Enable module interrupt. */ I2C_EnableInterrupts(EXAMPLE_I2C_MASTER_BASEADDR, kI2C_GlobalInterruptEnable); I2C_EnableInterrupts(EXAMPLE_I2C_SLAVE_BASEADDR, kI2C_GlobalInterruptEnable); g_masterReadBegin = true; /* Master put receive data in receive buffer. */ g_masterRxIndex = 0; /* Wait master receive finished. */ while (g_masterRxIndex < I2C_DATA_LENGTH) { } /* Disable module interrupt. */ I2C_DisableInterrupts(EXAMPLE_I2C_MASTER_BASEADDR, kI2C_GlobalInterruptEnable); I2C_DisableInterrupts(EXAMPLE_I2C_SLAVE_BASEADDR, kI2C_GlobalInterruptEnable); /*6.Transfer completed. Check the data.*/ for (uint32_t i = 0U; i < I2C_DATA_LENGTH; i++) { if (g_slave_buff[i] != g_master_buff[i]) { PRINTF("\r\nError occured in the transfer ! \r\n"); break; } } PRINTF("Master received data :"); for (uint32_t i = 0U; i < I2C_DATA_LENGTH; i++) { if (i % 8 == 0) { PRINTF("\r\n"); } PRINTF("0x%2x ", g_master_buff[i]); } PRINTF("\r\n\r\n"); PRINTF("\r\nEnd of I2C example .\r\n"); while (1) { } }
static status_t I2C_InitTransferStateMachineDMA(I2C_Type *base, i2c_master_dma_handle_t *handle, i2c_master_transfer_t *xfer) { assert(handle); assert(xfer); /* Set up transfer first. */ i2c_direction_t direction = xfer->direction; status_t result = kStatus_Success; if (handle->state != kIdleState) { return kStatus_I2C_Busy; } else { /* Init the handle member. */ handle->transfer = *xfer; /* Save total transfer size. */ handle->transferSize = xfer->dataSize; handle->state = kTransferDataState; /* Clear all status before transfer. */ I2C_MasterClearStatusFlags(base, kClearFlags); /* Change to send write address when it's a read operation with command. */ if ((xfer->subaddressSize > 0) && (xfer->direction == kI2C_Read)) { direction = kI2C_Write; } /* If repeated start is requested, send repeated start. */ if (handle->transfer.flags & kI2C_TransferRepeatedStartFlag) { result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, direction); } else /* For normal transfer, send start. */ { result = I2C_MasterStart(base, handle->transfer.slaveAddress, direction); } if (result) { return result; } while (!(base->S & kI2C_IntPendingFlag)) { } /* Check if there's transfer error. */ result = I2C_CheckAndClearError(base, base->S); /* Return if error. */ if (result) { if (result == kStatus_I2C_Nak) { result = kStatus_I2C_Addr_Nak; if (I2C_MasterStop(base) != kStatus_Success) { result = kStatus_I2C_Timeout; } if (handle->completionCallback) { (handle->completionCallback)(base, handle, result, handle->userData); } } return result; } /* Send subaddress. */ if (handle->transfer.subaddressSize) { do { /* Clear interrupt pending flag. */ base->S = kI2C_IntPendingFlag; handle->transfer.subaddressSize--; base->D = ((handle->transfer.subaddress) >> (8 * handle->transfer.subaddressSize)); /* Wait until data transfer complete. */ while (!(base->S & kI2C_IntPendingFlag)) { } /* Check if there's transfer error. */ result = I2C_CheckAndClearError(base, base->S); if (result) { return result; } } while ((handle->transfer.subaddressSize > 0) && (result == kStatus_Success)); if (handle->transfer.direction == kI2C_Read) { /* Clear pending flag. */ base->S = kI2C_IntPendingFlag; /* Send repeated start and slave address. */ result = I2C_MasterRepeatedStart(base, handle->transfer.slaveAddress, kI2C_Read); if (result) { return result; } /* Wait until data transfer complete. */ while (!(base->S & kI2C_IntPendingFlag)) { } /* Check if there's transfer error. */ result = I2C_CheckAndClearError(base, base->S); if (result) { return result; } } } /* Clear pending flag. */ base->S = kI2C_IntPendingFlag; } return result; }