DMA triggered by a GPIO

Showing results for 
Search instead for 
Did you mean: 

DMA triggered by a GPIO

Contributor III

Hi community,

It is the third ticket I open.

I dont succedded to work with gpio trigger on DMA.

I'm using Kinetis K64 + SDK 2.1.

I wrote a minimalist example, with a very simple memory to memory DMA transfer.

When I start it explicitly with EDMA_StartTransfer(&g_EDMA_Handle) so all is OK and I get the interrupt notification at the end of the transfer.

But when I configured my GPIO pin to be a trigger ( like that):

    PORT_SetPinInterruptConfig(ADS_PORT, N_DRDY_PIN, kPORT_DMAFallingEdge);
    PORT_SetPinMux(ADS_PORT, N_DRDY_PIN, kPORT_MuxAsGpio);
    GPIO_PinInit(ADC_GPIO, N_DRDY_PIN, &config);


and the DMAMUX0 like:

    DMAMUX_SetSource(DMAMUX0, 0, kDmaRequestMux0PortD);
    DMAMUX_EnableChannel(DMAMUX0, 0);

    EDMA_Init(DMA0, &userConfig);
    EDMA_CreateHandle(&g_EDMA_Handle, DMA0, 0);
    EDMA_SetCallback(&g_EDMA_Handle, _edma_cb, NULL);
    EDMA_PrepareTransfer(&transferConfig, srcAddr, sizeof(srcAddr[0]), destAddr, sizeof(destAddr[0]),
                             sizeof(srcAddr[0]), sizeof(srcAddr), kEDMA_MemoryToMemory);
    EDMA_SubmitTransfer(&g_EDMA_Handle, &transferConfig);

It doesnt work me at all ....

Note that I checked with scope the interrupts and this is working.

Where should be configured the trigger please.

Please help.

I don't found in the datasheet how the DMA can be hardware triggered. The only trigger the datasheet talks is in DMAMUX.


1 Reply

Specialist V


This is the code used in the uTasker project to trigger DMA transfers from port changes. This particular reference shows how to cause a second GPIO (port mirroring) to follow a port input by each change triggering a suitable DMA transfer. Complete code is available in the open source uTasker project at (search for the define DMA_PORT_MIRRORING in Port_Interrupts.h; the GPIO is configured for DMA triggering in kinetis_PORTS.h and the DMA controller set up in kinetis_DMA.h).
Apart from the limitation of the DMA channel used the code is target independent and so operates on all Kinetis parts with DMA.

INTERRUPT_SETUP interrupt_setup;                    // interrupt configuration parameters
interrupt_setup.int_type = PORT_INTERRUPT;          // identifier to configure port interrupt
interrupt_setup.int_port       = PORTB;             // the port that the interrupt input is on
interrupt_setup.int_port_bits  = PORTB_BIT16;       // UART input pin on FRDM-K64F
interrupt_setup.int_port_sense = (IRQ_BOTH_EDGES | PULLUP_ON | PORT_DMA_MODE); // DMA on both edges
interrupt_setup.int_handler = 0;                    // no interrupt handler when using DMA

// Configure the DMA trigger from the UART input pin change to toggle an alternative port so that the input signal is mirrored to that output without CPU intervention
static const unsigned long ulOutput = PORTC_BIT16;  // the output to be mirrored to
fnConfigDMA_buffer(9, DMAMUX0_CHCFG_SOURCE_PORTB, sizeof(ulOutput), (void *)&ulOutput, (void *)&(((GPIO_REGS *)GPIOC_ADD)->PTOR), (DMA_FIXED_ADDRESSES | DMA_LONG_WORDS), 0, 0); // use DMA channel 9 without any interrupts (free-runnning)

fnConfigureInterrupt((void *)&interrupt_setup);     // configure interrupt

Note that the DMAMUX trigger is selected as DMAMUX0_CHCFG_SOURCE_PORTB and that only one such DMA trigger is available on each of the GPIO ports (whereby ports are A, B, C, D etc.).