コード例 #1
0
ファイル: i2c_api.c プロジェクト: Babody/mbed
static inline int i2c_do_read(i2c_t *obj, int last) {
    if (last == 2) {
        /* this time is befor last byte read */
        /* Set MR3 WAIT bit is 1 */;
        REG(MR3.UINT32) |= MR3_WAIT;
    } else if (last == 1) {
        i2c_set_MR3_NACK(obj);
    } else {
        i2c_set_MR3_ACK(obj);
    }

    /* return the data */
    return (REG(DRR.UINT32) & 0xFF);
}
コード例 #2
0
ファイル: i2c_api.c プロジェクト: Babody/mbed
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
    int count = 0;
    int status;
    int value;
    volatile uint32_t work_reg = 0;

    if(length <= 0) {
        return 0;
    }
    i2c_set_MR3_ACK(obj);
    /* There is a STOP condition for last processing */
    if (obj->last_stop_flag != 0) {
        status = i2c_start(obj);
        if (status != 0) {
            i2c_set_err_noslave(obj);
            return I2C_ERROR_BUS_BUSY;
        }
    }
    obj->last_stop_flag = stop;
    /*  Send Slave address */
    status = i2c_read_address_write(obj, (address | 0x01));
    if (status != 0) {
        i2c_set_err_noslave(obj);
        return I2C_ERROR_NO_SLAVE;
    }
    /* wait RDRF */
    status = i2c_wait_RDRF(obj);
    /* check ACK/NACK */
    if ((status != 0) || ((REG(SR2.UINT32) & SR2_NACKF) != 0)) {
        /* Slave sends NACK */
        (void)i2c_set_STOP(obj);
        /* dummy read */
        value = REG(DRR.UINT32);
        (void)i2c_wait_STOP(obj);
        i2c_set_SR2_NACKF_STOP(obj);
        obj->last_stop_flag = 1;
        return I2C_ERROR_NO_SLAVE;
    }
    /* Read in all except last byte */
    if (length > 2) {
        /* dummy read */
        value = REG(DRR.UINT32);
        for (count = 0; count < (length - 1); count++) {
            /* wait for it to arrive */
            status = i2c_wait_RDRF(obj);
            if (status != 0) {
                i2c_set_err_noslave(obj);
                return I2C_ERROR_NO_SLAVE;
            }
            /* Recieve the data */
            if (count == (length - 2)) {
                value = i2c_do_read(obj, 1);
            } else if ((length >= 3) && (count == (length - 3))) {
                value = i2c_do_read(obj, 2);
            } else {
                value = i2c_do_read(obj, 0);
            }
            data[count] = (char)value;
        }
    } else if (length == 2) {
        /* Set MR3 WATI bit is 1 */
        REG(MR3.UINT32) |= MR3_WAIT;
        /* dummy read */
        value = REG(DRR.UINT32);
        /* wait for it to arrive */
        status = i2c_wait_RDRF(obj);
        if (status != 0) {
            i2c_set_err_noslave(obj);
            return I2C_ERROR_NO_SLAVE;
        }
        i2c_set_MR3_NACK(obj);
        data[count] = (char)REG(DRR.UINT32);
        count++;
    } else {
        /* length == 1 */
        /* Set MR3 WATI bit is 1 */;
        REG(MR3.UINT32) |=  MR3_WAIT;
        i2c_set_MR3_NACK(obj);
        /* dummy read */
        value = REG(DRR.UINT32);
    }
    /* wait for it to arrive */
    status = i2c_wait_RDRF(obj);
    if (status != 0) {
        i2c_set_err_noslave(obj);
        return I2C_ERROR_NO_SLAVE;
    }

    /* If not repeated start, send stop. */
    if (stop) {
        (void)i2c_set_STOP(obj);
        /* RIICnDRR read */
        value = (REG(DRR.UINT32) & 0xFF);
        data[count] = (char)value;
        /* RIICnMR3.WAIT = 0 */
        REG(MR3.UINT32) &= ~MR3_WAIT;
        (void)i2c_wait_STOP(obj);
        i2c_set_SR2_NACKF_STOP(obj);
    } else {
        (void)i2c_restart(obj);
        /* RIICnDRR read */
        value = (REG(DRR.UINT32) & 0xFF);
        data[count] = (char)value;
        /* RIICnMR3.WAIT = 0 */
        REG(MR3.UINT32) &= ~MR3_WAIT;
        (void)i2c_wait_START(obj);
        /* SR2.START = 0 */
        REG(SR2.UINT32) &= ~SR2_START;
    }

    return length;
}
コード例 #3
0
ファイル: i2c_api.c プロジェクト: AlessandroA/mbed
static void i2c_rx_irq(IRQn_Type irq_num, uint32_t index)
{
    i2c_t *obj = i2c_data[index].async_obj;
    if (obj->rx_buff.pos == SIZE_MAX) {
        if ((REG(SR2.UINT32) & SR2_NACKF) != 0) {
            /* Slave sends NACK */
            (void)i2c_set_STOP(obj);
            /* dummy read */
            if (REG(DRR.UINT32)) {}
            (void)i2c_wait_STOP(obj);
            i2c_set_SR2_NACKF_STOP(obj);
            obj->i2c.last_stop_flag = 1;
            
            i2c_data[index].event = I2C_EVENT_ERROR | I2C_EVENT_TRANSFER_EARLY_NACK;
            i2c_abort_asynch(obj);
            ((void (*)())i2c_data[index].async_callback)();
            return;
        }
        if (obj->rx_buff.length == 1) {
            /* length == 1 */
            /* Set MR3 WAIT bit is 1 */;
            REG(MR3.UINT32) |=  MR3_WAIT;
            i2c_set_MR3_NACK(obj);
        } else if (obj->rx_buff.length == 2) {
            /* Set MR3 WAIT bit is 1 */
            REG(MR3.UINT32) |= MR3_WAIT;
        }
        /* dummy read */
        if (REG(DRR.UINT32)) {}
        obj->rx_buff.pos = 0;
        return;
    }
    if ((REG(SR2.UINT32) & SR2_NACKF) != 0) {
        /* Slave sends NACK */
        i2c_set_err_noslave(obj);
        i2c_data[index].event = I2C_EVENT_ERROR | I2C_EVENT_TRANSFER_EARLY_NACK;
        i2c_abort_asynch(obj);
        ((void (*)())i2c_data[index].async_callback)();
        return;
    } else {
        switch (obj->rx_buff.length - obj->rx_buff.pos) {
            case 1:
                /* Finished */
                /* If not repeated start, send stop. */
                if (i2c_data[index].shouldStop) {
                    (void)i2c_set_STOP(obj);
                    /* RIICnDRR read */
                    *(uint8_t *)obj->rx_buff.buffer = REG(DRR.UINT32) & 0xFF;
                    /* RIICnMR3.WAIT = 0 */
                    REG(MR3.UINT32) &= ~MR3_WAIT;
                    (void)i2c_wait_STOP(obj);
                    i2c_set_SR2_NACKF_STOP(obj);
                } else {
                    (void)i2c_restart(obj);
                    /* RIICnDRR read */
                    *(uint8_t *)obj->rx_buff.buffer = REG(DRR.UINT32) & 0xFF;
                    /* RIICnMR3.WAIT = 0 */
                    REG(MR3.UINT32) &= ~MR3_WAIT;
                    (void)i2c_wait_START(obj);
                    /* SR2.START = 0 */
                    REG(SR2.UINT32) &= ~SR2_START;
                }
                
                i2c_transfer_finished(obj);
                return;
                
            case 2:
                i2c_set_MR3_NACK(obj);
                break;
                
            case 3:
                /* this time is befor last byte read */
                /* Set MR3 WAIT bit is 1 */
                REG(MR3.UINT32) |= MR3_WAIT;
                break;
                
            default:
                i2c_set_MR3_ACK(obj);
                break;
        }
        *(uint8_t *)obj->rx_buff.buffer = REG(DRR.UINT32) & 0xFF;
        obj->rx_buff.buffer = (uint8_t *)obj->rx_buff.buffer + 1;
        ++obj->rx_buff.pos;
    }
}