예제 #1
0
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);
    }
}
예제 #2
0
파일: i2c_api.c 프로젝트: AlessandroA/mbed
int i2c_stop(i2c_t *obj) {
    if (I2C_MasterStop(i2c_addrs[obj->instance]) != kStatus_Success) {
        obj->next_repeated_start = 0;
        return 1;
    }

    return 0;
}
예제 #3
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;
        }
    }
}
예제 #4
0
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;
}
예제 #5
0
/*!
 * @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)
    {
    }
}
예제 #6
0
파일: fsl_i2c_dma.c 프로젝트: 01org/zephyr
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;
}