LPC43XX HSADC DMA how to

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 
已解决

LPC43XX HSADC DMA how to

跳至解决方案
333 次查看
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);
}

 

 

 

标签 (2)
0 项奖励
回复
1 解答
181 次查看
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 项奖励
回复
3 回复数
304 次查看
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 项奖励
回复
287 次查看
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 项奖励
回复
182 次查看
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 项奖励
回复