LPC43XX: Timer triggered DMA transfer?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC43XX: Timer triggered DMA transfer?

Jump to solution
4,018 Views
a_bet
Contributor IV

Hi to you all,
I've search the web (having a thread going on ARM Connected Community), read the manual, tried LPCOpenV2.20 (last available) and tried my code too, but: I'm still unable to trigger a memory-to-memory DMA transfer using a timer as a trigger.
LPCOpen provides an example which is similar to what I'm trying to do: "DMA example using a timer capture input as a trigger", actually I'm trying to use a timer match as a trigger.
The setup function looks like this (Note that the //comments are not mine):

/* Setup DMA M2M transfer to trigger on timer match */
static void setupDMATrigger(void)
{
    /* Initialize GPDMA controller */
    Chip_GPDMA_Init(LPC_GPDMA);

    /* Get DMA channel */
    dmaCh = Chip_GPDMA_GetFreeChannel(LPC_GPDMA, GPDMA_CONN_MAT0_0);

    /* Setup DMA transfer */
    Chip_GPDMA_Transfer(LPC_GPDMA, dmaCh,
                      (uint32_t) &source[0], GPDMA_CONN_MAT0_0, //(uint32_t) &dest[0],
                      GPDMA_TRANSFERTYPE_M2M_CONTROLLER_DMA,
                      sizeof(source));

//            Chip_GPDMA_Stop(LPC_GPDMA, dmaChSSPTx);

    /* Enable GPDMA interrupt */
    NVIC_EnableIRQ(DMA_IRQn);
}

But then in the main function:

int main(void)
{
    int numDmaXfers = 0;

    SystemCoreClockUpdate();
    Board_Init();

    /* Setup tiemr capture input used for DMA trigger */
    setupTimerCapInput();

    /* Setup timer for match event on each capture event */
    setupTimerTrigger();


    /* Setup DMA for memory to memory transfer on timer match event */
//    setupDMATrigger();


    /* Enable timer interrupt */
    NVIC_EnableIRQ(TIMER0_IRQn);
    NVIC_ClearPendingIRQ(TIMER0_IRQn);

... etc, etc ...

The function is grayed out!

The timer has it's own setup, but I believe that's not critical, the manual states this about DMA Operation (Chapter 32, sec. 32.7.2):

DMA requests are generated by 0 to 1 transitions of the External Match 0 and 1 bits of
each timer. In order to have an effect, the GPDMA must be configured and the relevant
timer DMA request selected as a DMA source via the CREG block, see Table 101.

So it looks to me, that the timer just keeps going and the DMA must "sense" the timer REQ. That makes well.. sense.
The problem is in the Chip_GPDMA_Transfer call: GPDMA_CONN_MAT0_0 is not the destination. And I believe &dest[0] was correct.

How am I supposed to connect the peripheral to DMA in a way such that it triggers the transfer, but it is not the source nor the destination (because actually it isn't)?


Any help would be highly appreciated, and I'll attach both the example 's source and the user manual for your reference.

Regards,
Andrea

Original Attachment has been moved to: cr_startup_lpc43xx.c.zip

Original Attachment has been moved to: sysinit.c.zip

Original Attachment has been moved to: periph_dma_timertrig.c.zip

Labels (4)
1 Solution
2,015 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Andrea,

Sorry, I have no idea of the attached file to be erroneously, then make you felt confused.

Let me explain it in details.

As the these figure 1 & figure 1 illuminates, the Memm-to-memory mode doesn't request trigger (Fig 1), then figure 2 has demonstrated the completely process of the Memm-to-memory mode, it works without any peripheral requests.

So you need to trigger the Memm-to-memory transfer via the software instead the original approach.

Hope this is clear.

2017-03-20_11-00-06.jpg

                                                                       Fig 1

2017-03-20_10-49-45.jpg

                                                                         Fig 2


Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

View solution in original post

7 Replies
2,013 Views
billygao
Contributor I

Excuse me, but I want to ask if there is someone solved this question. I'd like to read the date from camera with dma triggered by the timer connected to pclk(with the camera).

Sorry for my bad English.

0 Kudos
2,014 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Andrea Bettati,

Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.

I've amended the codes, please refer to the code below for details.

/*
 * @brief DMA example using a timer capture input as a trigger
 *
 * @note
 * Copyright(C) NXP Semiconductors, 2013
 * All rights reserved.
 *
 * @par
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * LPC products.  This software is supplied "AS IS" without any warranties of
 * any kind, and NXP Semiconductors and its licensor disclaim any and
 * all warranties, express or implied, including all implied warranties of
 * merchantability, fitness for a particular purpose and non-infringement of
 * intellectual property rights.  NXP Semiconductors assumes no responsibility
 * or liability for the use of the software, conveys no license or rights under any
 * patent, copyright, mask work right, or any other intellectual property rights in
 * or to any products. NXP Semiconductors reserves the right to make changes
 * in the software without notification. NXP Semiconductors also makes no
 * representation or warranty that such application will be suitable for the
 * specified use without further testing or modification.
 *
 * @par
 * Permission to use, copy, modify, and distribute this software and its
 * documentation is hereby granted, under NXP Semiconductors' and its
 * licensor's relevant copyrights in the software, without fee, provided that it
 * is used in conjunction with NXP Semiconductors microcontrollers.  This
 * copyright, permission, and disclaimer notice must appear in all copies of
 * this code.
 */

#include "board.h"

/*****************************************************************************
 * Private types/enumerations/variables
 ****************************************************************************/

#define SOURCEARRAYSIZE (4)

#define TICKRATE_HZ 10
/* Source and destination DMA areas */
static uint32_t source[SOURCEARRAYSIZE], dest[SOURCEARRAYSIZE];

/* Counters used for DMA transfers and passed comparisons */
static volatile int dmaXfers;
static int compPass;

/* DMA channel */
static uint8_t dmaCh;

/*****************************************************************************
 * Public types/enumerations/variables
 ****************************************************************************/

/*****************************************************************************
 * Private functions
 ****************************************************************************/



/* Setup a timer for external capture input trigger */
static void setupTimerTrigger(void)
{
     uint32_t timerFreq;
     /* Enable timer 0 clock and reset it */
     Chip_TIMER_Init(LPC_TIMER0);
     Chip_RGU_TriggerReset(RGU_TIMER0_RST);
     while (Chip_RGU_InReset(RGU_TIMER0_RST)) {}

     //Amendment
     /* Get timer 1 peripheral clock rate */
     timerFreq = Chip_Clock_GetRate(CLK_MX_TIMER0);

     /* Timer setup for match and interrupt at TICKRATE_HZ */
     Chip_TIMER_Reset(LPC_TIMER0);
     Chip_TIMER_MatchEnableInt(LPC_TIMER0, 1);
     Chip_TIMER_SetMatch(LPC_TIMER0, 1, (timerFreq / TICKRATE_HZ));
     Chip_TIMER_ResetOnMatchEnable(LPC_TIMER0, 1);
     Chip_TIMER_Enable(LPC_TIMER0);     
     
     /* Enable timer interrupt */
     NVIC_EnableIRQ(TIMER0_IRQn);
     NVIC_ClearPendingIRQ(TIMER0_IRQn);
     
     //Amendment
     
     
}

/* Setup DMA M2M transfer to trigger on timer match */
static void setupDMATrigger(void)
{
     /* Initialize GPDMA controller */
     Chip_GPDMA_Init(LPC_GPDMA);

     /* Get DMA channel */
     dmaCh = Chip_GPDMA_GetFreeChannel(LPC_GPDMA, GPDMA_CONN_MAT0_1);

     /* Setup DMA transfer */
     Chip_GPDMA_Transfer(LPC_GPDMA, dmaCh,
                           (uint32_t) &source[0], GPDMA_CONN_MAT0_1 , //(uint32_t) &dest[0],
                           GPDMA_TRANSFERTYPE_M2M_CONTROLLER_DMA,
                           sizeof(source));

//     Chip_GPDMA_Stop(LPC_GPDMA, dmaChSSPTx);

     /* Enable GPDMA interrupt */
     NVIC_EnableIRQ(DMA_IRQn);
}

/* Put some varying data in the source buffer */
static void fillSourceBuff(void)
{
     int i;
     static uint32_t seed;

     for (i = 0; i < SOURCEARRAYSIZE; i++) {
          seed += 1 + (seed << 1);
          source[i] = seed;
     }
}

/* Verify source and destination data (after DMA transfer) */
static int checkSourceDestData(void)
{
     int i, matches = 1;

     for (i = 0; i < SOURCEARRAYSIZE; i++) {
          if (source[i] != dest[i]) {
               matches = 0;
          }
     }

     return matches;
}

/*****************************************************************************
 * Public functions
 ****************************************************************************/

/**
 * @brief     DMA interrupt handler
 * @return     Nothing
 */
void DMA_IRQHandler(void)
{
     Board_LED_Toggle(0);

     /* Increase DMA transfer count */
     dmaXfers++;

//     if (Chip_GPDMA_Interrupt(LPC_GPDMA, dmaCh) == SUCCESS) {
//          isDmaTxfCompleted = 1;
//     }
}

void TIMER0_IRQHandler(void)
{
     static bool On = false;

     if (Chip_TIMER_MatchPending(LPC_TIMER0, 0)) {
          Chip_TIMER_ClearMatch(LPC_TIMER0, 0);
          On = (bool) !On;
          Board_LED_Set(0, On);
     }
}

/**
 * @brief     Main routine for DMA timer trigger example
 * @return     Nothing
 */
int main(void)
{
     int numDmaXfers = 0;

     SystemCoreClockUpdate();
     Board_Init();


     /* Setup source data */
     fillSourceBuff();
     /* Setup DMA for memory to memory transfer on timer match event */
     setupDMATrigger();
     
     /* Setup timer for match event on each capture event */
     setupTimerTrigger();


          /* Wait for interrupt */
          __WFI();

          if (numDmaXfers != dmaXfers) {
               numDmaXfers = dmaXfers;

               /* Compare data */
               compPass += checkSourceDestData();

               DEBUGOUT("DMA transfer triggered by timer: %d\r\n", numDmaXfers);
               DEBUGOUT("DMA transfer memory comparisons: %d\r\n", compPass);
          }

     /* Idle in background waiting for DMA events */
     while (1) {

     }

     return 0;
}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Hope it helps.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

2,015 Views
a_bet
Contributor IV

Hi jeremyzhou‌ thanks for your reply. I tested your code and it is not working.
I think you copied the timer setup from the "timers.c" example, but this is not enough to get the dma example working.
What the example NXP is providing is supposed to do the following:
while(1)
{

  1.  Initialize timer, dma, a source buffer
  2. At every timer match the dma copy of the source buffer into the destination one should be automatically (read via hardware) triggered by the timer match event.
  3. Re-initialize the source buffer with random numbers

}
I hope I explained what is going on.
The code you suggest is not working, in-fact nothing is being transfered into the dest buffer: even if the DMA ISR is called, the destination buffer is constantly 0. As you can see in the picture below.Untitled window_149.png

So, may I ask you (or someone in the technical support at NXP) to dig a little further? This chip is as poorly documented as underrated:
Looking forward to hear from the support team.

Andrea

0 Kudos
2,014 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Andrea,

Thanks for your reply.

I've contacted with the LPCOpen library about the issue, and I also found some bugs with the demo.

And I'm working on it now.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
2,015 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Andrea,

Let me clarify it.

I'm afraid that your purpose can't be achieved as the Memory-to-memory DMA flow mode doesn't support the request trigger (Fig 1). Therefore, you should follow these process to trigger DMA when match even happen.

1).

Initialize timer, dma, a source buffer.

2).

while(1)
{

   Output the values of the destination area for checking.

   Re-initialize the DMA

}

3).

In the timer's interrupt function, enable the DMA channel (Set the E bit in the Channel configuration registers) which can be implemented via calling the Chip_GPDMA_Transfe().

2017-03-20_11-00-06.jpg

                                         Fig 1

Hope it helps.
Have a great day,

Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos
2,015 Views
a_bet
Contributor IV

Hi jeremyzhou‌,
thanks for the reply. I'm don't understand the point of the image you posted (I use LPCXpresso) anyway, I get what you mean.
Basically this equals trigger the DMA transfer via software: I was trying to do it via hardware, not in the timer ISR and I thought (actually it was so) that the purpose of the example was to trigger the DMA transfer via hardware not software.
This is critical for the product I'm designing because I have to do some real-time processing and I'm trying to avoid having multiple ISR going at the same time.
So, with

I'm afraid that your purpose can't be achieved as the Memory-to-memory DMA flow mode doesn't support the request trigger (Fig 1).


Do you mean that DMA trigger via timer match can not be done in hardware on the LPC4370? I really can't understand the picture, I'm sorry.

Best regards,
Andrea

0 Kudos
2,016 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Andrea,

Sorry, I have no idea of the attached file to be erroneously, then make you felt confused.

Let me explain it in details.

As the these figure 1 & figure 1 illuminates, the Memm-to-memory mode doesn't request trigger (Fig 1), then figure 2 has demonstrated the completely process of the Memm-to-memory mode, it works without any peripheral requests.

So you need to trigger the Memm-to-memory transfer via the software instead the original approach.

Hope this is clear.

2017-03-20_11-00-06.jpg

                                                                       Fig 1

2017-03-20_10-49-45.jpg

                                                                         Fig 2


Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------