Exemple #1
0
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) {
    I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
    I2cHandle.Instance = (I2C_TypeDef *)(obj->i2c);
    int timeout;
    int count;
    int value;

    if (length == 0) return 0;

    i2c_start(obj);

    // Wait until SB flag is set
    timeout = FLAG_TIMEOUT;
    while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_SB) == RESET) {
        timeout--;
        if (timeout == 0) {
            return 0;
        }
    }

    i2c->DR = __HAL_I2C_7BIT_ADD_READ(address);


    // Wait address is acknowledged
    timeout = FLAG_TIMEOUT;
    while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_ADDR) == RESET) {
        timeout--;
        if (timeout == 0) {
            return 0;
        }
    }
    __HAL_I2C_CLEAR_ADDRFLAG(&I2cHandle);

    // Read all bytes except last one
    for (count = 0; count < (length - 1); count++) {
        value = i2c_byte_read(obj, 0);
        data[count] = (char)value;
    }

    // If not repeated start, send stop.
    // Warning: must be done BEFORE the data is read.
    if (stop) {
        i2c_stop(obj);
    }

    // Read the last byte
    value = i2c_byte_read(obj, 1);
    data[count] = (char)value;

    return length;
}
Exemple #2
0
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) {
    I2C_TypeDef *i2c = (I2C_TypeDef *)(obj->i2c);
    I2cHandle.Instance = (I2C_TypeDef *)(obj->i2c);
    int timeout;
    int count;

    if (length == 0) return 0;
    i2c_start(obj);

    // Wait until SB flag is set
    timeout = FLAG_TIMEOUT;
    while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_SB) == RESET) {
        timeout--;
        if (timeout == 0) {
            return 0;
        }
    }

    i2c->DR = __HAL_I2C_7BIT_ADD_WRITE(address);


    // Wait address is acknowledged
    timeout = FLAG_TIMEOUT;
    while (__HAL_I2C_GET_FLAG(&I2cHandle, I2C_FLAG_ADDR) == RESET) {
        timeout--;
        if (timeout == 0) {
            return 0;
        }
    }
    __HAL_I2C_CLEAR_ADDRFLAG(&I2cHandle);

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

    // If not repeated start, send stop.
    if (stop) {
        i2c_stop(obj);
    }

    return count;
}
Exemple #3
0
// this function is based on STM code
int machine_hard_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_t *src, size_t len, bool stop) {
    machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t*)self_in;
    I2C_HandleTypeDef *hi2c = self->pyb->i2c;
    uint32_t Timeout = *self->timeout;

    /* Init tickstart for timeout management*/
    uint32_t tickstart = HAL_GetTick();

#if 0
    // TODO: for multi-master, here we could wait for the bus to be free
    // we'd need a flag to tell if we were in the middle of a set of transactions
    // (ie didn't send a stop bit in the last call)
    /* Wait until BUSY flag is reset */
    if (!I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart)) {
        return -MP_EBUSY;
    }
#endif

    /* Check if the I2C is already enabled */
    if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) {
        /* Enable I2C peripheral */
        __HAL_I2C_ENABLE(hi2c);
    }

    /* Disable Pos */
    hi2c->Instance->CR1 &= ~I2C_CR1_POS;

    /* Send Slave Address */
    int ret = send_addr_byte(hi2c, I2C_7BIT_ADD_WRITE(addr << 1), Timeout, tickstart);
    if (ret != 0) {
        return ret;
    }

    /* Clear ADDR flag */
    __HAL_I2C_CLEAR_ADDRFLAG(hi2c);

    int num_acks = 0;

    while (len > 0U) {
        /* Wait until TXE flag is set */
        while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_TXE) == RESET) {
            /* Check if a NACK is detected */
            if (I2C_IsAcknowledgeFailed(hi2c)) {
                goto nack;
            }

            /* Check for the Timeout */
            if (Timeout != HAL_MAX_DELAY) {
                if ((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout)) {
                    goto timeout;
                }
            }
        }

        /* Write data to DR */
        hi2c->Instance->DR = *src++;
        len--;

        /* Wait until BTF flag is set */
        while (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == RESET) {
            /* Check if a NACK is detected */
            if (I2C_IsAcknowledgeFailed(hi2c)) {
                goto nack;
            }

            /* Check for the Timeout */
            if (Timeout != HAL_MAX_DELAY) {
                if ((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout)) {
                    goto timeout;
                }
            }
        }
        ++num_acks;
    }
nack:

    /* Generate Stop */
    if (stop) {
        hi2c->Instance->CR1 |= I2C_CR1_STOP;
    }

    return num_acks;

timeout:
    // timeout, release the bus cleanly
    hi2c->Instance->CR1 |= I2C_CR1_STOP;
    return -MP_ETIMEDOUT;
}
Exemple #4
0
// this function is based on STM code
int machine_hard_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop) {
    machine_hard_i2c_obj_t *self = (machine_hard_i2c_obj_t*)self_in;
    I2C_HandleTypeDef *hi2c = self->pyb->i2c;
    uint32_t Timeout = *self->timeout;

    /* Init tickstart for timeout management*/
    uint32_t tickstart = HAL_GetTick();

#if 0
    // TODO: for multi-master, here we could wait for the bus to be free
    // we'd need a flag to tell if we were in the middle of a set of transactions
    // (ie didn't send a stop bit in the last call)
    /* Wait until BUSY flag is reset */
    if (!I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BUSY, SET, I2C_TIMEOUT_BUSY_FLAG, tickstart)) {
        return -MP_EBUSY;
    }
#endif

    /* Check if the I2C is already enabled */
    if ((hi2c->Instance->CR1 & I2C_CR1_PE) != I2C_CR1_PE) {
        /* Enable I2C peripheral */
        __HAL_I2C_ENABLE(hi2c);
    }

    /* Disable Pos */
    hi2c->Instance->CR1 &= ~I2C_CR1_POS;

    /* Enable Acknowledge */
    hi2c->Instance->CR1 |= I2C_CR1_ACK;

    /* Send Slave Address */
    int ret = send_addr_byte(hi2c, I2C_7BIT_ADD_READ(addr << 1), Timeout, tickstart);
    if (ret != 0) {
        return ret;
    }

    if (len == 0U) {
        /* Clear ADDR flag */
        __HAL_I2C_CLEAR_ADDRFLAG(hi2c);

        /* Generate Stop */
        if (stop) {
            hi2c->Instance->CR1 |= I2C_CR1_STOP;
        }
    } else if (len == 1U) {
        /* Disable Acknowledge */
        hi2c->Instance->CR1 &= ~I2C_CR1_ACK;

        /* Clear ADDR flag */
        __HAL_I2C_CLEAR_ADDRFLAG(hi2c);

        /* Generate Stop */
        if (stop) {
            hi2c->Instance->CR1 |= I2C_CR1_STOP;
        }
    } else if (len == 2U) {
        /* Disable Acknowledge */
        hi2c->Instance->CR1 &= ~I2C_CR1_ACK;

        /* Enable Pos */
        hi2c->Instance->CR1 |= I2C_CR1_POS;

        /* Clear ADDR flag */
        __HAL_I2C_CLEAR_ADDRFLAG(hi2c);
    } else {
        /* Enable Acknowledge */
        hi2c->Instance->CR1 |= I2C_CR1_ACK;

        /* Clear ADDR flag */
        __HAL_I2C_CLEAR_ADDRFLAG(hi2c);
    }

    while (len > 0U) {
        if (len <= 3U) {
            if (len == 1U) {
                /* Wait until RXNE flag is set */
                int ret = I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart);
                if (ret != 0) {
                    return ret;
                }

                /* Read data from DR */
                *dest++ = hi2c->Instance->DR;
                len--;
            } else if (len == 2U) {
                /* Wait until BTF flag is set */
                if (!I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart)) {
                  return -MP_ETIMEDOUT;
                }

                /* Generate Stop */
                if (stop) {
                    hi2c->Instance->CR1 |= I2C_CR1_STOP;
                }

                /* Read data from DR */
                *dest++ = hi2c->Instance->DR;
                len--;

                /* Read data from DR */
                *dest++ = hi2c->Instance->DR;
                len--;
            } else {
                /* Wait until BTF flag is set */
                if (!I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart)) {
                  return -MP_ETIMEDOUT;
                }

                /* Disable Acknowledge */
                hi2c->Instance->CR1 &= ~I2C_CR1_ACK;

                /* Read data from DR */
                *dest++ = hi2c->Instance->DR;
                len--;

                /* Wait until BTF flag is set */
                if (!I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_BTF, RESET, Timeout, tickstart)) {
                    return -MP_ETIMEDOUT;
                }

                /* Generate Stop */
                if (stop) {
                    hi2c->Instance->CR1 |= I2C_CR1_STOP;
                }

                /* Read data from DR */
                *dest++ = hi2c->Instance->DR;
                len--;

                /* Read data from DR */
                *dest++ = hi2c->Instance->DR;
                len--;
            }
        } else {
            /* Wait until RXNE flag is set */
            int ret = I2C_WaitOnRXNEFlagUntilTimeout(hi2c, Timeout, tickstart);
            if (ret != 0) {
                return ret;
            }

            /* Read data from DR */
            *dest++ = hi2c->Instance->DR;
            len--;

            if (__HAL_I2C_GET_FLAG(hi2c, I2C_FLAG_BTF) == SET) {
                /* Read data from DR */
                *dest++ = hi2c->Instance->DR;
                len--;
            }
        }
    }

    return 0;
}