Esempio n. 1
0
/*!
    \brief      handle I2C1 event interrupt request
    \param[in]  none
    \param[out] none
    \retval     none
*/
void I2C1_EventIRQ_Handler(void)
{
    if(i2c_flag_get(I2C1, I2C_ADDSEND)){
        /* clear the ADDSEND bit */
        event2 =i2c_flag_get(I2C1,I2C_ADDSEND );
    }else if(i2c_flag_get(I2C1, I2C_RBNE)){
        /* if reception data register is not empty ,I2C1 will read a data from I2C_DATA */
        *i2c_rxbuffer++ = i2c_receive_data(I2C1);
    }else if(i2c_flag_get(I2C1, I2C_STPDET)){
        Status=SUCCESS;
        /* clear the STPDET bit */
        i2c_enable(I2C1);
        /* disable I2C1 interrupt */
        i2c_interrupt_disable(I2C1, I2C_CTL1_ERRIE | I2C_CTL1_BUFIE | I2C_CTL1_EVIE);
    }
}
Esempio n. 2
0
/** Configure I2C as slave or master.
 *  @param obj The I2C object
 *  @param data    The buffer for receiving
 *  @param length  Number of bytes to read
 *  @return non-zero if a value is available
 */
int i2c_slave_read(i2c_t *obj, char *data, int length)
{
    struct i2c_s *obj_s = I2C_S(obj);
    int count = 0;
    int timeout = 0;

    i2c_ack_config(obj_s->i2c, I2C_ACK_ENABLE);

    /* wait until ADDSEND bit is set */
    while (!i2c_flag_get(obj_s->i2c, I2C_FLAG_ADDSEND)) {
        timeout++;
        if (timeout > 100000) {
            return -1;
        }
    }
    /* clear ADDSEND bit */
    i2c_flag_clear(obj_s->i2c, I2C_FLAG_ADDSEND);

    while (0 < length) {
        /* wait until the RBNE bit is set */
        timeout = 0;
        while (!i2c_flag_get(obj_s->i2c, I2C_FLAG_RBNE)) {
            timeout++;
            if (timeout > 100000) {
                return -1;
            }
        }
        *data = i2c_data_receive(obj_s->i2c);
        data++;
        length--;
        count++;
    }
    /* wait until the STPDET bit is set */
    timeout = 0;
    while (!i2c_flag_get(obj_s->i2c, I2C_FLAG_STPDET)) {
        timeout++;
        if (timeout > 100) {
            return count;
        }
    }
    /* clear the STPDET bit */
    i2c_enable(obj_s->i2c);

    i2c_ack_config(obj_s->i2c, I2C_ACK_DISABLE);

    return count;
}
Esempio n. 3
0
/** Configure I2C as slave or master.
 *  @param obj The I2C object
 *  @param data    The buffer for sending
 *  @param length  Number of bytes to write
 *  @return non-zero if a value is available
 */
int i2c_slave_write(i2c_t *obj, const char *data, int length)
{
    struct i2c_s *obj_s = I2C_S(obj);
    int count = 0;
    int timeout = 0;

    i2c_ack_config(obj_s->i2c, I2C_ACK_ENABLE);
    /* wait until ADDSEND bit is set */
    while (!i2c_flag_get(obj_s->i2c, I2C_FLAG_ADDSEND)) {
        timeout++;
        if (timeout > 100000) {
            return -1;
        }
    }
    /* clear ADDSEND bit */
    i2c_flag_clear(obj_s->i2c, I2C_FLAG_ADDSEND);
    while (length > 0) {
        /* wait until the TBE bit is set */
        timeout = 0;
        while (!i2c_flag_get(obj_s->i2c, I2C_FLAG_TBE)) {
            timeout++;
            if (timeout > 100000) {
                return -1;
            }
        }
        i2c_data_transmit(obj_s->i2c, *data);
        data++;
        length--;
        count++;
    }
    /* the master doesn't acknowledge for the last byte */
    timeout = 0;
    while (!i2c_flag_get(obj_s->i2c, I2C_FLAG_AERR)) {
        timeout++;
        if (timeout > 100000) {
            return -1;
        }
    }
    /* clear the bit of AERR */
    i2c_flag_clear(obj_s->i2c, I2C_FLAG_AERR);
    /* disable acknowledge */
    i2c_ack_config(obj_s->i2c, I2C_ACK_DISABLE);

    return count;
}
Esempio n. 4
0
/** Write one byte
 *
 *  @param obj The I2C object
 *  @param data Byte to be written
 *  @return 0 if NAK was received, 1 if ACK was received, 2 for timeout.
 */
int i2c_byte_write(i2c_t *obj, int data)
{
    int timeout;
    struct i2c_s *obj_s = I2C_S(obj);

    I2C_DATA(obj_s->i2c) = (uint8_t)data;

    /* wait until the byte is transmitted */
    timeout = FLAG_TIMEOUT;
    while (((i2c_flag_get(obj_s->i2c, I2C_FLAG_TBE)) == RESET) &&
            ((i2c_flag_get(obj_s->i2c, I2C_FLAG_BTC)) == RESET)) {
        if ((timeout--) == 0) {
            return 2;
        }
    }

    return 1;
}
Esempio n. 5
0
/** Send START command
 *
 *  @param obj The I2C object
 */
int i2c_start(i2c_t *obj)
{
    int timeout;
    struct i2c_s *obj_s = I2C_S(obj);

    /* clear I2C_FLAG_AERR Flag */
    i2c_flag_clear(obj_s->i2c, I2C_FLAG_AERR);

    /* wait until I2C_FLAG_I2CBSY flag is reset */
    timeout = FLAG_TIMEOUT;
    while ((i2c_flag_get(obj_s->i2c, I2C_FLAG_I2CBSY)) == SET) {
        if ((timeout--) == 0) {
            return (int)GD_BUSY;
        }
    }

    /* ensure the i2c has been stopped */
    timeout = FLAG_TIMEOUT;
    while ((I2C_CTL0(obj_s->i2c) & I2C_CTL0_STOP) == I2C_CTL0_STOP) {
        if ((timeout--) == 0) {
            return (int)GD_ERROR;
        }
    }

    /* generate a START condition */
    i2c_start_on_bus(obj_s->i2c);

    /* ensure the i2c has been started successfully */
    timeout = FLAG_TIMEOUT;
    while ((i2c_flag_get(obj_s->i2c, I2C_FLAG_SBSEND)) == RESET) {
        if ((timeout--) == 0) {
            return (int)GD_ERROR;
        }
    }

    return (int)GD_OK;
}
Esempio n. 6
0
/** Check to see if the I2C slave has been addressed.
 *  @param obj The I2C object
 *  @return The status - 1 - read addresses, 2 - write to all slaves,
 *         3 write addressed, 0 - the slave has not been addressed
 */
int i2c_slave_receive(i2c_t *obj)
{
    struct i2c_s *obj_s = I2C_S(obj);
    int ret = NoData;

    i2c_ack_config(obj_s->i2c, I2C_ACK_ENABLE);

    if (i2c_flag_get(obj_s->i2c, I2C_FLAG_ADDSEND)) {
        i2c_ack_config(obj_s->i2c, I2C_ACK_ENABLE);
        if (i2c_flag_get(obj_s->i2c, I2C_FLAG_RXGC)) {
            ret = WriteGeneral;
        }

        if (i2c_flag_get(obj_s->i2c, I2C_FLAG_TRS)) {
            ret = ReadAddressed;
        } else {
            ret = WriteAddressed;
        }
    }

    i2c_ack_config(obj_s->i2c, I2C_ACK_ENABLE);

    return (ret);
}
Esempio n. 7
0
/*!
    \brief      handle I2C1 error interrupt request
    \param[in]  none
    \param[out] none
    \retval     none
*/
void I2C1_ErrorIRQ_Handler(void)
{
    /* no acknowledge received */
    if(i2c_flag_get(I2C1, I2C_AERR)){
        i2c_flag_clear(I2C1, I2C_AERR);
    }

    /* SMBus alert */
    if(i2c_flag_get(I2C1, I2C_SMBALTS)){
        i2c_flag_clear(I2C1, I2C_SMBALTS);
    }

    /* bus timeout in SMBus mode */
    if(i2c_flag_get(I2C1, I2C_SMBTO)){
        i2c_flag_clear(I2C1, I2C_SMBTO);
    }

    /* over-run or under-run when SCL stretch is disabled */
    if(i2c_flag_get(I2C1, I2C_OUERR)){
       i2c_flag_clear(I2C1, I2C_OUERR);
    }

    /* arbitration lost */
    if(i2c_flag_get(I2C1, I2C_LOSTARB)){
        i2c_flag_clear(I2C1, I2C_LOSTARB);
    }

    /* bus error */
    if(i2c_flag_get(I2C1, I2C_BERR)){
        i2c_flag_clear(I2C1, I2C_BERR);
    }

    /* CRC value doesn't match */
    if(i2c_flag_get(I2C1, I2C_PECERR)){
        i2c_flag_clear(I2C1, I2C_PECERR);
    }

    /* disable the error interrupt */
    i2c_interrupt_disable(I2C1,I2C_CTL1_ERRIE | I2C_CTL1_BUFIE | I2C_CTL1_EVIE);
}
Esempio n. 8
0
/** Read one byte
 *
 *  @param obj The I2C object
 *  @param last Acknoledge
 *  @return The read byte
 */
int i2c_byte_read(i2c_t *obj, int last)
{
    int timeout;
    struct i2c_s *obj_s = I2C_S(obj);

    if (last) {
        /* disable acknowledge */
        i2c_ack_config(obj_s->i2c, I2C_ACK_DISABLE);
    } else {
        /* enable acknowledge */
        i2c_ack_config(obj_s->i2c, I2C_ACK_ENABLE);
    }

    /* wait until the byte is received */
    timeout = FLAG_TIMEOUT;
    while ((i2c_flag_get(obj_s->i2c, I2C_FLAG_RBNE)) == RESET) {
        if ((timeout--) == 0) {
            return -1;
        }
    }

    return (int)I2C_DATA(obj_s->i2c);
}
Esempio n. 9
0
/** Configure the I2C frequency
 *
 *  @param obj The I2C object
 *  @param hz  Frequency in Hz
 */
void i2c_frequency(i2c_t *obj, int hz)
{
    int timeout;
    struct i2c_s *obj_s = I2C_S(obj);

    /* wait until I2C_FLAG_I2CBSY flag is reset */
    timeout = BUSY_TIMEOUT;
    while ((i2c_flag_get(obj_s->i2c, I2C_FLAG_I2CBSY)) && (--timeout != 0));

    /* reset to clear pending flags */
    i2c_hw_reset(obj);

    /* disable I2C peripheral */
    i2c_disable(obj_s->i2c);

    /* configure I2C frequence */
    i2c_clock_config(obj_s->i2c, hz, I2C_DTCY_2);

    /* configure I2C address mode and slave address */
    i2c_mode_addr_config(obj_s->i2c, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0);

    /* enable I2C peripheral */
    i2c_enable(obj_s->i2c);
}
Esempio n. 10
0
/** Blocking sending data
 *
 *  @param obj     The I2C object
 *  @param address 7-bit address (last bit is 0)
 *  @param data    The buffer for sending
 *  @param length  Number of bytes to write
 *  @param stop    Stop to be generated after the transfer is done
 *  @return
 *      zero or non-zero - Number of written bytes
 *      negative - I2C_ERROR_XXX status
 */
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
{
    struct i2c_s *obj_s = I2C_S(obj);
    gd_status_enum status = GD_OK;
    uint32_t count = 0;
    int timeout = 0;

    if (obj_s->global_trans_option == I2C_FIRST_AND_LAST_FRAME ||
            obj_s->global_trans_option == I2C_LAST_FRAME) {
        if (stop) {
            obj_s->global_trans_option = I2C_FIRST_AND_LAST_FRAME;
        } else {
            obj_s->global_trans_option = I2C_FIRST_FRAME;
        }
    } else if (obj_s->global_trans_option == I2C_FIRST_FRAME ||
               obj_s->global_trans_option == I2C_NEXT_FRAME) {
        if (stop) {
            obj_s->global_trans_option = I2C_LAST_FRAME;
        } else {
            obj_s->global_trans_option = I2C_NEXT_FRAME;
        }
    }

    if (obj_s->global_trans_option == I2C_FIRST_AND_LAST_FRAME || obj_s->global_trans_option == I2C_FIRST_FRAME) {
        /* wait until I2C_FLAG_I2CBSY flag is reset */
        timeout = FLAG_TIMEOUT;
        while ((i2c_flag_get(obj_s->i2c, I2C_FLAG_I2CBSY)) == SET) {
            if ((timeout--) == 0) {
                i2c_stop(obj);
                return I2C_ERROR_BUS_BUSY;
            }
        }
    }

    if (obj_s->global_trans_option == I2C_FIRST_AND_LAST_FRAME || obj_s->global_trans_option == I2C_FIRST_FRAME ||
            obj_s->previous_state_mode != I2C_STATE_MASTER_BUSY_TX) {
        /* generate a START condition */
        i2c_start_on_bus(obj_s->i2c);

        /* ensure the i2c has been started successfully */
        timeout = FLAG_TIMEOUT;
        while ((i2c_flag_get(obj_s->i2c, I2C_FLAG_SBSEND)) == RESET) {
            if ((timeout--) == 0) {
                i2c_stop(obj);
                return I2C_ERROR_BUS_BUSY;
            }
        }

        /* send slave address */
        i2c_master_addressing(obj_s->i2c, address, I2C_TRANSMITTER);

        /* wait until I2C_FLAG_ADDSEND flag is set */
        while (!i2c_flag_get(obj_s->i2c, I2C_FLAG_ADDSEND)) {
            timeout++;
            if (timeout > 100000) {
                i2c_stop(obj);
                return I2C_ERROR_NO_SLAVE;
            }
        }

        /* clear ADDSEND */
        i2c_flag_clear(obj_s->i2c, I2C_FLAG_ADDSEND);
    }

    obj_s->state = (operation_state_enum)I2C_STATE_MASTER_BUSY_TX;

    for (count = 0; count < length; count++) {
        status = (gd_status_enum)i2c_byte_write(obj, data[count]);
        if (status != 1) {
            i2c_stop(obj);
            return count;
        }
    }

    obj_s->previous_state_mode = obj_s->state;

    /* if not sequential write, then send stop */
    if (stop) {
        i2c_stop(obj);
    }

    return count;
}
Esempio n. 11
0
/** Blocking reading data
 *
 *  @param obj     The I2C object
 *  @param address 7-bit address (last bit is 1)
 *  @param data    The buffer for receiving
 *  @param length  Number of bytes to read
 *  @param stop    Stop to be generated after the transfer is done
 *  @return Number of read bytes
 */
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
{
    struct i2c_s *obj_s = I2C_S(obj);
    uint32_t count = 0U;
    int timeout = 0;

    if (obj_s->global_trans_option == I2C_FIRST_AND_LAST_FRAME ||
            obj_s->global_trans_option == I2C_LAST_FRAME) {
        if (stop) {
            obj_s->global_trans_option = I2C_FIRST_AND_LAST_FRAME;
        } else {
            obj_s->global_trans_option = I2C_FIRST_FRAME;
        }
    } else if (obj_s->global_trans_option == I2C_FIRST_FRAME ||
               obj_s->global_trans_option == I2C_NEXT_FRAME) {
        if (stop) {
            obj_s->global_trans_option = I2C_LAST_FRAME;
        } else {
            obj_s->global_trans_option = I2C_NEXT_FRAME;
        }
    }

    if (obj_s->global_trans_option == I2C_FIRST_AND_LAST_FRAME || obj_s->global_trans_option == I2C_FIRST_FRAME) {
        /* wait until I2C_FLAG_I2CBSY flag is reset */
        timeout = FLAG_TIMEOUT;
        while ((i2c_flag_get(obj_s->i2c, I2C_FLAG_I2CBSY)) == SET) {
            if ((timeout--) == 0) {
                i2c_stop(obj);
                return I2C_ERROR_BUS_BUSY;
            }
        }
    }

    if (obj_s->global_trans_option == I2C_FIRST_AND_LAST_FRAME || obj_s->global_trans_option == I2C_FIRST_FRAME ||
            obj_s->previous_state_mode != I2C_STATE_MASTER_BUSY_RX) {
        /* generate a START condition */
        i2c_start_on_bus(obj_s->i2c);

        /* ensure the i2c has been started successfully */
        timeout = FLAG_TIMEOUT;
        while ((i2c_flag_get(obj_s->i2c, I2C_FLAG_SBSEND)) == RESET) {
            if ((timeout--) == 0) {
                i2c_stop(obj);
                return I2C_ERROR_BUS_BUSY;
            }
        }

        /* send slave address */
        i2c_master_addressing(obj_s->i2c, address, I2C_RECEIVER);

        if (1 == length) {
            /* disable acknowledge */
            i2c_ack_config(obj_s->i2c, I2C_ACK_DISABLE);
            /* send a stop condition to I2C bus*/
        } else if (2 == length) {
            /* send a NACK for the next data byte which will be received into the shift register */
            i2c_ackpos_config(obj_s->i2c, I2C_ACKPOS_NEXT);
            /* disable acknowledge */
            i2c_ack_config(obj_s->i2c, I2C_ACK_DISABLE);
        } else {
            /* enable acknowledge */
            i2c_ack_config(obj_s->i2c, I2C_ACK_ENABLE);
        }

        /* wait until I2C_FLAG_ADDSEND flag is set */
        while (!i2c_flag_get(obj_s->i2c, I2C_FLAG_ADDSEND)) {
            timeout++;
            if (timeout > 100000) {
                i2c_stop(obj);
                return I2C_ERROR_NO_SLAVE;
            }
        }

        /* clear ADDSEND */
        i2c_flag_clear(obj_s->i2c, I2C_FLAG_ADDSEND);
    }

    obj_s->state = (operation_state_enum)I2C_STATE_MASTER_BUSY_RX;

    for (count = 0; count < length; count++) {
        if (length > 2 && count == length - 3) {
            while (RESET == i2c_flag_get(obj_s->i2c, I2C_FLAG_BTC));
            i2c_ack_config(obj_s->i2c, I2C_ACK_DISABLE);
        } else if (2 == length && count == 0) {
            while (RESET == i2c_flag_get(obj_s->i2c, I2C_FLAG_BTC));
        }

        while (RESET == i2c_flag_get(obj_s->i2c, I2C_FLAG_RBNE));
        data[count] = i2c_data_receive(obj_s->i2c);
    }

    obj_s->previous_state_mode = obj_s->state;

    /* if not sequential read, then send stop */
    if (stop) {
        i2c_stop(obj);
    }

    return count;
}