がれすたさんのDIY日記

電子回路、Python、組み込みシステム開発、自作エフェクターを語るblog

MIMXRT10xxのUART DMAメモ

前回は割り込みについてやったので今回はDMAについてメモを書く
参考には公式サンプルのlpuart_edma_transferを使うのでそれを参考にしてください。

公式サンプルが動作コードなので使い方的なのは解説しません

DMA部分のメモ

ポーリング、割り込みとは違いDMAMUXEDMAAPIが新しく出てくるのでそれの説明からしていく。

    /*Initはクロックの供給をしている*/
    DMAMUX_Init(EXAMPLE_LPUART_DMAMUX_BASEADDR);

 /*ソースとチャンネルの設定*/
    DMAMUX_SetSource(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_TX_DMA_CHANNEL, LPUART_TX_DMA_REQUEST);
    DMAMUX_SetSource(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_RX_DMA_CHANNEL, LPUART_RX_DMA_REQUEST);

 /*チャンネルの有効*/
    DMAMUX_EnableChannel(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_TX_DMA_CHANNEL);
    DMAMUX_EnableChannel(EXAMPLE_LPUART_DMAMUX_BASEADDR, LPUART_RX_DMA_CHANNEL);


f:id:gsmcustomeffects:20191012214331p:plain
DMAMUX_SetSourceの設定だが引数がbase,channel,sourceである。
channelはDMAのチャンネルなので好きなチャンネルを設定すればいい
sourceはペリフェラル側なので決まっている値使うペリフェラルごとにMIMXRT1052.hで定義されている。
f:id:gsmcustomeffects:20191012214721p:plain

LPUARTの場合は送受信で2,3を使っている。
DMAMUX_EnableChannelのほうは0,1をチャンネルとして設定している。

    /*デフォルト設定の読み込み*/
    EDMA_GetDefaultConfig(&config);

    /*EDMAの初期化*/
    EDMA_Init(EXAMPLE_LPUART_DMA_BASEADDR, &config);

    /*ハンドル設定/
    EDMA_CreateHandle(&g_lpuartTxEdmaHandle, EXAMPLE_LPUART_DMA_BASEADDR, LPUART_TX_DMA_CHANNEL);
    EDMA_CreateHandle(&g_lpuartRxEdmaHandle, EXAMPLE_LPUART_DMA_BASEADDR, LPUART_RX_DMA_CHANNEL);

EDMAに関してはInitしてHandleの登録するだけ。

LPUART_TransferCreateHandleEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, LPUART_UserCallback, NULL, &g_lpuartTxEdmaHandle,
                                    &g_lpuartRxEdmaHandle);

最後にLPUART_TransferCreateHandleEDMAでUART用のハンドルを作成する。
コールバックやEDMAHandleを登録する。

あとは送受信APIを呼ぶだけ。

LPUART_ReceiveEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &receiveXfer);
LPUART_SendEDMA(DEMO_LPUART, &g_lpuartEdmaHandle, &sendXfer);

コールバックに関してはサンプルと同様にstatus比較で処理分岐するのがいいと思う

void LPUART_UserCallback(LPUART_Type *base, lpuart_edma_handle_t *handle, status_t status, void *userData)
{
    userData = userData;

    if (kStatus_LPUART_TxIdle == status)
    {
        txBufferFull = false;
        txOnGoing = false;
    }

    if (kStatus_LPUART_RxIdle == status)
    {
        rxBufferEmpty = false;
        rxOnGoing = false;
    }
}

まとめ

LPUARTでDMAの使い方をまとめた。
LPUARTにDMA専用APIが用意されているので比較的楽に記述できる点が良いと感じた。