예제 #1
0
int i2c_stop(i2c_t *obj)
{
    obj->start_pending = 0;
    write_tx_fifo(obj, MXC_S_I2CM_TRANS_TAG_STOP);

    return wait_tx_in_progress(obj);
}
예제 #2
0
파일: i2c_api.c 프로젝트: Archcady/mbed-os
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
{
    int err, retval = 0;
    int i;

    if (!(obj->stop_pending) && (obj->i2c->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
        return 0;
    }

    // clear all interrupts
    obj->i2c->intfl = 0x3FF;

    // write the address to the fifo
    if ((err = write_tx_fifo(obj, (MXC_S_I2CM_TRANS_TAG_START | address))) != 0) { // start + addr (write)
        i2c_reset(obj);
        return err;
    }
    obj->start_pending = 0;

    // start the transaction
    obj->i2c->trans |= MXC_F_I2CM_TRANS_TX_START;

    // load as much of the cmd into the FIFO as possible
    for (i = 0; i < length; i++) {
        if ((err = write_tx_fifo(obj, (MXC_S_I2CM_TRANS_TAG_TXDATA_ACK | data[i]))) != 0) { // cmd (expect ACK)
            retval = (retval ? retval : err);
            break;
        }
    }

    if (stop) {
        obj->stop_pending = 0;
        if ((err = write_tx_fifo(obj, MXC_S_I2CM_TRANS_TAG_STOP)) != 0) { // stop condition
            retval = (retval ? retval : err);
        }

        if ((err = wait_tx_in_progress(obj)) != 0) {
            retval = (retval ? retval : err);
        }
    } else {
        obj->stop_pending = 1;
        int timeout = MXC_I2CM_TX_TIMEOUT;
        // Wait for TX fifo to be empty
        while (!(obj->i2c->intfl & MXC_F_I2CM_INTFL_TX_FIFO_EMPTY) && timeout--);
    }

    if (retval == 0) {
        return length;
    }

    i2c_reset(obj);

    return retval;
}
예제 #3
0
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
{
    int err, retval = 0;
    int i = length;
    int timeout;

    if (!(obj->stop_pending) && (obj->i2c->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
        return 0;
    }

    // clear all interrupts
    obj->i2c->intfl = 0x3FF;

    // start + addr (read)
    if ((retval = write_tx_fifo(obj, (MXC_S_I2CM_TRANS_TAG_START | address | I2C_SLAVE_ADDR_READ_BIT))) != 0) {
        goto read_done;
    }
    obj->start_pending = 0;

    while (i > 256) {
        if ((retval = write_tx_fifo(obj, (MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT | 255))) != 0) {
            goto read_done;
        }
        i -= 256;
    }

    if (i > 1) {
        if ((retval = write_tx_fifo(obj, (MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT | (i - 2)))) != 0) {
            goto read_done;
        }
    }

    // start the transaction
    obj->i2c->trans |= MXC_F_I2CM_TRANS_TX_START;

    if ((retval = write_tx_fifo(obj, MXC_S_I2CM_TRANS_TAG_RXDATA_NACK)) != 0) { // NACK last data byte
        goto read_done;
    }

    if (stop) {
        if ((retval = write_tx_fifo(obj, MXC_S_I2CM_TRANS_TAG_STOP)) != 0) { // stop condition
            goto read_done;
        }
    }

    timeout = MXC_I2CM_RX_TIMEOUT;
    i = 0;
    while (i < length) {
        while (!(obj->i2c->intfl & MXC_F_I2CM_INTFL_RX_FIFO_NOT_EMPTY) &&
                (!(obj->i2c->bb & MXC_F_I2CM_BB_RX_FIFO_CNT))) {
            if ((--timeout < 0) || !(obj->i2c->trans & MXC_F_I2CM_TRANS_TX_IN_PROGRESS)) {
                retval = -3;
                goto read_done;
            }
        }

        timeout = MXC_I2CM_RX_TIMEOUT;

        obj->i2c->intfl = MXC_F_I2CM_INTFL_RX_FIFO_NOT_EMPTY;

        uint16_t temp = *obj->rxfifo;

        if (temp & MXC_S_I2CM_RSTLS_TAG_EMPTY) {
            continue;
        }
        data[i++] = (uint8_t) temp;
    }

read_done:

    if (stop) {
        obj->stop_pending = 0;
        if ((err = wait_tx_in_progress(obj)) != 0) {
            retval = (retval ? retval : err);
        }
    } else {
        obj->stop_pending = 1;
    }

    if (retval == 0) {
        return length;
    }

    return retval;
}