こんにちは、みんな
最近、SPI DMAのマルチセンサー通信で問題が発生しました。SPIトランザクションが-EIOで返却されるか、データが破損している場合です。私が見つけたドライバに掘り下げると、spi_nxp_lpspi転送開始時に両方のLPSPI DMA要求有効ビットを有効にしますが、転送の最後には1ビットだけが無効になります。2つのDMAチャネルのうち2番目に終了するものが、自身のDERビットをクリアせずにSPIコンテキストを完了するため、各転送は次のリクエストに1つのEnable Leakを送ります。
In ドライバ/spi/spi_nxp_lpspi/spi_nxp_lpspi_dma.c, 両方のビットがtransceive_dma()(:346)で同時に有効化されています:
if (channel == dma_data->dma_tx.channel) {
spi_mcux_issue_TCR(spi_dev);
dma_data->state = LPSPI_TRANSFER_STATE_TX_DONE;
base->DER &= ~LPSPI_DER_TDDE_MASK;
} else {
dma_data->state = LPSPI_TRANSFER_STATE_RX_DONE;
base->DER &= ~LPSPI_DER_RDDE_MASK;
}lpspi_dma_callback()では、最初に終了するチャネルが自分のビットをクリアします(:249–:253):
if (channel == dma_data->dma_tx.channel) {
spi_mcux_issue_TCR(spi_dev);
dma_data->state = LPSPI_TRANSFER_STATE_TX_DONE;
base->DER &= ~LPSPI_DER_TDDE_MASK;
} else {
dma_data->state = LPSPI_TRANSFER_STATE_RX_DONE;
base->DER &= ~LPSPI_DER_RDDE_MASK;
}両方のビットをクリアすると、すべてのトランザクションが警告なしに通過するようです。以下は私が使用したパッチです。
@@ lpspi_dma_callback()
case LPSPI_TRANSFER_STATE_TX_DONE:
case LPSPI_TRANSFER_STATE_RX_DONE:
dma_data->state = LPSPI_TRANSFER_STATE_RX_TX_DONE;
/* TX and RX both done here. */
+ base->DER &= ~(LPSPI_DER_TDDE_MASK | LPSPI_DER_RDDE_MASK);
spi_context_complete(ctx, spi_dev, 0);
spi_context_cs_control(ctx, false);
break;
@@
error:
+ base->DER &= ~(LPSPI_DER_TDDE_MASK | LPSPI_DER_RDDE_MASK);
LOG_ERR("DMA callback error with channel %d.", channel);
spi_context_complete(ctx, spi_dev, ret);
spi_context_cs_control(ctx, false);添付は私が使ったテストアプリケーションです。上記の解決策がアプリに組み込まれています。
私の質問は、ドライバーが片方だけクリアして両方がクリアされない理由があるのでしょうか?