LPC82x SCT DMAREQ example

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

LPC82x SCT DMAREQ example

Jump to solution
2,502 Views
nantunes
Contributor I

Hello,

I have been looking for a clear, working example of the LPC824 SCT0 DMAREQ register working without much luck.

By my attempts, I can design a DMA channel that performs its task as long as the trigger is from software or a peripheral request, but once I attempt to wait for the SCT_DMA0 trigger it seems to never activate. In particular:

DMAREQ0 has bit 30 (trigger on L match reload) set.

DMA_ITRIG_INMUX0 is set to 0x02 (SCT_DMA0)

According to my understanding of the documentation this should generate an hardware trigger (on falling edge? - documentation is not clear) on DMA Channel 0 with HWTRIGEN enabled and PERIPHREQEN disabled. But on my code the trigger(s) seem to never arrive and the channel sits idle.

None of the examples I've seen here cover this scenario - using an SCT output to set an ADC capture that in turn issues an DMA request is not the functionality that I'm interested in and that is the most common example.

Interestingly, checked if the MCUXpresso Config Tools could help me prototype the behaviour I'm looking for, but I could not find a way to configure the DMAREQ for an event or the DMA_ITRIG_INMUX (at least on version 11.1.1) for an 82x part. Is this implemented in a later version?

EDIT: Correction, DMA_ITRIG_INMUX registers can be accessed in register pins view.

Best regards,

N. Antunes

Labels (2)
0 Kudos
1 Solution
2,446 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

Regarding how to generate the event based on SCTimer, you can refer to the SDK example

xiangjun_rong_0-1626232806021.png

This is the code to generate event with match mechanism.

#define SCTIMER_CLK_FREQ CLOCK_GetFreq(kCLOCK_Irc)
#define DEMO_FIRST_SCTIMER_OUT kSCTIMER_Out_2
#define DEMO_SECOND_SCTIMER_OUT kSCTIMER_Out_4

int main(void)
{
sctimer_config_t sctimerInfo;
uint32_t eventCounterL, eventCounterH;
uint32_t sctimerClock;
uint32_t matchValueL, matchValueH;

/* Board pin, clock, debug console init */
/* Enable clock of uart0. */
CLOCK_EnableClock(kCLOCK_Uart0);
/* Ser DIV of uart0. */
CLOCK_SetClkDivider(kCLOCK_DivUsartClk, 1U);

BOARD_InitPins();
BOARD_BootClockIRC12M();
BOARD_InitDebugConsole();

/* Enable clock of sct. */

/* Enable clock of sct. */
CLOCK_EnableClock(kCLOCK_Sct);

sctimerClock = SCTIMER_CLK_FREQ;

/* Print a note to terminal */
PRINTF("\r\nSCTimer example to use it in 16-bit mode\r\n");
PRINTF("\r\nThe example shows both 16-bit counters running and toggling an output periodically ");

SCTIMER_GetDefaultConfig(&sctimerInfo);

/* Switch to 16-bit mode */
sctimerInfo.enableCounterUnify = false;

/* Calculate prescaler and match value for Counter L for 100ms interval */
matchValueL = MSEC_TO_COUNT(100U, sctimerClock);
sctimerInfo.prescale_l = matchValueL / 65536;
matchValueL = matchValueL / (sctimerInfo.prescale_l + 1) - 1;

/* Calculate prescaler and match value for Counter H for 200ms interval */
matchValueH = MSEC_TO_COUNT(200U, sctimerClock);
sctimerInfo.prescale_h = matchValueH / 65536;
matchValueH = matchValueH / (sctimerInfo.prescale_h + 1) - 1;

/* Initialize SCTimer module */
SCTIMER_Init(SCT0, &sctimerInfo);

/* Schedule a match event for Counter L every 0.1 seconds */
if (SCTIMER_CreateAndScheduleEvent(SCT0, kSCTIMER_MatchEventOnly, matchValueL, 0, kSCTIMER_Counter_L,
&eventCounterL) == kStatus_Fail)
{
return -1;
}

SCT->DMAREQ0|=1<<eventCounterL;  //Rong wrote

/* Toggle first output when Counter L event occurs */
SCTIMER_SetupOutputToggleAction(SCT0, DEMO_FIRST_SCTIMER_OUT, eventCounterL);

/* Reset Counter L when Counter L event occurs */
SCTIMER_SetupCounterLimitAction(SCT0, kSCTIMER_Counter_L, eventCounterL);

........

}

Hope it can help you

BR

XiangJun Rong

View solution in original post

0 Kudos
9 Replies
2,487 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi, Nuno,

Regarding your question, let's clarify your question clearly. From your description, it appears that you want to use SCT to generate signal to trigger ADC to sample, after the ADC samples is ready, you use DMA to transfer the data from ADC result register to memory, am I right?

If it is the case, you have to use SCT to trigger ADC, then use ADC to trigger DMA, but you can not use SCT to trigger DMA directly.

We have ADC plus DMA example in SDK package, but it use software trigger mode rather than hardware triggering mode, what you have to do is to change the example code so that it uses SCT to trigger ADC.

xiangjun_rong_0-1626142889088.png

 

You have to set the ADC0->SEQ_CTRL[0]|=3<<12;

 

xiangjun_rong_1-1626143032126.png

Regarding the question how to configure the SCT_OUT3, I think it is a bit complex. Pls refer to the SCT example in SDK package.

Hope it can help you

BR

XiangJun Rong

 

 

0 Kudos
2,482 Views
nantunes
Contributor I

Hi XiangJun,

Thank you for the answer. I will try to be as clear as possible.

I am looking for an example of an SCT event triggering a DMA channel on the LPC824, as supported by the DMAREQ registers. No ADC.

Best regards,

Nuno Antunes

0 Kudos
2,475 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

I am sorry for misunderstanding you, now I see you want to use SCT event to trigger DMA directly.

Pls refer to the section:

xiangjun_rong_0-1626161459444.png

 

The SCT->DMAREQ0[DEV_0] bits defines the SCT event source to trigger DMA.

Hope it can help you

BR

XiangJun Rong

 

0 Kudos
2,458 Views
nantunes
Contributor I

HI,

Thank you for your answer. I have set SCT->DMAREQ0[DEV_0], and DMA_ITRIG_INMUX0 register accordingly. But DMA trigger is not registered, DRQ remains 1 after channel set.

I will attempt again to debug the situation, but is there any other rule for successful trigger setup of DEV_0?

For example, can DMAREQ0 be set while the counter is running? Is there a limit for the trigger frequently (right now it's triggering at 1.5Mhz from a 30Mhz system clock)

Best regards,

Nuno Antunes

0 Kudos
2,447 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

Regarding how to generate the event based on SCTimer, you can refer to the SDK example

xiangjun_rong_0-1626232806021.png

This is the code to generate event with match mechanism.

#define SCTIMER_CLK_FREQ CLOCK_GetFreq(kCLOCK_Irc)
#define DEMO_FIRST_SCTIMER_OUT kSCTIMER_Out_2
#define DEMO_SECOND_SCTIMER_OUT kSCTIMER_Out_4

int main(void)
{
sctimer_config_t sctimerInfo;
uint32_t eventCounterL, eventCounterH;
uint32_t sctimerClock;
uint32_t matchValueL, matchValueH;

/* Board pin, clock, debug console init */
/* Enable clock of uart0. */
CLOCK_EnableClock(kCLOCK_Uart0);
/* Ser DIV of uart0. */
CLOCK_SetClkDivider(kCLOCK_DivUsartClk, 1U);

BOARD_InitPins();
BOARD_BootClockIRC12M();
BOARD_InitDebugConsole();

/* Enable clock of sct. */

/* Enable clock of sct. */
CLOCK_EnableClock(kCLOCK_Sct);

sctimerClock = SCTIMER_CLK_FREQ;

/* Print a note to terminal */
PRINTF("\r\nSCTimer example to use it in 16-bit mode\r\n");
PRINTF("\r\nThe example shows both 16-bit counters running and toggling an output periodically ");

SCTIMER_GetDefaultConfig(&sctimerInfo);

/* Switch to 16-bit mode */
sctimerInfo.enableCounterUnify = false;

/* Calculate prescaler and match value for Counter L for 100ms interval */
matchValueL = MSEC_TO_COUNT(100U, sctimerClock);
sctimerInfo.prescale_l = matchValueL / 65536;
matchValueL = matchValueL / (sctimerInfo.prescale_l + 1) - 1;

/* Calculate prescaler and match value for Counter H for 200ms interval */
matchValueH = MSEC_TO_COUNT(200U, sctimerClock);
sctimerInfo.prescale_h = matchValueH / 65536;
matchValueH = matchValueH / (sctimerInfo.prescale_h + 1) - 1;

/* Initialize SCTimer module */
SCTIMER_Init(SCT0, &sctimerInfo);

/* Schedule a match event for Counter L every 0.1 seconds */
if (SCTIMER_CreateAndScheduleEvent(SCT0, kSCTIMER_MatchEventOnly, matchValueL, 0, kSCTIMER_Counter_L,
&eventCounterL) == kStatus_Fail)
{
return -1;
}

SCT->DMAREQ0|=1<<eventCounterL;  //Rong wrote

/* Toggle first output when Counter L event occurs */
SCTIMER_SetupOutputToggleAction(SCT0, DEMO_FIRST_SCTIMER_OUT, eventCounterL);

/* Reset Counter L when Counter L event occurs */
SCTIMER_SetupCounterLimitAction(SCT0, kSCTIMER_Counter_L, eventCounterL);

........

}

Hope it can help you

BR

XiangJun Rong

0 Kudos
2,438 Views
nantunes
Contributor I

Hi,

Thank you for your patience and for providing an example. I will consider this as solved.

Best regards,

Nuno Antunes

0 Kudos
2,269 Views
nantunes
Contributor I

An additional remark to this solution and for anyone facing similar issues in the future:

I was only able to trigger the SCT DMA request correctly when the channel configuration register for the DMA had TRIGPOL set to 1 and TRIGTYPE set to 0 (rising edge triggered).

Best regards,

Nuno Antunes

0 Kudos
2,485 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

This the code to configure SCT to trigger ADC based LPC54114, pls refer to it. You can change the PWM output from SCT_OUT7 to OUT3.

BR

XiangJun Rong

//Only the SCT0_OUT7 signal can trigger ADC for a fixed sampling cycle time
//POI1_4: PIO1_4/ADC0_7(Func=0), PDM1_CLK(Func=1),FC7_RTS_SCL_SSEL1(Func=2),SCT0_OUT7(Func=3), FC3
void SCTimerPWMSetting(void)
{
sctimer_config_t sctimerInfo;
sctimer_pwm_signal_param_t pwmParam;
uint32_t event;
uint32_t sctimerClock;
//enable gated clock
//CLOCK_EnableClock(kCLOCK_Sct0);
CLOCK_EnableClock(kCLOCK_Iocon);
const uint32_t port1_pin4_config = (/* Pin is configured as CTIMER3_MAT3 */
IOCON_PIO_FUNC3 |
/* No addition pin function */
IOCON_PIO_MODE_INACT |
/* Input function is not inverted */
IOCON_PIO_INV_DI |
/* Enables digital function */
IOCON_PIO_DIGITAL_EN |
/* Input filter disabled */
IOCON_PIO_INPFILT_OFF |
/* Standard mode, output slew rate control is enabled */
IOCON_PIO_SLEW_STANDARD |
/* Open drain is disabled */
IOCON_PIO_OPENDRAIN_DI);
/* PORT0 PIN0 (coords: 31) is configured as FC0_RXD_SDA_MOSI */
IOCON_PinMuxSet(IOCON, 1U, 4U, port1_pin4_config);
sctimerClock = SCTIMER_CLK_FREQ;
/* Print a note to terminal */
PRINTF("\r\nSCTimer example to output 2 center-aligned PWM signals\r\n");
PRINTF("\r\nProbe the signal using an oscilloscope");

SCTIMER_GetDefaultConfig(&sctimerInfo);

/* Initialize SCTimer module */
SCTIMER_Init(SCT0, &sctimerInfo);

/* Configure first PWM with frequency 24kHZ from first output */
pwmParam.output = kSCTIMER_Out_7;
pwmParam.level = kSCTIMER_HighTrue;
pwmParam.dutyCyclePercent = 50;
if (SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 2400U, sctimerClock, &event) == kStatus_Fail)
{
return;
}

/* Configure second PWM with different duty cycle but same frequency as before */
// pwmParam.output = DEMO_SECOND_SCTIMER_OUT;
// pwmParam.level = kSCTIMER_LowTrue;
// pwmParam.dutyCyclePercent = 20;
// if (SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 24000U, sctimerClock, &event) == kStatus_Fail)
// {
// return -1;
// }

/* Start the timer */
SCTIMER_StartTimer(SCT0, kSCTIMER_Counter_L);


}

0 Kudos
2,500 Views
nantunes
Contributor I

Also, after reviewing the user manual, why is the register overview claiming DMA_ITRIG_INMUX0 is at 0x40028000 (offset 0x000) :

nantunes_0-1626112613175.png

But the next table caption sets it at 0x400280E0?

nantunes_1-1626112775090.png

The former seems correct according to the CMSIS header.

Best regards,

Nuno Antunes

0 Kudos