MATによるDMA転送の方法

08 Feb 2016

お世話になります。

使用デバイス:mbed LPC1768

タイマーマッチ (MAT0.0) をトリガーとして1byteずつDMA転送をしたいと思っています。

下記に示すように0.5sごとに転送させることを想定して実装してみたのですが、 DMA転送は行われるものの一気に転送されてしまっているようです。

以下についてご教授いただけたらと思います。

  • 1.そもそもMATによるDMA Request はできるのか
  • 2.できるとしたら、以下のコードのどこに誤りがあるのか

何卒、よろしくお願い致します。

include the mbed library with this snippet

#include "mbed.h"

uint32_t srcBuffer[] = { 0x00040000 , 0x00100000, 0x00040000, 0x00100000, 0x00040000, 0x00100000, 0x00040000, 0x00100000, };
uint32_t dstBuffer[sizeof(srcBuffer)];

Serial serial(USBTX, USBRX);

int main() {
    serial.baud(115200);
    serial.printf("\r\n\r\nHello!\r\n");
    

    // Timer Settings
    LPC_SC->PCONP |= (0x01 << 1) | (0x01 << 22);
    LPC_SC->PCLKSEL0 |= (0x01 << 2); 
    LPC_PINCON->PINSEL7 |= (0x02 << 18);

    LPC_TIM0->TCR &= ~(0x01 << 0);
    
    LPC_TIM0->CTCR |= (0x00 << 0);
    LPC_TIM0->PR = 95999;           // 1 count-up per 1ms
    LPC_TIM0->MR0 = 500;            // 500ms
    LPC_TIM0->MCR |= (0x2 << 0);
    
    
    // DMA Settings
    uint32_t dstadr = (uint32_t)dstBuffer;
    LPC_GPIO1->FIODIR = (1 << 18) | (1 << 20);
   
    LPC_SC->PCONP |= (1UL << 29);
  
    LPC_GPDMA->DMACConfig |= 0x01;
    
    LPC_GPDMA->DMACIntTCClear = 0x0F;
    LPC_GPDMA->DMACIntErrClr  = 0x0F;
    
    LPC_SC->DMAREQSEL |= (1 << 0);
    LPC_GPDMA->DMACSoftBReq |= (1 << 8);

    LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)srcBuffer;
    LPC_GPDMACH0->DMACCDestAddr = dstadr;
    LPC_GPDMACH0->DMACCLLI = 0;
    LPC_GPDMACH0->DMACCControl =    (uint32_t)sizeof(srcBuffer) |
                                    (1 << 12) |
                                    (1 << 15) |
                                    (2 << 18) |
                                    (2 << 21) |
                                    (1 << 26) |
                                    (1 << 27);

    serial.printf("%08X %08X %08X %08X %08X %08X %08X %08X\r\n", dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3], dstBuffer[4], dstBuffer[5], dstBuffer[6], dstBuffer[7]);
    LPC_GPDMACH0->DMACCConfig = (1 << 0) |
                                (8 << 1) |
                                (0 << 11) |
                                (1 << 15);

    LPC_TIM0->TCR |= 0x01;  // Enable Timer
    
    while(1) {
        wait(0.5);
        serial.printf("%08X %08X %08X %08X %08X %08X %08X %08X\r\n", dstBuffer[0], dstBuffer[1], dstBuffer[2], dstBuffer[3], dstBuffer[4], dstBuffer[5], dstBuffer[6], dstBuffer[7]);
    }
}
09 Feb 2016

こんにちは。

一気に転送されてしまっているという事ですが、DMAの設定で転送するワード数がソースバッファ分全て設定されているようなので(DMACCControlのTransferSizeビット)、DMAが起動すると全て転送されてしまうのではないでしょうか?

Quote:

そもそもMATによるDMA Request はできるのか

これについては、mbedというよりもLPC1768の仕様だと思いますので、LPCOpenのようなNXPさんのサイトで聞いた方が良いかもしれません。

一般的にタイマー割り込みでのDMA起動などのトリガは可能ですが、割り込みを使わないで行おうとしているのでしょうか?

10 Feb 2016

ご返答ありがとうございます!

Quote:

一気に転送されてしまっているという事ですが、DMAの設定で転送するワード数がソースバッファ分全て設定されているようなので(DMACCControlのTransferSizeビット)、DMAが起動すると全て転送されてしまうのではないでしょうか?

こちら TransferSize を 1にしてみましたが、初回に1Byte分送信されたのみで残りが転送されませんでした。

Quote:

一般的にタイマー割り込みでのDMA起動などのトリガは可能ですが、割り込みを使わないで行おうとしているのでしょうか?

最終的には 1us ~ 数百ns くらのタイミングで転送を行いたく、割り込み処理の遅れが致命的になってしまうためペリフェラルのみで完結できる方法がないかと思案しているところです。

Quote:

LPCOpenのようなNXPさんのサイトで聞いた方が良いかもしれません。

たしかに、LPCのサイトの方が直接的な解答が頂けそうですね! そちらでも聞いてみたいと思います。