DMA - ダイレクトメモリアクセス

GPDMA (General Purpose Direct Memory Access Controller)

/cookbook/MODDMA

Andy Kirkham 氏のMODDMAライブラリで、DMAコントローラを手軽に使おう。

Import libraryMODDMA

MODDMA GPDMA Controller New features: transfer pins to memory buffer under periodic timer control and send double buffers to DAC

The LPC17xx GPDMA

GPDMA は、メモリ、ペリフェラル、レジスタ間のデータ転送をホストCPUの介在なしで行うことができます。

これにより、データ転送中に、CPUは別の仕事をすることが可能です。

LPC1768には8つまでのDMAが利用可能です。

Getting started

宣言

#include "mbed.h"
#include "MODDMA.h"

MODDMA dma;

MODDMA_Config

MODDMA_Config

メモリ → メモリ は、転送元と転送先のアドレスを指定し、m2m とする。

    MODDMA_Config *config;
    char src[] = "TEST TEST TEST";
    char dst[sizeof(src)];

    config = new MODDMA_Config;
    config->channelNum    ( MODDMA::Channel_0 );
    config->srcMemAddr    ( (uint32_t) &src );
    config->dstMemAddr    ( (uint32_t) &dst );
    config->transferSize  ( sizeof(src) );
    config->transferType  ( MODDMA::m2m );

    dma.Setup( config );
    dma.Enable ( config );

GPDMA_CONNECTION

GPDMA_CONNECTION

メモリ → ペリフェラル は、転送元のアドレス、転送先はあらかじめ定義されているペリフェラル名を指定し、m2p とする。

    MODDMA_Config *config = new MODDMA_Config;
    MODDMA::GPDMA_CONNECTION connection;
    char src[] = "TEST TEST TEST";

    connection = MODDMA::UART0_Tx;

    config->channelNum    ( MODDMA::Channel_0 );
    config->srcMemAddr    ( (uint32_t) &src );
    config->dstMemAddr    ( connection );
    config->transferSize  ( sizeof(src) );
    config->transferType  ( MODDMA::m2p );

    dma.Setup( config );
    dma.Enable ( config );

割込み

DMA完了時やエラー時の割込みは、コールバック関数を設定する。

void tc_callback () {
    MODDMA_Config *config = dma.getConfig();

     :

    // Clear DMA IRQ flags.
    if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();    
    if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq();    
}

void err_callback () {
    MODDMA_Config *config = dma.getConfig();

     :

    // Clear DMA IRQ flags.
    if (dma.irqType() == MODDMA::TcIrq) dma.clearTcIrq();    
    if (dma.irqType() == MODDMA::ErrIrq) dma.clearErrIrq();    
}

  :

    connection = MODDMA::UART0_Tx;

    config = new MODDMA_Config;
    config->channelNum    ( MODDMA::Channel_0 );
    config->srcMemAddr    ( (uint32_t) &src );
    config->dstMemAddr    ( connection );
    config->transferSize  ( sizeof(src) );
    config->transferType  ( MODDMA::m2p );
    config->attach_tc     ( tc_callback );
    config->attach_err    ( err_callback );

MODDMA_LLI

MODDMA_LLI

連続転送は Linked List Item (LLI) を切り替えながら、循環してDMA転送するようにする。

Import programMODDMA_LLI_test

GPDMA (Direct Memory Access) and LLI (Link List Item) test see: http://mbed.org/users/okini3939/notebook/dma_jp/

    MODDMA_Config *config;
    MODDMA::GPDMA_CONNECTION connection;
    MODDMA_LLI *lli0, *lli1;
    char src0[] = "TEST TEST TEST";
    char src1[] = "TEST TEST TEST";

    connection = MODDMA::UART0_Tx;

    lli0 = new MODDMA_LLI;
    lli1 = new MODDMA_LLI;

    config = new MODDMA_Config;
    config->channelNum    ( MODDMA::Channel_0 );
    config->srcMemAddr    ( (uint32_t) &src0 );
    config->dstMemAddr    ( connection );
    config->transferSize  ( sizeof(src0) );
    config->transferType  ( MODDMA::m2p );
    config->dmaLLI        ( (uint32_t)lli0 );
    config->attach_tc     ( tc_callback );
    config->attach_err    ( err_callback );

    lli0->SrcAddr = ( (uint32_t)&src0 );
    lli0->DstAddr = ( (uint32_t)dma.LUTPerAddr(connection) );
    lli0->NextLLI = ( (uint32_t)lli1 );
    lli0->Control = ( dma.CxControl_TransferSize(sizeof(src0)) 
                | dma.CxControl_SBSize((uint32_t)dma.LUTPerBurst(connection)) 
                | dma.CxControl_DBSize((uint32_t)dma.LUTPerBurst(connection)) 
                | dma.CxControl_SWidth((uint32_t)dma.LUTPerWid(connection)) 
                | dma.CxControl_DWidth((uint32_t)dma.LUTPerWid(connection)) 
                | dma.CxControl_SI() 
                | dma.CxControl_I() );

    lli1->SrcAddr = ( (uint32_t)&src1 );
    lli1->DstAddr = lli0->DstAddr;
    lli1->NextLLI = ( (uint32_t)lli0 );
    lli1->Control = lli0->Control;

    dma.Setup( config );
    dma.Enable ( config );

Note

  • SPIで使う場合、送信(Tx)と受信(Rx)を対でDMAを設定しないとバッファあふれで動かなくなります。

参考


戻る


Please log in to post comments.