in hw/mcu/ambiq/apollo3/src/ext/AmbiqSuite/mcu/apollo3/hal/am_hal_mspi.c [2764:3075]
uint32_t am_hal_mspi_interrupt_service(void *pHandle, uint32_t ui32IntStatus)
{
am_hal_mspi_state_t *pMSPIState = (am_hal_mspi_state_t *)pHandle;
uint32_t ui32Module;
uint32_t ui32Status;
#ifndef AM_HAL_DISABLE_API_VALIDATION
//
// Check the handle.
//
if (!AM_HAL_MSPI_CHK_HANDLE(pHandle))
{
return AM_HAL_STATUS_INVALID_HANDLE;
}
#endif // AM_HAL_DISABLE_API_VALIDATION
ui32Module = pMSPIState->ui32Module;
//
// Add a delay to help make the service function work.
//
// am_hal_flash_delay(FLASH_CYCLES_US(10));
#if MSPI_USE_CQ
if (pMSPIState->bHP)
{
#if 0
if (ui32IntStatus & AM_HAL_MSPI_INT_CQUPD)
{
while(1);
}
#endif
//
// Accumulate the INTSTAT for this transaction
//
pMSPIState->ui32TxnInt |= ui32IntStatus;
//
// We need to wait for the DMA complete as well
//
if (pMSPIState->ui32TxnInt & (AM_HAL_MSPI_INT_DMACMP | AM_HAL_MSPI_INT_ERR))
{
uint32_t index;
//
// Wait for the command completion
//
if (!(pMSPIState->ui32TxnInt & AM_HAL_MSPI_INT_CMDCMP))
{
//
//
//
while (!MSPIn(ui32Module)->INTSTAT_b.CMDCMP);
}
pMSPIState->ui32TxnInt |= MSPIn(ui32Module)->INTSTAT;
//
// Clear the interrupt status
//
MSPIn(ui32Module)->INTCLR = AM_HAL_MSPI_INT_ALL;
//
// Need to determine the error, call the callback with proper status
//
if (pMSPIState->ui32TxnInt & AM_HAL_MSPI_INT_ERR)
{
ui32Status = AM_HAL_STATUS_FAIL;
//
// Disable DMA
//
MSPIn(ui32Module)->DMACFG_b.DMAEN = 0;
//
// Must reset xfer block
//
MSPIn(ui32Module)->MSPICFG_b.IPRSTN = 0; // in reset
MSPIn(ui32Module)->MSPICFG_b.IPRSTN = 1; // back out -- clears current transfer
}
else
{
ui32Status = AM_HAL_STATUS_SUCCESS;
}
pMSPIState->ui32LastHPIdxProcessed++;
pMSPIState->ui32NumHPEntries--;
index = pMSPIState->ui32LastHPIdxProcessed % pMSPIState->ui32MaxHPTransactions;
am_hal_mspi_dma_entry_t *pDMAEntry = &pMSPIState->pHPTransactions[index];
//
// Call the callback
//
if ( pDMAEntry->pfnCallback != NULL )
{
pDMAEntry->pfnCallback(pDMAEntry->pCallbackCtxt, ui32Status);
pDMAEntry->pfnCallback = NULL;
}
//
// Post next transaction if queue is not empty
//
if (pMSPIState->ui32NumHPEntries)
{
pMSPIState->ui32TxnInt = 0;
program_dma(pMSPIState);
}
else
{
pMSPIState->bHP = false;
// Unpause the CQ
//
// Command to set the DMACFG to disable DMA.
// Need to make sure we disable DMA before we can reprogram
//
MSPIn(ui32Module)->DMACFG = _VAL2FLD(MSPI_DMACFG_DMAEN, 0);
// Restore interrupts
MSPIn(ui32Module)->INTEN &= ~(AM_HAL_MSPI_INT_DMACMP | AM_HAL_MSPI_INT_CMDCMP);
// Resume the CQ
MSPIn(ui32Module)->CQSETCLEAR = AM_HAL_MSPI_SC_UNPAUSE_CQ;
}
}
return AM_HAL_STATUS_SUCCESS;
}
#endif
//
// Need to check if there is an ongoing transaction
// This is needed because we may get interrupts even for the XIP transactions
//
if (pMSPIState->ui32NumCQEntries)
{
#if MSPI_USE_CQ
am_hal_cmdq_status_t status;
uint32_t index;
am_hal_mspi_CQ_t *pCQ = &g_MSPIState[ui32Module].CQ;
//
// Get the current and last indexes.
//
if (pCQ->pCmdQHdl)
{
ui32Status = am_hal_cmdq_get_status(pCQ->pCmdQHdl, &status);
if (AM_HAL_STATUS_SUCCESS == ui32Status)
{
// For Sequence - this can be updated in the callback
pMSPIState->bRestart = false;
//
// Figure out which callbacks need to be handled.
//
while (!pMSPIState->bRestart && (pMSPIState->ui32LastIdxProcessed != status.lastIdxProcessed))
{
pMSPIState->ui32LastIdxProcessed++;
pMSPIState->ui32NumCQEntries--;
index = pMSPIState->ui32LastIdxProcessed & (AM_HAL_MSPI_MAX_CQ_ENTRIES - 1);
if ( pMSPIState->pfnCallback[index] != NULL )
{
pMSPIState->pfnCallback[index](pMSPIState->pCallbackCtxt[index], AM_HAL_STATUS_SUCCESS);
if (pMSPIState->eSeq != AM_HAL_MSPI_SEQ_RUNNING)
{
pMSPIState->pfnCallback[index] = NULL;
}
}
}
// For Sequence - this can be updated in the callback
if (!pMSPIState->bRestart)
{
//
// Process one extra callback if there was an error.
//
if ( (ui32IntStatus & AM_HAL_MSPI_INT_ERR) || (status.bErr) )
{
pMSPIState->ui32LastIdxProcessed++;
pMSPIState->ui32NumCQEntries--;
index = pMSPIState->ui32LastIdxProcessed & (AM_HAL_MSPI_MAX_CQ_ENTRIES - 1);
if ( pMSPIState->pfnCallback[index] != NULL )
{
pMSPIState->pfnCallback[index](pMSPIState->pCallbackCtxt[index], AM_HAL_STATUS_FAIL);
if (pMSPIState->eSeq != AM_HAL_MSPI_SEQ_RUNNING)
{
pMSPIState->pfnCallback[index] = NULL;
}
}
// Disable CQ
ui32Status = mspi_cq_disable(pMSPIState);
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return ui32Status;
}
// Disable DMA
MSPIn(ui32Module)->DMACFG_b.DMAEN = 0;
// Must reset xfer block
MSPIn(ui32Module)->MSPICFG_b.IPRSTN = 0; // in reset
MSPIn(ui32Module)->MSPICFG_b.IPRSTN = 1; // back out -- clears current transfer
// Clear the CQ error.
MSPIn(ui32Module)->CQSTAT |= _VAL2FLD(MSPI_CQSTAT_CQERR, 0);
am_hal_cmdq_error_resume(pCQ->pCmdQHdl);
if (pMSPIState->ui32NumCQEntries)
{
// Re-enable CQ
ui32Status = mspi_cq_enable(pMSPIState);
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return ui32Status;
}
}
}
if (pMSPIState->ui32NumCQEntries == 0)
{
// Disable CQ
ui32Status = mspi_cq_disable(pMSPIState);
if (AM_HAL_STATUS_SUCCESS != ui32Status)
{
return ui32Status;
}
}
}
}
}
#else
//
// Accumulate the INTSTAT for this transaction
//
pMSPIState->ui32TxnInt |= ui32IntStatus;
//
// We need to wait for the DMA complete as well
//
if (pMSPIState->ui32TxnInt & (AM_HAL_MSPI_INT_DMACMP | AM_HAL_MSPI_INT_ERR))
{
uint32_t index;
//
// Wait for the command completion
//
if (!(pMSPIState->ui32TxnInt & AM_HAL_MSPI_INT_CMDCMP))
{
// May need to re-evaluate
while (!MSPIn(ui32Module)->INTSTAT_b.CMDCMP);
}
pMSPIState->ui32TxnInt |= MSPIn(ui32Module)->INTSTAT;
//
// Clear the interrupt status
//
MSPIn(ui32Module)->INTCLR = AM_HAL_MSPI_INT_ALL;
//
// Need to determine the error, call the callback with proper status
//
if (pMSPIState->ui32TxnInt & AM_HAL_MSPI_INT_ERR)
{
ui32Status = AM_HAL_STATUS_FAIL;
//
// Disable DMA
//
MSPIn(ui32Module)->DMACFG_b.DMAEN = 0;
//
// Must reset xfer block
//
MSPIn(ui32Module)->MSPICFG_b.IPRSTN = 0; // in reset
MSPIn(ui32Module)->MSPICFG_b.IPRSTN = 1; // back out -- clears current transfer
}
else
{
ui32Status = AM_HAL_STATUS_SUCCESS;
}
pMSPIState->ui32LastIdxProcessed++;
pMSPIState->ui32NumCQEntries--;
index = pMSPIState->ui32LastIdxProcessed % pMSPIState->ui32MaxTransactions;
//
// Call the callback
//
if ( pMSPIState->pfnCallback[index] != NULL )
{
pMSPIState->pfnCallback[index](pMSPIState->pCallbackCtxt[index], ui32Status);
pMSPIState->pfnCallback[index] = NULL;
}
//
// Post next transaction if queue is not empty
//
if (pMSPIState->ui32NumCQEntries)
{
index = (pMSPIState->ui32LastIdxProcessed + 1) % pMSPIState->ui32MaxTransactions;
pMSPIState->ui32TxnInt = 0;
run_txn_cmdlist(&pMSPIState->pTransactions[index], sizeof(am_hal_mspi_cq_dma_entry_t) / sizeof(am_hal_cmdq_entry_t));
}
}
#endif // !MSPI_USE_CQ
if (pMSPIState->ui32NumCQEntries == 0)
{
// Disable DMA
MSPIn(ui32Module)->DMACFG_b.DMAEN = 0;
}
}
//
// Return the status.
//
return AM_HAL_STATUS_SUCCESS;
}