LPC82x DMA DSTBURSTWRAP behaviour

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

LPC82x DMA DSTBURSTWRAP behaviour

Jump to solution
3,348 Views
nantunes
Contributor I

I am trying to generate a complex PWM using two SCT channels. They have to be synchronized so I am using MATCHREL[1] and MATCHREL[2], and DMA to load the new values sequentially from memory per trigger - this seems to work perfectly for a single register, with DMA0_CFG register set to BURSTPOWER = 0, and no wrap settings (SRCBURSTWRAP and DSTBURSTWRAP set to 0).

However, with BURSTPOWER = 1 (2^1 transfers), DSTBURSTWRAP  = 1, and DMA destination set to MATCHREL[1], two transfers occur, but as far as I could verify only MATCHREL[1] is written twice.

Are there any limitations on the behavior of DSTBURSTWRAP? I assumed that it would use the WIDTH value of the XFERCFG register and increase the destination accordingly, resetting once the burst was completed, but this doesn't seem to be the case. How is the transfer width of the sequential writes decided?

On that note, how does XFERCFG DSTINC value affects DSTBURSTWRAP? With DSTINC set to a value different from 0, I know that at least it writes sequentially to addresses but the wrap functionality goes ignored (as far as I can reason) - at the very least i know it writes to MATCHREL[3] since that controls a different subsystem.

Here is an snippet for the current DMA settings (uses old LPCOpen nomenclature) -  as stated above, to me the end result is double writes to MATCHREL[1]:

#define HRES (104)
(...)
LPC_DMA->SRAMBASE = Chip_DMA_Table;
Chip_DMA_Table[0].dest = (uint32_t) &LPC_SCT->MATCHREL[1].U;
Chip_DMA_Table[0].source = (uint32_t) &scandata[HRES];
(...)
LPC_DMA->DMACH[0].CFG = (1 << 1) | (1 << 4) | (1 << 6) | (1 << 8 )| (0 << 14) | (1 << 15);
LPC_DMA->DMACH[0].XFERCFG = (1 << 0) | (2 << 8 )| (1 << 12) | (0 << 14) | ((HRES-1) << 16);

Labels (3)
0 Kudos
Reply
1 Solution
3,177 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello,

For your case, you can choose not use "Burst Wrap" function.

Just config  BURSTPOWER 0001: Burst size = 2 (21).

config SRCINC to 0, DSTINC to 0x1, WIDTH to 0x02. 

 

BR

Alice

View solution in original post

0 Kudos
Reply
7 Replies
3,289 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello,

Could you please share your project or simple project that can reproduce your issue? If still have not solved.

 

BR

Alice

0 Kudos
Reply
3,275 Views
nantunes
Contributor I

Hi,

Base project isn't very useful as it runs on a custom board.

I've made a small sample that should run on most configurations (apologies in advance for large amounts of magic numbers):

 

#if defined (__USE_LPCOPEN)
#include "chip.h"
#endif

#define HRES (104)

uint32_t scandata[HRES];

void configurePins(void) {
	LPC_SYSCON->SYSAHBCLKCTRL |=  (1 << 6);
	LPC_SYSCON->PRESETCTRL    &= ~(1 << 10);
	LPC_SYSCON->PRESETCTRL    |=  (1 << 10);
	LPC_IOCON->PIO0[10] = 0x1 << 8;
	LPC_IOCON->PIO0[11] = 0x1 << 8;

    LPC_SYSCON->SYSAHBCLKCTRL |= (1<<7);	    /* Enable SWM clock */
    LPC_SWM->PINASSIGN[3] = 0x0fffffffUL;		/* SPI0_SCK */
    LPC_SWM->PINASSIGN[4] = 0xff0e1702UL;		/* SPI0_MOSI, SPI0_MISO, SPI0_SSEL */
    LPC_SWM->PINENABLE0 = 0xfffffe1fUL;			/* (ACMP disabled) SWDIO, XTALIN, XTALOUT, RESET */
    LPC_SWM->PINASSIGN[7] = 0xffffffffUL;		/* SCT0_OUT0 (disabled) */
    LPC_SWM->PINASSIGN[8] = 0xff0b1103UL;		/* SCT0_OUT1, SCT0_OUT2, SCT_OUT3 */
    /* Set outputs: PIO0_23 is MISO, PIO0_13 and PIO0_3 are SCT0_OUT0/1, PIO0_1 is MUX, PIO0_0 is used for debug */
    LPC_GPIO_PORT->DIR[0] |= (1 << 23) | (1 << 17) | (1 << 13) | (1 << 3) | (1 << 1) | 1;
    /* Set outputs: PIO0_10 is control, PIO0_11 is mux select (experimental)*/
    LPC_GPIO_PORT->DIR[0] |= (1 << 10) | (1 << 11);
    /* Set inputs: PIO0_14 is SSEL, PIO0_2 is MOSI, PIO0_15 is SCK */
    LPC_GPIO_PORT->DIR[0] &= ~((1 << 14) | (1 << 2) | (1 << 15));
}

void setupSCT()
{
	LPC_SYSCON->SYSAHBCLKCTRL |= (1<<8);
	LPC_SYSCON->PRESETCTRL |= 0x1 << 8;
	LPC_SCT->CONFIG &= ~(0x1);
	LPC_SCT->MATCHREL[0].L = 17;
	LPC_SCT->MATCHREL[0].H = 17;
	LPC_SCT->MATCHREL[1].L = 20;
	LPC_SCT->MATCHREL[1].H = 0;
	LPC_SCT->MATCHREL[2].L = 20;
	LPC_SCT->MATCHREL[2].H = 0;
	LPC_SCT->MATCHREL[3].L = 0;
	LPC_SCT->MATCHREL[3].H = 8;
	LPC_SCT->DMAREQ0 |= (uint32_t) 1 << 0;
	LPC_SCT->DMAREQ1 |= (uint32_t) 1 << 0;
	LPC_SCT->EV[0].STATE = 0x1;
	LPC_SCT->EV[0].CTRL = (1 << 12);
	LPC_SCT->EV[1].STATE = 0x1;
	LPC_SCT->EV[1].CTRL = 0x1 | (1 << 12);
	LPC_SCT->EV[2].STATE = 0x1;
	LPC_SCT->EV[2].CTRL = 0x1 | (1 << 4) | (1 << 12);
	LPC_SCT->EV[3].STATE = 0x1;
	LPC_SCT->EV[3].CTRL = 0x2 | (1 << 12);
	LPC_SCT->EV[4].STATE = 0x1;
	LPC_SCT->EV[4].CTRL = 0x2 | (1 << 4) | (1 << 12);
	LPC_SCT->EV[5].STATE = 0x1;
	LPC_SCT->EV[5].CTRL = 0x3 | (1 << 12);
	LPC_SCT->EV[6].STATE = 0x1;
	LPC_SCT->EV[6].CTRL = 0x3 | (1 << 4) | (1 << 12);
	LPC_SCT->OUT[1].SET = (0x1 << 2);
	LPC_SCT->OUT[1].CLR = (0x1 << 1);
	LPC_SCT->RES = 3 << 2;
	LPC_SCT->OUT[2].SET = (0x1 << 4);
	LPC_SCT->OUT[2].CLR = (0x1 << 3);
	LPC_SCT->OUT[3].SET = (0x1 << 6);
	LPC_SCT->OUT[3].CLR = (0x1 << 5);
	LPC_SCT->LIMIT_L = 0x1;
	LPC_SCT->LIMIT_H = 0x1;
	LPC_SCT->CTRL_L &= ~(1 << 2);
	LPC_SCT->CTRL_H &= ~(1 << 2);
}

void initDMA(void)
{
	LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 29;
	LPC_SYSCON->PRESETCTRL &= ~(1 << 29);
	LPC_SYSCON->PRESETCTRL |= (1 << 29);
	NVIC_DisableIRQ( DMA_IRQn );
	LPC_DMATRIGMUX->DMA_ITRIG_INMUX[0] = DMATRIG_SCT0_DMA0;
	LPC_DMATRIGMUX->DMA_ITRIG_INMUX[1] = DMATRIG_SCT0_DMA1;
	LPC_SYSCON->PRESETCTRL &= ~(1 << 29);
	LPC_SYSCON->PRESETCTRL |= (1 << 29);
	LPC_DMA->CTRL = 1 << 0;
	LPC_DMA->SRAMBASE = Chip_DMA_Table;
}

void main(void)
{
	configurePins();
	setupSCT();
	initDMA();
	for(int i = 0; i < HRES; i++)
	{
		scandata[i] = (uint32_t) 0x00020001;
	}
	Chip_DMA_Table[0].dest = (uint32_t) &LPC_SCT->MATCHREL[1].U;
	Chip_DMA_Table[0].source = (uint32_t) &scandata[HRES];
	Chip_DMA_Table[0].xfercfg = 0x00000000;

	LPC_DMA->DMACOMMON[0].ENABLECLR = (1 << 0);\
	LPC_DMA->DMACH[0].CFG = (1 << 1) | (1 << 4) | (1 << 6) | (1 << 8 ) | (0 << 14) | (1 << 15);\
	LPC_DMA->DMACH[0].XFERCFG = (1 << 0) | (2 << 8 ) | (1 << 12) | (0 << 14) | ((HRES) << 16);
	LPC_DMA->DMACOMMON[0].ENABLESET = (1 << 0);
	LPC_DMA->DMACOMMON[0].SETVALID = (1 << 0);
	LPC_DMA->DMACOMMON[0].SETTRIG = (1 << 0);
	while(1)
	{
	}
}

 

 

With TRIGBURST set to 1, both SCT_OUT1 and SCT_OUT2 should have the same output. But in this case, SCT_OUT2 remains high as set in setupSCT(). Changing DSTINC to 1 does make both SCT_OUT1 and SCT_OUT2 have the same output, but SCT_OUT3 is also affected (so I assume the DMA is just increasing destination address without wrap).

My goal is simply to transfer the content of scandata[], two writes at a time, to a set of consecutive registers. I can probably manage to do it with two independent DMA transfers but I would like to know why TRIGBURST fails in this case. 

0 Kudos
Reply
3,241 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hell,

Yes, when set DSTBURSTWRAP to 1, meaning that the destination address range for each burst will be the same, not change, for your case, it is  MATCHREL[1].

How about set SRCBURSTWRAP to SRCBURSTWRAP 1, and config  DSTINC  to1.

Alice_Yang_0-1663581230169.png

 

 

BR

Alice

 

0 Kudos
Reply
3,233 Views
nantunes
Contributor I

Hi,

Thank you for the reply.

Considering BURSTPOWER = 1 (2^1), then each triggered transfer with SRCBURSTWRAP = 1 will have scandata[0] and scandata[1]. This is what I understand when the documentation says When enabled, the source data address for the DMA is “wrapped”, meaning that the source address range for each burst will be the same. I am also assuming "range" is a sequential set of addresses/registers. It is also not clear if SRCINC should be set to 1 or 0 for SRCBURSTWRAP to have the expected behavior.

That is also the equivalent of one of my original questions : If DSTINC is set to 1, will this mean the destination address wrap is performed or ignored? Is it part of the "range" calculation at all?

I would be happy to see an example where the destination address range for a burst is a sequential set of registers (in my case MATCHREL[1] and MATCHREL[2]).

0 Kudos
Reply
3,198 Views
nantunes
Contributor I

Hello,

We still are unable to reach the expected behaviour. I would like to have a confirmation this feature functions as described (and the fault is on our side), before we spend resources on building an alternative.

0 Kudos
Reply
3,178 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

Hello,

For your case, you can choose not use "Burst Wrap" function.

Just config  BURSTPOWER 0001: Burst size = 2 (21).

config SRCINC to 0, DSTINC to 0x1, WIDTH to 0x02. 

 

BR

Alice

0 Kudos
Reply
3,144 Views
nantunes
Contributor I

While I do not think this answer addresses my issue, I will accept that it's technically valid for the example I set. No use continuing this discussion.

0 Kudos
Reply