LPC43XX HSADC DMA how to

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

LPC43XX HSADC DMA how to

Jump to solution
331 Views
robberpen
Contributor III

Hi

After seup hsadc’s descriptor0, It can sampling data to FIFOOUTPUT register by software trigger.
And set FIFO_LEVEL register to 7. Then it successfully interrupts to ADCHS_IRQHandler().
Based on programming guide, it should also trigger DMA_HSADC_read signal to trigger DMA channel activation.

However, DMA channel 7 never work.(did not copy src:FIFOOUTPUT to dst:Memory)
Is something wrong for DMA setup here? Or how to check/debug this.

 

PS: DMAMUXER8 already set in this case.

LPC_CREG->DMAMUX = (LPC_CREG->DMAMUX | (0x3 << 16)); //16b(DMAMUXER8) = 0x3

 

 

Ref - https://community.nxp.com/t5/LPC-Microcontrollers/DMA-keep-getting-quot-Empty-FIFO-empty-quot-0x8000...
https://community.nxp.com/t5/LPC-Microcontrollers/LPC-Link2-High-Speed-ADC-and-DMA-Interrupt/td-p/15...

  • Setup HSADC is working.

 

	 Chip_HSADC_SetupDescEntry(LPC_ADCHS, 0, 0, (HSADC_DESC_CH(1) |
	 HSADC_DESC_BRANCH_NEXT | HSADC_DESC_MATCH(1) |
	 HSADC_DESC_THRESH_NONE | HSADC_DESC_RESET_TIMER ));

	 Chip_HSADC_SetupDescEntry(LPC_ADCHS, 0, 1, (HSADC_DESC_CH(1) |
	 HSADC_DESC_BRANCH_NEXT | HSADC_DESC_MATCH(1) |
	 HSADC_DESC_THRESH_NONE | HSADC_DESC_RESET_TIMER));

	 Chip_HSADC_SetupDescEntry(LPC_ADCHS, 0, 2, (HSADC_DESC_CH(1) |
	 HSADC_DESC_BRANCH_NEXT | HSADC_DESC_MATCH(1) |
	 HSADC_DESC_THRESH_NONE | HSADC_DESC_RESET_TIMER ));

	 Chip_HSADC_SetupDescEntry(LPC_ADCHS, 0, 3, (HSADC_DESC_CH(1) |
	 HSADC_DESC_BRANCH_NEXT | HSADC_DESC_MATCH(1) |
	 HSADC_DESC_THRESH_NONE | HSADC_DESC_RESET_TIMER ));

	 Chip_HSADC_SetupDescEntry(LPC_ADCHS, 0, 4, (HSADC_DESC_CH(1) |
	 HSADC_DESC_BRANCH_NEXT | HSADC_DESC_MATCH(1) |
	 HSADC_DESC_THRESH_NONE | HSADC_DESC_RESET_TIMER ));

	 Chip_HSADC_SetupDescEntry(LPC_ADCHS, 0, 5, (HSADC_DESC_CH(1) |
	 HSADC_DESC_BRANCH_NEXT | HSADC_DESC_MATCH(1) |
	 HSADC_DESC_THRESH_NONE | HSADC_DESC_RESET_TIMER ));

	 Chip_HSADC_SetupDescEntry(LPC_ADCHS, 0, 6, (HSADC_DESC_CH(1) |
	 HSADC_DESC_BRANCH_NEXT | HSADC_DESC_MATCH(1) |
	 HSADC_DESC_THRESH_NONE | HSADC_DESC_RESET_TIMER ));

	 Chip_HSADC_SetupDescEntry(LPC_ADCHS, 0, 7, (HSADC_DESC_CH(1) |
	 HSADC_DESC_MATCH(1) | HSADC_DESC_THRESH_NONE |HSADC_DESC_BRANCH_FIRST |
	 HSADC_DESC_RESET_TIMER | HSADC_DESC_HALT |HSADC_DESC_INT));

 

 

  • DMA not work

 

static void App_DMA_Init(void)
{
	/* Initialize GPDMA controller */
	Chip_GPDMA_Init(LPC_GPDMA);
	/* Setting GPDMA interrupt */
	NVIC_DisableIRQ(DMA_IRQn);
	NVIC_SetPriority(DMA_IRQn, ((0x01 << 3) | 0x01));
	NVIC_EnableIRQ(DMA_IRQn);
}

void Setup_DMA_J(void) //copy from https://community.nxp.com/t5/LPC-Microcontrollers/DMA-keep-getting-quot-Empty-FIFO-empty-quot-0x8000-from-HSADC/m-p/734753
{
uint8_t DMA_CH = 7
	App_DMA_Init();
	LPC_CREG->DMAMUX = (LPC_CREG->DMAMUX | (0x3 << 16)); //16b(DMAMUXER8) = 0x3
	/* Clear all DMA interrupt and error flag */
	LPC_GPDMA->CONFIG = 0x00;
#if 0 /* PTM duplicated */
	LPC_GPDMA->INTTCCLEAR = 0xFF; //clears channel terminal count interrupt
	LPC_GPDMA->INTERRCLR = 0xFF; //clears channel error interrupt.
#endif
	LPC_GPDMA->CONFIG = 0x01;
	while (!(LPC_GPDMA->CONFIG & 0x01))
		;
	LPC_GPDMA->CH[DMA_CH].SRCADDR = (uint32_t) &LPC_ADCHS->FIFO_OUTPUT[0];
	LPC_GPDMA->CH[DMA_CH].DESTADDR = ((uint32_t) gluData);
	//LPC_GPDMA->CH[DMA_CH].DESTADDR = ((uint32_t) &sample);
	//LPC_GPDMA->CH[DMA_CH].CONTROL = (DMA_TRANSFER_SIZE << 0) // transfer size
	LPC_GPDMA->CH[DMA_CH].CONTROL = (FIFO_OUTPUT_LEVEL << 0)
			| (0x0 << 12) // src burst size
			| (0x0 << 15) // dst burst size
			| (0x2 << 18) // src transfer width
			| (0x2 << 21) // dst transfer width
			| (0x1 << 24) // src AHB master select
			| (0x0 << 25) // dst AHB master select
			| (0x0 << 26) // src increment: 0, src address not increment after each trans
			| (0x1 << 27) // dst increment: 1, dst address increment after each trans
			| (0x1 << 31); // terminal count interrupt enable bit: 1, enabled, (0x0UL << 31); // Terminal count interrupt disabled
	LPC_GPDMA->CH[DMA_CH].CONFIG = (0x1 << 0) // enable bit: 1 enable, 0 disable
	| (HSADC_DMA_READ << 1) // src peripheral: set to 8 - HSADC
			| (0x0 << 6) // dst peripheral: no setting - memory
			| (0x0 << 11) // flow control: peripheral to memory - DMA control
			| (0x1 << 14) // IE - interrupt error mask
			| (0x1 << 15) // ITC - terminal count interrupt mask
			| (0x0 << 16) // lock: when set, this bit enables locked transfer
			| (0x1 << 18); // Halt: 1, enable DMA requests; 0, ignore further src DMA req
	LPC_GPDMA->CH[DMA_CH].LLI = 0;
	NVIC_SetPriority(DMA_IRQn,0x00);
	NVIC_ClearPendingIRQ(DMA_IRQn);
	LPC_GPDMA->CONFIG = 0x01;
	NVIC_EnableIRQ(DMA_IRQn);
}

 

 

 

Labels (2)
0 Kudos
Reply
1 Solution
179 Views
robberpen
Contributor III

Seems 0x06 << 11 is for burst DMA.

I am keep more testing. thanks

	LPC_GPDMA->CH[DMA_CH].CONFIG = (0x1 << 0) // enable bit: 1 enable, 0 ...
	| (0x6 << 11) // flow control: peripheral to memory - DMA control

 

View solution in original post

0 Kudos
Reply
3 Replies
302 Views
robberpen
Contributor III

I can work hsadc with DMA transfer, but I need more future feature by DMA_read REQ signal.

Here some keys need confirm

Based on  48.7.4.1 DMA read 

  • hsadc only support DMA channel 8 for read?
  • My workaround solution is set bit 1 on IRQ handler.

    >LPC_GPDMA->CH[DMA_CH].CONFIG = LPC_GPDMA->CH[DMA_CH].CONFIG |  0x1;

  • But I wand to active DMA by  DMA_read REQ siganl, so I also set DMAMUXER8, But it still not working as I expect that DMA_read signal should be trigger when FIFO_LEVEL or FIFO_FULL occur.
    >LPC_CREG->DMAMUX = (LPC_CREG->DMAMUX | (0x3 << 16));

 

 

void ADCHS_IRQHandler(void) {
	LPC_GPDMA->CH[DMA_CH].CONFIG = LPC_GPDMA->CH[DMA_CH].CONFIG |  0x1;
	Chip_HSADC_ClearIntStatus(LPC_ADCHS, 1, Chip_HSADC_GetIntStatus(LPC_ADCHS, 1) & Chip_HSADC_GetEnabledInts(LPC_ADCHS, 1));
	Chip_HSADC_ClearIntStatus(LPC_ADCHS, 0, Chip_HSADC_GetIntStatus(LPC_ADCHS, 0) & Chip_HSADC_GetEnabledInts(LPC_ADCHS, 0));
}

 

 

2024-08-24 02_02_06-UM10503.png

0 Kudos
Reply
285 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

I suppose that you can use the following code and have a try.

#define TICKRATE_HZ1 (1000) /* 10 ticks per second */

#define DGEC 0xE

#define HSADC_DMA_READ 8

#define DMA_CH 7

#define DMA_TRANSFER_SIZE 1024 // max. 4095

#define NUM_SAMPLE DMA_TRANSFER_SIZE

uint32_t descrip0,descrip1,config;

uint32_t freqHSADC;

 

uint32_t sample[NUM_SAMPLE];

void ADCHS_DMA_init(void)

{

//uint8_t DGEC = 0xE;

////////////////////////////////// ADCHS采样频率设置///// ///////////////////////////////////////////////////// ///////// /*80M*/

//CLK_M4_ADCHS uses BASE_M4_CLK

 

Chip_USB0_Init();/*将USB0 PLL初始化为480 MHz */

 

Chip_Clock_SetDivider(CLK_IDIV_A,CLKIN_USBPLL,2); /*来自USB0PLL的DIV_A源,并将分频器设置为2(支持的最大div值为4)[IN 480 MHz;输出240 MHz */

 

Chip_Clock_SetDivider(CLK_IDIV_B,CLKIN_IDIVA,3); /*来自DIV_A的源DIV_B,[IN 240 MHz;输出80 MHz */

 

Chip_Clock_SetBaseClock(CLK_BASE_ADCHS, CLKIN_IDIVB, true, false); /* Source ADHCS base clock from DIV_B */

 

freqHSADC = Chip_HSADC_GetBaseClockRate(LPC_ADCHS);

 

Chip_Clock_EnableOpts(CLK_MX_ADCHS, true, true, 1);/*启用寄存器时钟*/

 

Chip_Clock_Enable(CLK_ADCHS); /*启用时钟*/

 

 

 

////////////////////////////////// HSADC设置///// ///////////////////////////////////////////////////// /////////

 

/* 中断设置 */

// LPC_ADCHS-> INTS [0] .CLR_EN = 0x7F; //禁用中断0

// LPC_ADCHS-> INTS [0] .CLR_STAT = 0x7F; //清除中断状态

// while(LPC_ADCHS-> INTS [0] .STATUS&0x7D); //等待状态清除,必须排除FIFO_EMPTY

// LPC_ADCHS-> INTS [1] .CLR_EN = 0x7F;

// LPC_ADCHS-> INTS [1] .CLR_STAT = 0x7F;

// while(LPC_ADCHS-> INTS [1] .STATUS&0x1E);

 

/*初始化HSADC */

Chip_RGU_TriggerReset(RGU_ADCHS_RST);//复位HADC

while (Chip_RGU_InReset(RGU_ADCHS_RST)){}

 

LPC_ADCHS-> POWER_DOWN = 0; //禁用电源关闭模式

 

/* FIFO 中断 1, 无 打包模式 */

//Chip_HSADC_SetupFIFO(LPC_ADCHS, 1, false);

 

LPC_ADCHS-> FIFO_CFG =(8 << 1); /* FIFO_LEVEL大小PACKED_READ 数据保存在FIFO的方式,1表示两个采样数据打包存放 */

LPC_ADCHS-> DSCR_STS = (1 << 1)| 0; //设置活动的描述符表与描述符

 

/* 设置描述符表0中的描述符0*/

LPC_ADCHS->DESCRIPTOR[0][0] = (1 << 24) /* RESET_TIMER 复位定时器*/

| (0 << 22) /* THRESH 未添加比较器*/

| (0 << /* MATCH 描述符计时器值等于MATC时,转换描述符*/

| (1 << 6) /* BRANCH to First 转换完成后跳转到该表第一个描述符*/;

descrip0 =LPC_ADCHS->DESCRIPTOR[0][0] ;

/* Set descriptor 1 to take a measurement after 0x9A clocks and branch to first descriptor*/

LPC_ADCHS->DESCRIPTOR[0][1] =(1 << 31) /* UPDATE TABLE*/ //最高位配置不上

| (1 << 24) /* RESET_TIMER*/

| (0 << 22) /* THRESH*/

| (0 << /* MATCH*/

| (0x01 << 6) /* BRANCH to first*/;

descrip1 =LPC_ADCHS->DESCRIPTOR[0][1] ;

LPC_ADCHS-> CONFIG =(0x90 << 6)/*恢复时间,建议值*/

| (0 << 5)/* CHANNEL_ID_EN ,0表示不将通道ID输入到FIFO中*/

| (0x01)/* TRIGGER_MASK 01 表示仅使用软件触发*/;

 

/* CRS设置为0x4,所以SPEED所有DGEC应该被设置为0xE */

LPC_ADCHS-> ADC_SPEED =(DGEC << 20)

| (DGEC << 16)

| (DGEC << 12)

| (DGEC <<

| (DGEC << 4)

| (DGEC);

 

//未设置阈值寄存器,因为未使用它们

LPC_ADCHS->POWER_CONTROL =(1 << 18)/* BGAP */

|(1 << 17)/*电源 ADC保持供电*/

|(0 << 4) /* DCINNEG在ADC0 No dc bias 当 DCINNEG 设置为 0 时,提供 ADCHS_NEG 引脚上的电压(ADCHS 用于真差分模式):*/

|(0 << 10)/* DC在ADC0中 No dc bias*/

|(0 << 16)/* 1 =以TWOS输出-0 =以Offset Binary输出*/

|(0x4)/* CRS ,设置ADC速度*/;

 

 

LPC_ADCHS-> FLUSH = 1; //FIFO刷新

 

///////////////////////////////////////////////////// //// DMA设置///////////////////////////////////////////// ///////////////////////

 

 

NVIC_DisableIRQ(DMA_IRQn);

LPC_GPDMA-> CH [DMA_CH] .CONFIG |=0; //启用位,1启用,0禁用

 

LPC_GPDMA->INTTCCLEAR |= ((1UL <<DMA_CH ) & 0xFF);

LPC_GPDMA->INTERRCLR |= ((1UL <<DMA_CH ) & 0xFF);

 

LPC_GPDMA-> CONFIG = 0x01;

while(!(LPC_GPDMA-> CONFIG&0x01)); //使能

 

/* 描述符寄存器的值仅能通过DMA通道7传递 */

LPC_GPDMA-> CH[DMA_CH].SRCADDR =(uint32_t)&LPC_ADCHS-> FIFO_OUTPUT [0];//DMA源地址

LPC_GPDMA-> CH[DMA_CH].DESTADDR =((uint32_t)&sample);//DMA目标地址

LPC_GPDMA-> CH[DMA_CH].CONTROL =(DMA_TRANSFER_SIZE)//传输大小 最大4095

| (0x0 << 12)// src突发大小

| (0x0 << 15)// dst突发大小

| (0x2 << 18)// src传输宽度,0x2表示以字的形式传输

| (0x2 << 21)// dst传输宽度,0x2表示以字的形式传输

| (0x1 << 24)// src AHB主选择

| (0x0 << 25)// dst AHB主选择

| (0x0 << 26)// src增量:0,每次传输后src地址不递增

| (0x1 << 27)// dst增量:1,每次传输后的dst地址增量

| (0x1 << 31); //终端计数中断使能位:1,使能

 

LPC_GPDMA->CH[DMA_CH].CONFIG = (HSADC_DMA_READ << 1)// src外设:设置为8-HSADC

| (0x0 << 6)// dst外设:无设置-内存

| (0x6 << 11)//流控制:外设-存储器

| (0x1 << 14); // IE-中断错误掩码

//| (0x1 << 15);

 

 

// ITC-终端计数中断屏蔽

//| (0x1 << 0);// enable bit: 1 enable, 0 disable

//| (0x0 << 16)//锁定:置位时,此位启用锁定传输

//| (0x1 << 18); //进一步忽略src DMA req

LPC_CREG->DMAMUX=3<<16; //select HSADC read for DMAMUXPER8

LPC_GPDMA-> CH [DMA_CH] .LLI = 0;

// NVIC_EnableIRQ(DMA_IRQn);

config =LPC_GPDMA-> CH [DMA_CH] .CONFIG;

LPC_GPDMA-> CH [DMA_CH].CONFIG|=(0x1 << 0);

Chip_HSADC_SWTrigger(LPC_ADCHS);//启动ADCHS软件触发

 

//不配置就无法读取到数据,但会覆盖之前的配置

NVIC_SetPriority(DMA_IRQn,0x00);

NVIC_ClearPendingIRQ(DMA_IRQn);

NVIC_EnableIRQ(DMA_IRQn);

 

__asm("cpsie i");

}

 

void DMA_IRQHandler(void)

{

__asm("nop");

//stop hsadc

LPC_GPDMA-> CH [DMA_CH].CONFIG&=~(0x1 << 0);

 

}

Hope it can help you

BR

XiangJun Rong

0 Kudos
Reply
180 Views
robberpen
Contributor III

Seems 0x06 << 11 is for burst DMA.

I am keep more testing. thanks

	LPC_GPDMA->CH[DMA_CH].CONFIG = (0x1 << 0) // enable bit: 1 enable, 0 ...
	| (0x6 << 11) // flow control: peripheral to memory - DMA control

 

0 Kudos
Reply