Ejemplo n.º 1
0
/** 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));
    }
}
Ejemplo n.º 2
0
/** Abort ongoing asynchronous transaction.
 *  @param obj The I2C object
 */
void i2c_abort_asynch(i2c_t *obj)
{
    // Do not deactivate I2C twice
    if (!i2c_active(obj)) return;

    // Disable interrupt
    i2c_enable_interrupt(obj, 0, false);

    // Abort
    obj->i2c.i2c->CMD = I2C_CMD_STOP | I2C_CMD_ABORT;

    // Block until free
    while(i2c_active(obj));

    unblockSleepMode(EM1);
}
Ejemplo n.º 3
0
int I2C::transfer(int address, const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length, const event_callback_t& callback, int event, bool repeated)
{
    lock();
    if (i2c_active(&_i2c)) {
        unlock();
        return -1; // transaction ongoing
    }
    aquire();

    _callback = callback;
    int stop = (repeated) ? 0 : 1;
    _irq.callback(&I2C::irq_handler_asynch);
    i2c_transfer_asynch(&_i2c, (void *)tx_buffer, tx_length, (void *)rx_buffer, rx_length, address, stop, _irq.entry(), event, _usage);
    unlock();
    return 0;
}
Ejemplo n.º 4
0
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)
{
    (void)stop;
    (void)hint;

    if (i2c_active(obj)) {
        return;
    }
    if ((tx_length == 0) && (rx_length == 0)) {
        return;
    }

    twi_info_t *twi_info = TWI_INFO(obj);
    twi_info->events     = 0;
    twi_info->handler    = (void (*)(void))handler;
    twi_info->event_mask = event;

    uint8_t twi_addr = twi_address(address);
    nrf_drv_twi_t const *twi = &m_twi_instances[TWI_IDX(obj)];

    if ((tx_length > 0) && (rx_length == 0)) {
        nrf_drv_twi_xfer_desc_t const xfer =
            NRF_DRV_TWI_XFER_DESC_TX(twi_addr, (uint8_t *)tx, tx_length);
        nrf_drv_twi_xfer(twi, &xfer,
            stop ? 0 : NRF_DRV_TWI_FLAG_TX_NO_STOP);
    }
    else if ((tx_length == 0) && (rx_length > 0)) {
        nrf_drv_twi_xfer_desc_t const xfer =
            NRF_DRV_TWI_XFER_DESC_RX(twi_addr, rx, rx_length);
        nrf_drv_twi_xfer(twi, &xfer, 0);
    }
    else if ((tx_length > 0) && (rx_length > 0)) {
        nrf_drv_twi_xfer_desc_t const xfer =
            NRF_DRV_TWI_XFER_DESC_TXRX(twi_addr,
                (uint8_t *)tx, tx_length, rx, rx_length);
        nrf_drv_twi_xfer(twi, &xfer, 0);
    }
}