基于APM32F411 DMA_ADC Handler模式分析及解决

描述

来源:转载自21ic论坛极海半导体专区

最近在编写DMA_ADC例程的过程中出现了一个中断配置的问题,在ADC采集过程中,结合手册进行ADC连续转换模式配置采集,手册上给出需要进行中断配置的信息,但是真实情况不需要进行中断配置也可以进行ADC连续转换采集,因此,我没过滤掉ADC采集中开启中断配置的信息,开启了ADC中断采集,因此这次以APM32F411官方例程中的DMA_ADC例程,复刻了此次出现的问题。

2、基于APM32F411 DMA_ADC例程问题复刻

/*!

* [url=home.php?mod=space&uid=247401]@brief[/url]     ADC Init

*

* @param     None

*

* @retval    None

*/

void ADC_Init(void)

{

GPIO_Config_T gpioConfig;

ADC_Config_T  adcConfig;

/* RCM Enable*/

RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOA);

/* GPIO Configuration */

GPIO_ConfigStructInit(&gpioConfig);

gpioConfig.pin = GPIO_PIN_0;

gpioConfig.mode = GPIO_MODE_AN;

gpioConfig.pupd = GPIO_PUPD_NOPULL;

GPIO_Config(GPIOA, &gpioConfig);

RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);

/* ADC Configuration */

ADC_Reset();

ADC_ConfigStructInit(&adcConfig);

/* Set resolution*/

adcConfig.resolution = ADC_RESOLUTION_12BIT;

/* Set dataAlign*/

adcConfig.dataAlign = ADC_DATA_ALIGN_RIGHT;

/* Set scanDir*/

adcConfig.scanConvMode = DISABLE;

/* Set convMode continous*/

adcConfig.continuousConvMode = ENABLE;

/* Set extTrigEdge*/

adcConfig.extTrigEdge = ADC_EXT_TRIG_EDGE_NONE;

/* Set nbrOfConversion*/

ADC_Config(ADC1, &adcConfig);

ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_0, 1, ADC_SAMPLETIME_112CYCLES);

NVIC_EnableIRQRequest(ADC_IRQn,0x00,0x00);

ADC_EnableInterrupt(ADC1,ADC_INT_EOC);

ADC_EnableDMA(ADC1);

ADC_EnableDMARequest(ADC1);

/* Enable ADC*/

ADC_Enable(ADC1);

ADC_SoftwareStartConv(ADC1);

}

根据上述复刻代码,在ADC_Init()代码配置中,使用NVIC申请中断号,使能中断,但是在中断服务函数中,我并没有进行内容处理。

3、问题定位及疑惑

当出现问题时,因为首先Debug进行单步调试,程序卡死时,出现以下的信息定位:

dma

  当程序出现问题时,我首先定位的信息便是Internal:Mode->Handler,Stack->MSP->0x20000400,同时Debug Faults中,SCB->DFSR寄存器的值为0x00000001。首先,模式由Thread变成Handler,这个变化可以说明当前程序由普通用户运行的代码变成了异常程序处理的代码。其次,看到SCB寄存器的内容,结合内核手册中的一些信息,如下:

dma

  DFSR->HALTED寄存器位置为1,从手册内容表示,CPU被调试器喊停,但被调停是因为什么原因呢?这个需要进一步分析,如下:

dma

DFSR寄存器中HALTED寄存器被置位是因为在NVIC中进行了HALT的请求,然后我回顾了以下程序,在ADC初始化中进行了NVIC的请求,因为程序在ADC进行采集时,会一直跳进中断程序。记录到这里,我已经对问题进行了确认。因为在ADC配置中开启了中断,当中断开启后,请求了HALT,并且CPU响应了这次请求对ADC的中断服务函数进行处理,但我并没有对ADC的中断服务函数进行处理与ADC采集为连续配置模式,因此程序一直处在Handler模式与线程模式下的切换。并且结合.s启动文件可知,如下:

Default_Handler PROC

EXPORT  ADC_IRQHandler                      [WEAK]

当我通过申请使能中断后,MCU会通过传入的中断号,并计算出偏移量,加载到中断向量表中(这个后面计划出一个启动文件分析,到时在细讲)。当MCU相应中断使能时,程序切换至Handler模式时,PC便将这个地址当做入口,跳入中断服务函数并执行。如下图形式(仅举例):

dma

同时,因为我初始的程序并没有对ADC_Handler模式进行定义处理,同时导致MCU在响应中断后进不了中断服务函数,从而一致卡死在汇编语言B.处,类似C语言中的while(1);,从而产生死循环。

注:文章作者在原帖中提供了例程文件,有需要请至原文21ic论坛下载

原文地址:https://bbs.21ic.com/icview-3329454-1-1.html

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分