AnsweredAssumed Answered

HADC and DMA of lpc4370 cannot be interrupted

Question asked by YuLong Li on Apr 20, 2020
Latest reply on Apr 25, 2020 by CHEN CHUANPING

I use GPDMA to transfer HADC data from ADC to memory. The code is the reference of Mr. Benjamin Artes, and I made a small change to the code. But I found that the DMA interrupt could not be triggered. Here is my code. thank you.

 

hadc.c

 

#include "board.h"
#include <stdio.h>

/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/

/* The default example uses DMA. To use the example in an interrutp based
configuration, enable the following definition. */
//#define USE_INTERRUPT_MODE

/* HSADC clock rate used for sampling */
#define HSADC_CLOCK_RATE (80 * 1000000)


static const CHIP_CGU_CLKIN_T adcBaseClkSources[] = {
CLKIN_IRC, /* Usually 12MHz */
CLKIN_CLKIN, /* External clock in rate */
CLKIN_CRYSTAL, /* Usually 12MHz */
CLKIN_AUDIOPLL, /* Unknown, will be 0 if not configured */
CLKIN_MAINPLL /* Usually 204MHz, may be too fast to use with a divider */
};

 

/* Periodic sample rate in Hz */
#define SAMPLERATE (5)

#define HSADC_DMA_READ 8

#define DMA_TRANSFER_SIZE 4095 // max. 4095

#define DMA_CH 7

#define NUM_SAMPLE DMA_TRANSFER_SIZE

uint32_t sample[NUM_SAMPLE];

/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
#define FIFO_SIZE 8
/* Last saved ADC sample for each input */

uint8_t TEST_DATA_8[NUM_SAMPLE*4];

uint16_t j=0,i=0;
uint32_t sts, data, ch=0;

/*****************************************************************************
* Private functions
****************************************************************************/

/* Returns a computed clock rate based on input clock and divider
selection */
static uint32_t getClockRate(int clkIndex, uint32_t maxCGU)
{
uint32_t clkRate;

clkRate = Chip_Clock_GetClockInputHz(adcBaseClkSources[clkIndex]);
clkRate = clkRate / maxCGU;

return clkRate;
}

/*****************************************************************************
* Public functions
****************************************************************************/

 

/**
* @brief Handle interrupt for HSADC peripheral
* @return Nothing
* @note The HSADC IRQ handler is called SPIFI_ADCHS_IRQHandler() on the
* M0 cores. For the M4 core, it's called ADCHS_IRQHandler().
*/
void ADCHS_IRQHandler(void)
{


}

void DMA_IRQHandler (void)
{
DEBUGOUT("aa ");
}
/**
* @brief main routine for HSADC example
* @return Function should not exit
*/
int main(void)
{

uint8_t DGEC = 0xE;

SystemCoreClockUpdate();
Board_Init();//设置调试串口LPC_USART2 与LED状态

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); /*来自DIV_B的ADHCS基本时钟*/

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; //禁用电源关闭模式

LPC_ADCHS-> FIFO_CFG =(8 << 1)/* FIFO_LEVEL大小 */ | (1)/* 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 << 8) /* MATCH 描述符计时器值等于MATC时,转换描述符*/
| (1 << 6) /* BRANCH to First 转换完成后跳转到该表第一个描述符*/;

/* 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*/
| (0x9A << 8) /* MATCH*/
| (0x01 << 6) /* BRANCH to first*/;

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 << 8)
| (DGEC << 4)
| (DGEC);

//未设置阈值寄存器,因为未使用它们
LPC_ADCHS->POWER_CONTROL =(1 << 18)/* BGAP */
|(1 << 17)/*电源 ADC保持供电*/
|(0 << 4) /* DCINNEG在ADC0 No dc bias*/
|(0 << 10)/* DC在ADC0中 No dc bias*/
|(0 << 16)/* 1 =以TWOS输出-0 =以Offset Binary输出*/
|(0x4)/* CRS ,设置ADC速度*/;

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

///////////////////////////////////////////////////// //// DMA设置///////////////////////////////////////////// ///////////////////////
/* 初始化与使能 */
Chip_GPDMA_Init(LPC_GPDMA);

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-终端计数中断屏蔽
// | (0x0 << 16)//锁定:置位时,此位启用锁定传输
// | (0x1 << 18); //进一步忽略src DMA req
LPC_GPDMA-> CH [DMA_CH] .LLI = 0;
NVIC_EnableIRQ(DMA_IRQn);

Chip_HSADC_SWTrigger(LPC_ADCHS);

for(i = 0; i <4094;i ++)
{
; //发出DMA中断,等待采样结束
}
LPC_GPDMA-> CH [DMA_CH] .CONFIG =(0x1 << 0); //启用位,1启用,0禁用

/////////////////////////////////////////////////// /////////////////////////////////////////////////////

//开始DMA与ADC



//需要添加等待DMA完成
for(i = 0; i <4094;i ++)
{
; //发出DMA中断,等待采样结束
}
// Chip_HSADC_FlushFIFO(LPC_ADCHS);
// sts = Chip_HSADC_GetFIFOLevel(LPC_ADCHS);
// Chip_HSADC_DeInit(LPC_ADCHS);
// Chip_GPDMA_DeInit(LPC_GPDMA);

j=0;
for(i=0;i<4095;i++)
{
TEST_DATA_8[j++]=(sample[i]&0xff000000)>>24;
TEST_DATA_8[j++]=(sample[i]&0xff0000)>>16;
TEST_DATA_8[j++]=(sample[i]&0xff00)>>8;
TEST_DATA_8[j++]=sample[i]&0xff;
}
for(i = 0; i <4095*4; i ++)
{
Chip_UART_SendByte(DEBUG_UART,TEST_DATA_8[i]);
while((Chip_UART_ReadLineStatus(DEBUG_UART) & UART_LSR_THRE) == 0);
}
}

Outcomes