示例#1
0
文件: i2cm.c 项目: AronPride/Wellness
static void I2CM_IRQHandler(uint32_t instance)
{
    i2c_master_t *im = &i2c_master_state[instance];
    mxc_i2cm_regs_t *regs = MXC_I2CM_GET_I2CM(instance);
    mxc_i2cm_intfl_t intfl = regs->intfl_f;
    mxc_i2cm_inten_t inten = regs->inten_f;

    regs->intfl_f = intfl;

    if(intfl.tx_done && inten.tx_done)
    {
        if(!im->bytes_left)
        {
            if(im->stop_bit) {
                I2CM_WriteToTxFifo(im->index, MXC_S_I2CM_TRANS_TAG_STOP);
            }

            inten.tx_done = 0;
            regs->inten_f = inten;

            im->buf = NULL;

            if(im->callback_fn) {
                im->callback_fn(0);
            }
        }
        else {
            do_xmit(im);
        }
    }

    if((intfl.rx_fifo_not_empty || intfl.rx_fifo_full || intfl.rx_fifo_2q_full || intfl.rx_fifo_3q_full ) && inten.rx_fifo_empty)
    {
        volatile uint16_t *rx_fifo = (uint16_t *)(MXC_I2CM_GET_BASE_FIFO(im->index) + 0x800);
        uint8_t bytes_to_read = regs->bb_f.rx_fifo_cnt;
        uint32_t i;

        if(im->bytes_index < im->bytes_left) 
        {
            for(i = 0; i < bytes_to_read; i++) {
                im->buf[im->bytes_index++] = *rx_fifo;
            }
        }

        if(im->bytes_index == im->bytes_left) {
            inten = regs->inten_f;
            inten.rx_fifo_2q_full = 0;
            inten.rx_fifo_3q_full = 0;
            inten.rx_fifo_full = 0;
            inten.rx_fifo_empty = 0;
            regs->inten_f = inten;

            im->buf = NULL;

            if(im->callback_fn) {
                im->callback_fn(im->bytes_index);
            }
        }
    }
}
示例#2
0
void i2c_init(i2c_t *obj, PinName sda, PinName scl)
{
    // determine the I2C to use
    I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA);
    I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL);
    mxc_i2cm_regs_t *i2c = (mxc_i2cm_regs_t*)pinmap_merge(i2c_sda, i2c_scl);
    MBED_ASSERT((int)i2c != NC);

    obj->i2c = i2c;
    obj->fifos = (mxc_i2cm_fifo_regs_t*)MXC_I2CM_GET_BASE_FIFO(MXC_I2CM_GET_IDX(i2c));
    obj->start_pending = 0;
    obj->stop_pending = 0;

    // configure the pins
    pinmap_pinout(sda, PinMap_I2C_SDA);
    pinmap_pinout(scl, PinMap_I2C_SCL);

    // enable the clock
    MXC_CLKMAN->sys_clk_ctrl_9_i2cm = MXC_S_CLKMAN_CLK_SCALE_DIV_1;

    // reset module
    i2c->ctrl = MXC_F_I2CM_CTRL_MSTR_RESET_EN;
    i2c->ctrl = 0;

    // set default frequency at 100k
    i2c_frequency(obj, 100000);

    // set timeout to 255 ms and turn on the auto-stop option
    i2c->timeout = (0xFF << MXC_F_I2CM_TIMEOUT_TX_TIMEOUT_POS) | MXC_F_I2CM_TIMEOUT_AUTO_STOP_EN;

    // enable tx_fifo and rx_fifo
    i2c->ctrl |= (MXC_F_I2CM_CTRL_TX_FIFO_EN | MXC_F_I2CM_CTRL_RX_FIFO_EN);
}
示例#3
0
文件: i2cm.c 项目: AronPride/Wellness
static void do_xmit(i2c_master_t *im)
{
    volatile uint16_t *tx_fifo = (uint16_t *)MXC_I2CM_GET_BASE_FIFO(im->index);
    mxc_i2cm_regs_t *regs = MXC_I2CM_GET_I2CM(im->index);

    if(im->bytes_left && im->buf)
    {
        do {
            *tx_fifo = (MXC_S_I2CM_TRANS_TAG_TXDATA_ACK | im->buf[im->bytes_index++]);
            --im->bytes_left;
        } while(im->bytes_left && regs->intfl_f.tx_fifo_3q_empty);
    }
}
示例#4
0
文件: i2cm.c 项目: AronPride/Wellness
inline static int32_t I2CM_WriteToTxFifo(uint8_t index, const uint16_t data)
{
    volatile uint16_t *tx_fifo = (uint16_t *)MXC_I2CM_GET_BASE_FIFO(index);
    mxc_i2cm_regs_t *regs = MXC_I2CM_GET_I2CM(index);
    mxc_i2cm_intfl_t intfl;

    while(*tx_fifo) {
        intfl = regs->intfl_f;
        if((intfl.tx_nacked) || (intfl.tx_timeout) || (intfl.tx_lost_arbitr)) {
            return -1;
        }
    }
    *tx_fifo = data;
    return 0;
}
示例#5
0
文件: i2cm.c 项目: AronPride/Wellness
static int32_t I2CM_Rx(uint8_t index, uint8_t addr, uint8_t *data, uint32_t bytes)
{
    mxc_i2cm_regs_t *regs = MXC_I2CM_GET_I2CM(index);
    volatile uint16_t *rx_fifo = (uint16_t *)(MXC_I2CM_GET_BASE_FIFO(index) + 0x800);
    uint32_t i = bytes;
    
    /* start + addr (read) */
    if(I2CM_WriteToTxFifo(index, (MXC_S_I2CM_TRANS_TAG_START | addr | I2C_SLAVE_ADDR_READ_BIT))) { 
        return -1;
    }
    
    while(i > 256) 
    {
        if(I2CM_WriteToTxFifo(index, (MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT | 255))) {
            return -1;
        }
        i -= 256;
    }

    if (i > 1) 
    {
        if(I2CM_WriteToTxFifo(index, (MXC_S_I2CM_TRANS_TAG_RXDATA_COUNT | (i - 2)))) {
            return -1;
        }
    }

    mxc_i2cm_trans_t trans = regs->trans_f;
    /* start the transaction if it wasn't already started */
    if (!trans.tx_in_progress) {
        trans.tx_start = 1;
        regs->trans_f = trans;
    }

    if(I2CM_WriteToTxFifo(index, MXC_S_I2CM_TRANS_TAG_RXDATA_NACK)) { /* NACK last data byte */
        return -1;
    }

    if(I2CM_WriteToTxFifo(index, MXC_S_I2CM_TRANS_TAG_STOP)) { /* stop condition */
        return -1;
    }

    int32_t timeout = MXC_I2CM_RX_TIMEOUT;
    uint16_t temp;

    i = 0;
    while(i < bytes)
    {
        while (!regs->intfl_f.rx_fifo_not_empty && (regs->bb_f.rx_fifo_cnt == 0)) {
            if ((timeout-- < 0) || !regs->trans_f.tx_in_progress) {
                return -1;
            }
        }

        timeout = MXC_I2CM_RX_TIMEOUT;
    
        mxc_i2cm_intfl_t intfl = regs->intfl_f;
        intfl.rx_fifo_not_empty = 1;
        regs->intfl_f = intfl;

        temp = *rx_fifo;

        if(temp & MXC_S_I2CM_RSTLS_TAG_EMPTY) {
            continue;
        }
        data[i++] = (uint8_t) temp;
    }
    return i;
}