/*---------------------------------------------------------------------------*/ int i2c1_transfer(struct i2c_msg *msg) { I2C_TransferSeq_TypeDef seq; I2C_TransferReturn_TypeDef ret; uint32_t timeout = 3000; memset(&seq,0,sizeof(seq)); seq.addr = msg->address << 1; seq.flags = 0; if(msg->mode & I2C_WRITE) { seq.flags |= I2C_FLAG_WRITE; seq.buf[0].data = msg->buf; seq.buf[0].len = msg->len; } if(msg->mode & I2C_READ) { seq.flags |= I2C_FLAG_READ; seq.buf[1].data = msg->buf; seq.buf[1].len = msg->len; } ret = I2C_TransferInit(I2C1, &seq); while (ret == i2cTransferInProgress && timeout--) { ret = I2C_Transfer(I2C1); } if(ret != 0) return -EIO; return 1; }
// Used by the read_register and write_register functions // data_array is read data for WRITE_READ and tx2 data for WRITE_WRITE void i2c_transfer(uint16_t device_addr, uint8_t cmd_array[], uint8_t data_array[], uint16_t cmd_len, uint16_t data_len, uint8_t flag) { // Transfer structure I2C_TransferSeq_TypeDef i2cTransfer; // Initialize I2C transfer I2C_TransferReturn_TypeDef result; i2cTransfer.addr = device_addr; i2cTransfer.flags = flag; i2cTransfer.buf[0].data = cmd_array; i2cTransfer.buf[0].len = cmd_len; // Note that WRITE_WRITE this is tx2 data i2cTransfer.buf[1].data = data_array; i2cTransfer.buf[1].len = data_len; // Set up the transfer result = I2C_TransferInit(I2C0, &i2cTransfer); // Do it until the transfer is done while (result != i2cTransferDone) { if (result != i2cTransferInProgress) { DEBUG_BREAK; } result = I2C_Transfer(I2C0); } }
//0.95s内完成 uint8_t drv_R8025T_read(uint8_t addr, uint8_t* data, uint8_t len) { uint8_t result = 0; // uint8_t idx; // uint8_t try_count = 0; // uint32_t star_tick; /* Transfer structure */ I2C_TransferSeq_TypeDef i2cTransfer;// /* Initializing I2C transfer */ i2cTransfer.addr = R8025T_SLAVE_ADDRESS; i2cTransfer.flags = I2C_FLAG_WRITE_READ;//I2C_FLAG_WRITE_READ - data written from buf[0].data and read into buf[1].data i2cTransfer.buf[0].data = (&addr); i2cTransfer.buf[0].len = 1; i2cTransfer.buf[1].data = data; i2cTransfer.buf[1].len = len; I2C_TransferInit(I2C0, &i2cTransfer); /* Sending data */ while (I2C_Transfer(I2C0) == i2cTransferInProgress){;} result = (sizeof(data)/sizeof(uint8_t)); return result; }
/***************************************************************************//** * @brief * Write to sensor register. * * @param[in] i2c * Pointer to I2C peripheral register block. * * @param[in] addr * I2C address for temperature sensor, in 8 bit format, where LSB is reserved * for R/W bit. * * @param[in] reg * Register to write (temperature register cannot be written). * * @param[in] val * Value used when writing to register. * * @return * Returns 0 if register written, <0 if unable to write to register. ******************************************************************************/ int I2C_RegisterSet(I2C_TypeDef *i2c, uint8_t addr, uint8_t reg, uint8_t val) { I2C_TransferSeq_TypeDef seq; uint8_t data[1]; uint8_t data2[1]; seq.addr = addr; seq.flags = I2C_FLAG_WRITE_WRITE; /* Select register to be written */ data[0] = reg; seq.buf[0].data = data; /* Only 1 byte reg */ data2[0] = val; seq.buf[0].len = 1; seq.buf[1].data = data2; seq.buf[1].len = 1; /* Do a polled transfer */ I2C_Status = I2C_TransferInit(i2c, &seq); /* Sending data */ while (I2C_Transfer(I2C0) != i2cTransferDone){;} // // while (I2C_Status != i2cTransferDone) // { // /* Enter EM1 while waiting for I2C interrupt */ // EMU_EnterEM1(); // /* Could do a timeout function here. */ // } return(0); }
/***************************************************************************//** * @brief * Read sensor register content. * * @details * If reading the temperature register, when a measurement is completed inside * the sensor device, the new measurement may not be stored. For this reason, * the temperature should not be polled with a higher frequency than the * measurement conversion time for a given resolution configuration. Please * refer to sensor device datasheet. * * @param[in] i2c * Pointer to I2C peripheral register block. * * @param[in] addr * I2C address for temperature sensor, in 8 bit format, where LSB is reserved * for R/W bit. * * @param[in] reg * Register to read. * * @param[out] val * Reference to place register read. * * @return * Returns 0 if register read, <0 if unable to read register. ******************************************************************************/ int I2C_RegisterGet(I2C_TypeDef *i2c, uint8_t addr, uint8_t reg, uint8_t *val, uint32_t len) { I2C_TransferSeq_TypeDef seq; uint8_t regid[1]; uint8_t data[1]; seq.addr = addr; seq.flags = I2C_FLAG_WRITE_READ; /* Select register to be read */ regid[0] = ((uint8_t)reg); seq.buf[0].data = regid; seq.buf[0].len = 1; /* Only 1 byte reg*/ seq.buf[1].data = data; seq.buf[1].len = 1; /* Do a polled transfer */ I2C_Status = I2C_TransferInit(i2c, &seq); /* Sending data */ while (I2C_Transfer(I2C0) != i2cTransferDone){;} //if (I2C_Status != i2cTransferDone) //{ //return((int)I2C_Status); //} *val = data[0]; return(0); }
/** * @brief Start and track an I2C transfer. */ static void _transfer(i2c_t dev, I2C_TransferSeq_TypeDef *transfer) { i2c_progress[dev] = I2C_TransferInit(i2c_config[dev].dev, transfer); /* the transfer progresses via the interrupt handler */ while (i2c_progress[dev] == i2cTransferInProgress) { __WFI(); } }
/** Start i2c asynchronous transfer. * @param obj The I2C object * @param tx The buffer to send * @param tx_length The number of words to transmit * @param rx The buffer to receive * @param rx_length The number of words to receive * @param address The address to be set - 7bit or 9 bit * @param stop If true, stop will be generated after the transfer is done * @param handler The I2C IRQ handler to be set * @param hint DMA hint usage */ void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint32_t address, uint32_t stop, uint32_t handler, uint32_t event, DMAUsage hint) { I2C_TransferReturn_TypeDef retval; if(i2c_active(obj)) return; if((tx_length == 0) && (rx_length == 0)) return; // For now, we are assuming a solely interrupt-driven implementation. // Store transfer config obj->i2c.xfer.addr = address; // Some combination of tx_length and rx_length will tell us what to do if((tx_length > 0) && (rx_length == 0)) { obj->i2c.xfer.flags = I2C_FLAG_WRITE; //Store buffer info obj->i2c.xfer.buf[0].data = (void *)tx; obj->i2c.xfer.buf[0].len = (uint16_t) tx_length; } else if ((tx_length == 0) && (rx_length > 0)) { obj->i2c.xfer.flags = I2C_FLAG_READ; //Store buffer info obj->i2c.xfer.buf[0].data = rx; obj->i2c.xfer.buf[0].len = (uint16_t) rx_length; } else if ((tx_length > 0) && (rx_length > 0)) { obj->i2c.xfer.flags = I2C_FLAG_WRITE_READ; //Store buffer info obj->i2c.xfer.buf[0].data = (void *)tx; obj->i2c.xfer.buf[0].len = (uint16_t) tx_length; obj->i2c.xfer.buf[1].data = rx; obj->i2c.xfer.buf[1].len = (uint16_t) rx_length; } if(address > 255) obj->i2c.xfer.flags |= I2C_FLAG_10BIT_ADDR; // Store event flags obj->i2c.events = event; // Enable interrupt i2c_enable_interrupt(obj, handler, true); // Kick off the transfer retval = I2C_TransferInit(obj->i2c.i2c, &(obj->i2c.xfer)); if(retval == i2cTransferInProgress) { blockSleepMode(EM1); } else { // something happened, and the transfer did not go through // So, we need to clean up // Disable interrupt i2c_enable_interrupt(obj, 0, false); // Block until free while(i2c_active(obj)); } }
/***************************************************************************//** * @brief * Perform I2C transfer * * @details * This driver only supports master mode, single bus-master. It does not * return until the transfer is complete, polling for completion. * * @param[in] i2c * Pointer to the peripheral port * * @param[in] seq * Pointer to sequence structure defining the I2C transfer to take place. The * referenced structure must exist until the transfer has fully completed. ******************************************************************************/ I2C_TransferReturn_TypeDef I2CSPM_Transfer(I2C_TypeDef *i2c, I2C_TransferSeq_TypeDef *seq) { I2C_TransferReturn_TypeDef ret; uint32_t timeout = I2CSPM_TRANSFER_TIMEOUT; /* Do a polled transfer */ ret = I2C_TransferInit(i2c, seq); while (ret == i2cTransferInProgress && timeout--) { ret = I2C_Transfer(i2c); } return ret; }
/***************************************************************************//** * @brief * Perform I2C transfer. * * @details * This driver only supports master mode, single bus-master. It does not * return until the transfer is complete, polling for completion. * * @param[in] seq * Pointer to sequence structure defining the I2C transfer to take place. The * referenced structure must exist until the transfer has fully completed. ******************************************************************************/ I2C_TransferReturn_TypeDef I2CDRV_Transfer(I2C_TransferSeq_TypeDef *seq) { I2C_TransferReturn_TypeDef ret; uint32_t timeout = 300000; /* Do a polled transfer */ ret = I2C_TransferInit(I2C0, seq); while (ret == i2cTransferInProgress && timeout--) { ret = I2C_Transfer(I2C0); } return(ret); }
/***************************************************************************//** * @brief * Perform I2C transfer. * * @details * This driver only supports master mode, single bus-master. It does not * return until the transfer is complete, polling for completion. * * @param[in] seq * Pointer to sequence structure defining the I2C transfer to take place. The * referenced structure must exist until the transfer has fully completed. ******************************************************************************/ I2C_TransferReturn_TypeDef I2CDRV_Transfer(I2C_TransferSeq_TypeDef *seq) { I2C_TransferReturn_TypeDef ret; /* Do a polled transfer */ ret = I2C_TransferInit(I2C0, seq); while (ret == i2cTransferInProgress) { ret = I2C_Transfer(I2C0); } return(ret); }
/** * @brief Start and track an I2C transfer. */ static void _transfer(i2c_t dev, I2C_TransferSeq_TypeDef *transfer) { bool busy = true; /* start the i2c transaction */ i2c_progress[dev] = I2C_TransferInit(i2c_config[dev].dev, transfer); /* the transfer progresses via the interrupt handler */ while (busy) { unsigned int cpsr = irq_disable(); if (i2c_progress[dev] == i2cTransferInProgress) { cortexm_sleep_until_event(); } else { busy = false; } irq_restore(cpsr); } }
/********************************************************************** * 8025T向寄存器写数据驱动函数 **********************************************************************/ uint8_t drv_R8025T_write(uint8_t addr, uint8_t* data, uint8_t len) { // bool result = false; // uint8_t idx; // uint8_t try_count; // uint32_t star_tick; /* Transfer structure */ I2C_TransferSeq_TypeDef i2cTransfer;// /* Initializing I2C transfer */ i2cTransfer.addr = R8025T_SLAVE_ADDRESS; i2cTransfer.flags = I2C_FLAG_WRITE_WRITE; i2cTransfer.buf[0].data = (&addr); i2cTransfer.buf[0].len = 1; i2cTransfer.buf[1].data = data; i2cTransfer.buf[1].len = len; I2C_TransferInit(I2C0, &i2cTransfer); /* Sending data */ while (I2C_Transfer(I2C0) == i2cTransferInProgress){;} return 0; }
/***************************************************************************//** * @brief * Write to IIC device * * @details * * @note * * @param[in] dev * Pointer to device descriptor * * @param[in] pos * Slave address * * @param[in] buffer * Poniter to the buffer * * @param[in] size * Buffer size in byte * * @return * Error code ******************************************************************************/ static rt_size_t rt_iic_write ( rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) { rt_err_t err_code; rt_size_t write_size; struct efm32_iic_device_t* iic; I2C_TransferSeq_TypeDef seq; I2C_TransferReturn_TypeDef ret; if (!size) { return 0; } err_code = RT_EOK; write_size = 0; iic = (struct efm32_iic_device_t*)dev->user_data; /* Lock device */ if (rt_hw_interrupt_check()) { ret = rt_sem_take(iic->lock, RT_WAITING_NO); } else { ret = rt_sem_take(iic->lock, RT_WAITING_FOREVER); } if (ret != RT_EOK) { return ret; } if (iic->state & IIC_STATE_MASTER) { seq.addr = (rt_uint16_t)pos << 1; seq.flags = I2C_FLAG_WRITE; /* Set write buffer pointer and size */ seq.buf[0].data = (rt_uint8_t *)buffer; seq.buf[0].len = size; } else { // TODO: Slave mode TX } /* Do a polled transfer */ iic->timeout = false; rt_timer_stop(iic->timer); rt_timer_start(iic->timer); ret = I2C_TransferInit(iic->iic_device, &seq); while ((ret == i2cTransferInProgress) && !iic->timeout) { ret = I2C_Transfer(iic->iic_device); } if (ret != i2cTransferDone) { err_code = (rt_err_t)ret; } else { write_size = size; } /* Unlock device */ rt_sem_release(iic->lock); /* set error code */ rt_set_errno(err_code); return write_size; }
/***************************************************************************//** * @brief * Read from IIC device * * @details * * @note * * @param[in] dev * Pointer to device descriptor * * @param[in] pos * Slave address * * @param[in] buffer * Poniter to the buffer * * @param[in] size * Buffer size in byte * * @return * Error code ******************************************************************************/ static rt_size_t rt_iic_read ( rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) { rt_err_t err_code; rt_size_t read_size; struct efm32_iic_device_t* iic; I2C_TransferSeq_TypeDef seq; I2C_TransferReturn_TypeDef ret; if (!size) { return 0; } err_code = RT_EOK; read_size = 0; iic = (struct efm32_iic_device_t*)dev->user_data; /* Lock device */ if (rt_hw_interrupt_check()) { ret = rt_sem_take(iic->lock, RT_WAITING_NO); } else { ret = rt_sem_take(iic->lock, RT_WAITING_FOREVER); } if (ret != RT_EOK) { return ret; } if (iic->state & IIC_STATE_MASTER) { seq.addr = (rt_uint16_t)pos << 1; if (*(rt_uint8_t *)buffer == IIC_OP_READ_ONLY) { seq.flags = I2C_FLAG_READ; /* Set read buffer pointer and size */ seq.buf[0].data = (rt_uint8_t *)buffer; seq.buf[0].len = size; } else { seq.flags = I2C_FLAG_WRITE_READ; /* Set register to be read */ seq.buf[0].data = (rt_uint8_t *)buffer; seq.buf[0].len = 1; /* Set read buffer pointer and size */ seq.buf[1].data = (rt_uint8_t *)buffer; seq.buf[1].len = size; } /* Do a polled transfer */ iic->timeout = false; rt_timer_stop(iic->timer); rt_timer_start(iic->timer); ret = I2C_TransferInit(iic->iic_device, &seq); while ((ret == i2cTransferInProgress) && !iic->timeout) { ret = I2C_Transfer(iic->iic_device); } if (ret != i2cTransferDone) { iic_debug("IIC: read error %x\n", ret); iic_debug("IIC: read address %x\n", seq.addr); iic_debug("IIC: read data0 %x -> %x\n", seq.buf[0].data, *seq.buf[0].data); iic_debug("IIC: read len0 %x\n", seq.buf[0].len); iic_debug("IIC: read data1 %x -> %x\n", seq.buf[1].data, *seq.buf[1].data); iic_debug("IIC: read len1 %x\n", seq.buf[1].len); err_code = (rt_err_t)ret; } else { read_size = size; iic_debug("IIC: read size %d\n", read_size); } } else { rt_uint8_t* ptr; ptr = buffer; /* interrupt mode Rx */ while (size) { rt_base_t level; struct efm32_iic_int_mode_t *int_rx; int_rx = iic->rx_buffer; /* disable interrupt */ level = rt_hw_interrupt_disable(); if (int_rx->read_index != int_rx->save_index) { /* read a character */ *ptr++ = int_rx->data_ptr[int_rx->read_index]; size--; /* move to next position */ int_rx->read_index ++; if (int_rx->read_index >= IIC_RX_BUFFER_SIZE) { int_rx->read_index = 0; } } else { /* set error code */ err_code = -RT_EEMPTY; /* enable interrupt */ rt_hw_interrupt_enable(level); break; } /* enable interrupt */ rt_hw_interrupt_enable(level); } read_size = (rt_uint32_t)ptr - (rt_uint32_t)buffer; iic_debug("IIC: slave read size %d\n", read_size); } /* Unlock device */ rt_sem_release(iic->lock); /* set error code */ rt_set_errno(err_code); return read_size; }