static void I2CMaster_IRQ()

in IndustrialDeviceController/Software/MT3620_IDC_RTApp/lib/I2CMaster.c [477:567]


static void I2CMaster_IRQ(Platform_Unit unit)
{
    unsigned id = I2CMaster_UnitToID(unit);
    if (id >= MT3620_I2C_COUNT) {
        return;
    }

    MT3620_I2C_FIELD_WRITE(id, int_ctrl, mm_int_sta, true);

    I2CMaster* handle = &context[id];

    // This should never happen
    if (!handle->open) {
        return;
    }

    int32_t status = ERROR_NONE;
    if ((MT3620_I2C_FIELD_READ(id, mm_ack_val, mm_ack_id) & 0x1) != 0) {
        status = ERROR_I2C_ADDRESS_NACK;
    } else if (MT3620_I2C_FIELD_READ(id, mm_status, mm_arb_had_lose)) {
        MT3620_I2C_FIELD_WRITE(id, mm_status, mm_arb_had_lose, 1);
        status = ERROR_I2C_ARBITRATION_LOST;
    }

    uintptr_t txRemain = 0;
    uintptr_t rxRemain = 0;
    if (handle->useDMA) {
        MT3620_DMA_FIELD_WRITE(MT3620_I2C_DMA_TX(id), start, str, false);
        MT3620_DMA_FIELD_WRITE(MT3620_I2C_DMA_RX(id), start, str, false);

        txRemain += mt3620_dma[MT3620_I2C_DMA_TX(id)].rlct;
        rxRemain += mt3620_dma[MT3620_I2C_DMA_RX(id)].rlct;
    } else {
        unsigned i;
        for (i = 0; i < handle->count; i++) {
            uint8_t *readData = handle->transfer[i].readData;
            if (readData) {
                unsigned j;
                for (j = 0; j < handle->transfer[i].length; j++) {
                    if (!MT3620_I2C_FIELD_READ(id, mm_fifo_status, rx_fifo_emp)) {
                        readData[j] = mt3620_i2c[handle->id]->mm_fifo_data;
                    } else {
                        rxRemain++;
                    }
                }
            }
        }
    }

    mt3620_i2c_fifo_status_t fifo_status = { .mask = mt3620_i2c[id]->mm_fifo_status };
    mt3620_i2c_fifo_ptr_t    fifo_ptr    = { .mask = mt3620_i2c[id]->mm_fifo_ptr    };

    bool txClear = !fifo_status.tx_fifo_emp;
    if (txClear) {
        txRemain += (fifo_status.tx_fifo_full ? MT3620_I2C_TX_FIFO_DEPTH
            : (fifo_ptr.tx_fifo_wptr - fifo_ptr.tx_fifo_rptr));
    }

    bool rxClear = !fifo_status.rx_fifo_emp;
    if (rxClear) {
        rxRemain += (fifo_status.rx_fifo_full ? MT3620_I2C_RX_FIFO_DEPTH
            : (fifo_ptr.rx_fifo_wptr - fifo_ptr.rx_fifo_rptr));
    }

    if (txClear || rxClear) {
        fifoClearMaster(id, txClear, rxClear);
        if (status == ERROR_NONE) status = ERROR_I2C_TRANSFER_INCOMPLETE;
    }

    uintptr_t txCount = (txRemain > handle->txQueued
        ? 0 : (handle->txQueued - txRemain));
    uintptr_t rxCount = (rxRemain > handle->rxQueued
        ? 0 : (handle->rxQueued - rxRemain));

    uintptr_t dataCount = (txCount + rxCount);

    if (handle->callback) {
        handle->callback(status, dataCount);
    } else if (handle->callbackUser) {
        handle->callbackUser(status, dataCount, handle->userData);
    }

    handle->error        = (status != ERROR_NONE);
    handle->transfer     = NULL;
    handle->count        = 0;
    handle->txQueued     = 0;
    handle->rxQueued     = 0;
    handle->callback     = NULL;
    handle->callbackUser = NULL;
    handle->userData     = NULL;
}