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
已解决! 转到解答。
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.
Fig 1
Fig 2
Have a great day,
Ping
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
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.
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!
-----------------------------------------------------------------------------------------------------------------------
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)
{
}
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.
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
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!
-----------------------------------------------------------------------------------------------------------------------
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().
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!
-----------------------------------------------------------------------------------------------------------------------
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
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.
Fig 1
Fig 2
Have a great day,
Ping
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------